Merge pull request #3158 from yeswalrus/fix-policy-warning

Fix policy warning CMP0054
diff --git a/.gitignore b/.gitignore
index af91412..fdc52bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -134,6 +134,7 @@
 conformance/Protobuf_test_messages/
 conformance/conformance-php
 conformance/conformance-php-c
+conformance/*.class
 
 # php test output
 composer.lock
@@ -167,3 +168,6 @@
 js/node_modules/
 js/testproto_libs1.js
 js/testproto_libs2.js
+
+# Ignore the bazel symlinks
+/bazel-*
diff --git a/.travis.yml b/.travis.yml
index d49e0a7..e7853eb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@
 os:
   - osx
 # The Objective C build needs Xcode 7.0 or later.
-osx_image: xcode8.1
+osx_image: xcode8.3
 script:
   - ./tests.sh $CONFIG
 env:
diff --git a/BUILD b/BUILD
index ccfbe36..b3369b6 100644
--- a/BUILD
+++ b/BUILD
@@ -8,15 +8,35 @@
 # Protobuf Runtime Library
 ################################################################################
 
-COPTS = [
-    "-DHAVE_PTHREAD",
-    "-Wall",
-    "-Wwrite-strings",
-    "-Woverloaded-virtual",
-    "-Wno-sign-compare",
-    "-Wno-unused-function",
+WIN_COPTS = [
+    "/DHAVE_PTHREAD",
+    "/wd4018", # -Wno-sign-compare
+    "/wd4514", # -Wno-unused-function
 ]
 
+COPTS = select({
+    ":windows" : WIN_COPTS,
+    ":windows_msvc" : WIN_COPTS,
+    "//conditions:default": [
+        "-DHAVE_PTHREAD",
+        "-Wall",
+        "-Wwrite-strings",
+        "-Woverloaded-virtual",
+        "-Wno-sign-compare",
+        "-Wno-unused-function",
+    ],
+})
+
+config_setting(
+    name = "windows",
+    values = { "cpu": "x64_windows" },
+)
+
+config_setting(
+    name = "windows_msvc",
+    values = { "cpu": "x64_windows_msvc" },
+)
+
 config_setting(
     name = "android",
     values = {
@@ -60,7 +80,7 @@
     },
 )
 
-IOS_ARM_COPTS = COPTS + [
+IOS_ARM_COPTS = [
     "-DOS_IOS",
     "-miphoneos-version-min=7.0",
     "-arch armv7",
@@ -77,6 +97,7 @@
         "src/google/protobuf/arena.cc",
         "src/google/protobuf/arenastring.cc",
         "src/google/protobuf/extension_set.cc",
+        "src/google/protobuf/generated_message_table_driven_lite.cc",
         "src/google/protobuf/generated_message_util.cc",
         "src/google/protobuf/io/coded_stream.cc",
         "src/google/protobuf/io/zero_copy_stream.cc",
@@ -88,6 +109,7 @@
         "src/google/protobuf/stubs/bytestream.cc",
         "src/google/protobuf/stubs/common.cc",
         "src/google/protobuf/stubs/int128.cc",
+        "src/google/protobuf/stubs/io_win32.cc",
         "src/google/protobuf/stubs/once.cc",
         "src/google/protobuf/stubs/status.cc",
         "src/google/protobuf/stubs/statusor.cc",
@@ -103,8 +125,8 @@
         ":ios_armv7": IOS_ARM_COPTS,
         ":ios_armv7s": IOS_ARM_COPTS,
         ":ios_arm64": IOS_ARM_COPTS,
-        "//conditions:default": COPTS,
-    }),
+        "//conditions:default": [],
+    }) + COPTS,
     includes = ["src/"],
     linkopts = LINK_OPTS,
     visibility = ["//visibility:public"],
@@ -128,6 +150,7 @@
         "src/google/protobuf/extension_set_heavy.cc",
         "src/google/protobuf/field_mask.pb.cc",
         "src/google/protobuf/generated_message_reflection.cc",
+        "src/google/protobuf/generated_message_table_driven.cc",
         "src/google/protobuf/io/gzip_stream.cc",
         "src/google/protobuf/io/printer.cc",
         "src/google/protobuf/io/strtod.cc",
@@ -174,8 +197,8 @@
         ":ios_armv7": IOS_ARM_COPTS,
         ":ios_armv7s": IOS_ARM_COPTS,
         ":ios_arm64": IOS_ARM_COPTS,
-        "//conditions:default": COPTS,
-    }),
+        "//conditions:default": [],
+    }) + COPTS,
     includes = ["src/"],
     linkopts = LINK_OPTS,
     visibility = ["//visibility:public"],
@@ -201,22 +224,24 @@
     visibility = ["//visibility:public"],
 )
 
-RELATIVE_WELL_KNOWN_PROTOS = [
-    # AUTOGEN(well_known_protos)
-    "google/protobuf/any.proto",
-    "google/protobuf/api.proto",
-    "google/protobuf/compiler/plugin.proto",
-    "google/protobuf/compiler/profile.proto",
-    "google/protobuf/descriptor.proto",
-    "google/protobuf/duration.proto",
-    "google/protobuf/empty.proto",
-    "google/protobuf/field_mask.proto",
-    "google/protobuf/source_context.proto",
-    "google/protobuf/struct.proto",
-    "google/protobuf/timestamp.proto",
-    "google/protobuf/type.proto",
-    "google/protobuf/wrappers.proto",
-]
+# Map of all well known protos.
+# name => (include path, imports)
+WELL_KNOWN_PROTO_MAP = {
+    "any" : ("google/protobuf/any.proto", []),
+    "api" : ("google/protobuf/api.proto", ["source_context", "type"]),
+    "compiler_plugin" : ("google/protobuf/compiler/plugin.proto", ["descriptor"]),
+    "descriptor" : ("google/protobuf/descriptor.proto", []),
+    "duration" : ("google/protobuf/duration.proto", []),
+    "empty" : ("google/protobuf/empty.proto", []),
+    "field_mask" : ("google/protobuf/field_mask.proto", []),
+    "source_context" : ("google/protobuf/source_context.proto", []),
+    "struct" : ("google/protobuf/struct.proto", []),
+    "timestamp" : ("google/protobuf/timestamp.proto", []),
+    "type" : ("google/protobuf/type.proto", ["any", "source_context"]),
+    "wrappers" : ("google/protobuf/wrappers.proto", []),
+}
+
+RELATIVE_WELL_KNOWN_PROTOS = [proto[1][0] for proto in WELL_KNOWN_PROTO_MAP.items()]
 
 WELL_KNOWN_PROTOS = ["src/" + s for s in RELATIVE_WELL_KNOWN_PROTOS]
 
@@ -237,6 +262,33 @@
 )
 
 ################################################################################
+# Well Known Types Proto Library Rules
+#
+# These proto_library rules can be used with one of the language specific proto
+# library rules i.e. java_proto_library:
+#
+# java_proto_library(
+#   name = "any_java_proto",
+#   deps = ["@com_google_protobuf//:any_proto],
+# )
+################################################################################
+
+internal_copied_filegroup(
+    name = "_internal_wkt_protos",
+    srcs = WELL_KNOWN_PROTOS,
+    dest = "",
+    strip_prefix = "src",
+    visibility = ["//visibility:hidden"],
+)
+
+[proto_library(
+    name = proto[0] + "_proto",
+    srcs = [proto[1][0]],
+    deps = [dep + "_proto" for dep in proto[1][1]],
+    visibility = ["//visibility:public"],
+    ) for proto in WELL_KNOWN_PROTO_MAP.items()]
+
+################################################################################
 # Protocol Buffers Compiler
 ################################################################################
 
@@ -351,7 +403,6 @@
         "src/google/protobuf/compiler/php/php_generator.cc",
         "src/google/protobuf/compiler/plugin.cc",
         "src/google/protobuf/compiler/plugin.pb.cc",
-        "src/google/protobuf/compiler/profile.pb.cc",
         "src/google/protobuf/compiler/python/python_generator.cc",
         "src/google/protobuf/compiler/ruby/ruby_generator.cc",
         "src/google/protobuf/compiler/subprocess.cc",
@@ -471,6 +522,16 @@
 )
 
 cc_test(
+    name = "win32_test",
+    srcs = ["src/google/protobuf/stubs/io_win32_unittest.cc"],
+    deps = [
+        ":protobuf_lite",
+        "//external:gtest_main",
+    ],
+    tags = ["manual", "windows"],
+)
+
+cc_test(
     name = "protobuf_test",
     srcs = COMMON_TEST_SRCS + [
         # AUTOGEN(test_srcs)
@@ -479,6 +540,7 @@
         "src/google/protobuf/arenastring_unittest.cc",
         "src/google/protobuf/compiler/command_line_interface_unittest.cc",
         "src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc",
+        "src/google/protobuf/compiler/cpp/cpp_move_unittest.cc",
         "src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc",
         "src/google/protobuf/compiler/cpp/cpp_unittest.cc",
         "src/google/protobuf/compiler/cpp/metadata_test.cc",
@@ -516,6 +578,7 @@
         "src/google/protobuf/stubs/bytestream_unittest.cc",
         "src/google/protobuf/stubs/common_unittest.cc",
         "src/google/protobuf/stubs/int128_unittest.cc",
+        "src/google/protobuf/stubs/io_win32_unittest.cc",
         "src/google/protobuf/stubs/once_unittest.cc",
         "src/google/protobuf/stubs/status_test.cc",
         "src/google/protobuf/stubs/statusor_test.cc",
@@ -552,7 +615,6 @@
         # Files for csharp_bootstrap_unittest.cc.
         "conformance/**/*",
         "csharp/src/**/*",
-        "examples/**/*",
     ]),
     includes = [
         "src/",
@@ -580,7 +642,7 @@
     ]) + [
         ":gen_well_known_protos_java",
     ],
-    javacopts = ["-source 6"],
+    javacopts = ["-source 6", "-target 6"],
     visibility = ["//visibility:public"],
 )
 
@@ -589,6 +651,7 @@
     srcs = glob([
         "java/util/src/main/java/com/google/protobuf/util/*.java",
     ]),
+    javacopts = ["-source 6", "-target 6"],
     visibility = ["//visibility:public"],
     deps = [
         "protobuf_java",
diff --git a/CHANGES.txt b/CHANGES.txt
index ccc8ff9..c83da2d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,135 @@
+2017-08-14 version 3.4.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+  Planned Future Changes
+  * There are some changes that are not included in this release but are planned
+    for the near future
+      - Preserve unknown fields in proto3: We are going to bring unknown fields
+        back into proto3. In this release, some languages start to support
+        preserving unknown fields in proto3, controlled by flags/options. Some
+        languages also introduce explicit APIs to drop unknown fields for
+        migration. Please read the change log sections by languages for details.
+        For general timeline and plan:
+
+          https://docs.google.com/document/d/1KMRX-G91Aa-Y2FkEaHeeviLRRNblgIahbsk4wA14gRk/view
+
+        For issues and discussions:
+
+          https://github.com/google/protobuf/issues/272
+
+      - Make C++ implementation C++11 only: we plan to require C++11 to build
+        protobuf code starting from 3.5.0 or 3.6.0 release, after unknown fields
+        semantic changes are finished. Please join this
+        github issue:
+
+          https://github.com/google/protobuf/issues/2780
+
+        to provide your feedback.
+
+  General
+  * Extension ranges now accept options and are customizable.
+  * "reserve" keyword now supports “max” in field number ranges,
+    e.g.  reserve 1000 to max;
+
+  C++
+  * Proto3 messages are now able to preserve unknown fields. The default
+    behavior is still to drop unknowns, which will be flipped in a future
+    release. If you rely on unknowns fields being dropped. Please use
+    Message::DiscardUnknownFields() explicitly.
+  * Packable proto3 fields are now packed by default in serialization.
+  * Following C++11 features are introduced when C++11 is available:
+      - move-constructor and move-assignment are introduced to messages
+      - Repeated fields constructor now takes std::initializer_list
+      - rvalue setters are introduced for string fields
+  * Experimental Table-Driven parsing and serialization available to test. To
+    enable it, pass in table_driven_parsing table_driven_serialization protoc
+    generator flags for C++
+
+      $ protoc --cpp_out=table_driven_parsing,table_driven_serialization:./ \
+        test.proto
+
+  * lite generator parameter supported by the generator. Once set, all generated
+    files, use lite runtime regardless of the optimizer_for setting in the
+    .proto file.
+  * Various optimizations to make C++ code more performant on PowerPC platform
+  * Fixed maps data corruption when the maps are modified by both reflection API
+    and generated API.
+  * Deterministic serialization on maps reflection now uses stable sort.
+  * file() accessors are introduced to various *Descriptor classes to make
+    writing template function easier.
+  * ByteSize() and SpaceUsed() are deprecated.Use ByteSizeLong() and
+    SpaceUsedLong() instead
+  * Consistent hash function is used for maps in DEBUG and NDEBUG build.
+  * "using namespace std" is removed from stubs/common.h
+  * Various performance optimizations and bug fixes
+
+  Java
+  * Introduced new parser API DiscardUnknownFieldsParser in preparation of
+    proto3 unknown fields preservation change. Users who want to drop unknown
+    fields should migrate to use this new parser API. For example:
+
+      Parser<Foo> parser = DiscardUnknownFieldsParser.wrap(Foo.parser());
+      Foo foo = parser.parseFrom(input);
+
+  * Introduced new TextFormat API printUnicodeFieldValue() that prints field
+    value without escaping unicode characters.
+  * Added Durations.compare(Duration, Duration) and
+    Timestamps.compare(Timestamp, Timestamp).
+  * JsonFormat now accepts base64url encoded bytes fields.
+  * Optimized CodedInputStream to do less copies when parsing large bytes
+    fields.
+  * Optimized TextFormat to allocate less memory when printing.
+
+  Python
+  * SerializeToString API is changed to SerializeToString(self, **kwargs),
+    deterministic parameter is accepted for deterministic serialization.
+  * Added sort_keys parameter in json format to make the output deterministic.
+  * Added indent parameter in json format.
+  * Added extension support in json format.
+  * Added __repr__ support for repeated field in cpp implementation.
+  * Added file in FieldDescriptor.
+  * Added pretty-print filter to text format.
+  * Services and method descriptors are always printed even if generic_service
+    option is turned off.
+  * Note: AppEngine 2.5 is deprecated on June 2017 that AppEngine 2.5 will
+    never update protobuf runtime. Users who depend on AppEngine 2.5 should use
+    old protoc.
+  
+  PHP
+  * Support PHP generic services. Specify file option php_generic_service=true
+    to enable generating service interface.
+  * Message, repeated and map fields setters take value instead of reference.
+  * Added map iterator in c extension.
+  * Support json  encode/decode.
+  * Added more type info in getter/setter phpdoc
+  * Fixed the problem that c extension and php implementation cannot be used
+    together.
+  * Added file option php_namespace to use custom php namespace instead of
+    package.
+  * Added fluent setter.
+  * Added descriptor API in runtime for custom encode/decode.
+  * Various bug fixes.
+
+  Objective-C
+  * Fix for GPBExtensionRegistry copying and add tests.
+  * Optimize GPBDictionary.m codegen to reduce size of overall library by 46K
+    per architecture.
+  * Fix some cases of reading of 64bit map values.
+  * Properly error on a tag with field number zero.
+  * Preserve unknown fields in proto3 syntax files.
+  * Document the exceptions on some of the writing apis.
+
+  C#
+  * Implemented IReadOnlyDictionary<K,V> in MapField<K,V>
+  * Added TryUnpack method for Any message in addition to Unpack.
+  * Converted C# projects to MSBuild (csproj) format.
+
+  Ruby
+  * Several bug fixes.
+
+  Javascript
+  * Added support of field option js_type. Now one can specify the JS type of a
+    64-bit integer field to be string in the generated code by adding option
+    [jstype = JS_STRING] on the field.
+
 2017-04-05 version 3.3.0 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
   Planned Future Changes
   * There are some changes that are not included in this release but are
diff --git a/Makefile.am b/Makefile.am
index 3c3ca13..89e3700 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -207,6 +207,7 @@
   java/core/src/main/java/com/google/protobuf/ByteString.java                      \
   java/core/src/main/java/com/google/protobuf/CodedInputStream.java                \
   java/core/src/main/java/com/google/protobuf/CodedOutputStream.java               \
+  java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java      \
   java/core/src/main/java/com/google/protobuf/Descriptors.java                     \
   java/core/src/main/java/com/google/protobuf/DoubleArrayList.java                 \
   java/core/src/main/java/com/google/protobuf/DynamicMessage.java                  \
@@ -281,6 +282,7 @@
   java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java           \
   java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java             \
   java/core/src/test/java/com/google/protobuf/DescriptorsTest.java                 \
+  java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java        \
   java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java             \
   java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java              \
   java/core/src/test/java/com/google/protobuf/EnumTest.java                        \
@@ -317,6 +319,7 @@
   java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java        \
   java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java              \
   java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java              \
+  java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java          \
   java/core/src/test/java/com/google/protobuf/TestUtil.java                        \
   java/core/src/test/java/com/google/protobuf/TestUtilLite.java                    \
   java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java     \
@@ -597,76 +600,108 @@
   php/ext/google/protobuf/upb.c                                       \
   php/ext/google/protobuf/protobuf.c                                  \
   php/src/phpdoc.dist.xml                                             \
+  php/src/Google/Protobuf/Any.php                                     \
+  php/src/Google/Protobuf/Descriptor.php                              \
+  php/src/Google/Protobuf/DescriptorPool.php                          \
+  php/src/Google/Protobuf/Duration.php                                \
+  php/src/Google/Protobuf/EnumDescriptor.php                          \
+  php/src/Google/Protobuf/EnumValueDescriptor.php                     \
+  php/src/Google/Protobuf/FieldDescriptor.php                         \
+  php/src/Google/Protobuf/OneofDescriptor.php                         \
+  php/src/Google/Protobuf/Timestamp.php                               \
+  php/src/Google/Protobuf/Internal/CodedInputStream.php               \
+  php/src/Google/Protobuf/Internal/CodedOutputStream.php              \
   php/src/Google/Protobuf/Internal/DescriptorPool.php                 \
-  php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php              \
-  php/src/Google/Protobuf/Internal/OneofField.php                     \
-  php/src/Google/Protobuf/Internal/MessageOptions.php                 \
-  php/src/Google/Protobuf/Internal/FileDescriptorProto.php            \
-  php/src/Google/Protobuf/Internal/MapEntry.php                       \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
-  php/src/Google/Protobuf/Internal/InputStream.php                    \
-  php/src/Google/Protobuf/Internal/UninterpretedOption.php            \
-  php/src/Google/Protobuf/Internal/ServiceOptions.php                 \
-  php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php \
-  php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php         \
-  php/src/Google/Protobuf/Internal/OneofDescriptorProto.php           \
-  php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php   \
-  php/src/Google/Protobuf/Internal/OutputStream.php                   \
-  php/src/Google/Protobuf/Internal/MessageBuilderContext.php          \
-  php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php       \
-  php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php       \
-  php/src/Google/Protobuf/Internal/DescriptorProto.php                \
-  php/src/Google/Protobuf/Internal/MapField.php                       \
-  php/src/Google/Protobuf/Internal/MethodDescriptorProto.php          \
   php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php \
   php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php  \
-  php/src/Google/Protobuf/Internal/RepeatedField.php                  \
-  php/src/Google/Protobuf/Internal/EnumValueOptions.php               \
-  php/src/Google/Protobuf/Internal/MethodOptions.php                  \
-  php/src/Google/Protobuf/Internal/OneofOptions.php                   \
-  php/src/Google/Protobuf/Internal/Message.php                        \
-  php/src/Google/Protobuf/Internal/FileOptions.php                    \
-  php/src/Google/Protobuf/Internal/FileDescriptorSet.php              \
+  php/src/Google/Protobuf/Internal/DescriptorProto.php                \
+  php/src/Google/Protobuf/Internal/Descriptor.php                     \
+  php/src/Google/Protobuf/Internal/EnumBuilderContext.php             \
+  php/src/Google/Protobuf/Internal/EnumDescriptor.php                 \
   php/src/Google/Protobuf/Internal/EnumDescriptorProto.php            \
-  php/src/Google/Protobuf/Internal/GPBWire.php                        \
+  php/src/Google/Protobuf/Internal/EnumOptions.php                    \
+  php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php       \
+  php/src/Google/Protobuf/Internal/EnumValueOptions.php               \
   php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php     \
-  php/src/Google/Protobuf/Internal/FieldOptions.php                   \
-  php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php   \
+  php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
+  php/src/Google/Protobuf/Internal/FieldDescriptor.php                \
   php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php      \
-  php/src/Google/Protobuf/Internal/GPBType.php                        \
+  php/src/Google/Protobuf/Internal/FieldOptions_CType.php             \
   php/src/Google/Protobuf/Internal/FieldOptions_JSType.php            \
+  php/src/Google/Protobuf/Internal/FieldOptions.php                   \
+  php/src/Google/Protobuf/Internal/FileDescriptorProto.php            \
+  php/src/Google/Protobuf/Internal/FileDescriptorSet.php              \
+  php/src/Google/Protobuf/Internal/FileDescriptor.php                 \
+  php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php       \
+  php/src/Google/Protobuf/Internal/FileOptions.php                    \
+  php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php   \
+  php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php              \
+  php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php       \
+  php/src/Google/Protobuf/Internal/GPBDecodeException.php             \
+  php/src/Google/Protobuf/Internal/GPBJsonWire.php                    \
+  php/src/Google/Protobuf/Internal/GPBLabel.php                       \
+  php/src/Google/Protobuf/Internal/GPBType.php                        \
+  php/src/Google/Protobuf/Internal/GPBUtil.php                        \
+  php/src/Google/Protobuf/Internal/GPBWireType.php                    \
+  php/src/Google/Protobuf/Internal/GPBWire.php                        \
+  php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php       \
+  php/src/Google/Protobuf/Internal/MapEntry.php                       \
+  php/src/Google/Protobuf/Internal/MapFieldIter.php                   \
+  php/src/Google/Protobuf/Internal/MapField.php                       \
+  php/src/Google/Protobuf/Internal/MessageBuilderContext.php          \
+  php/src/Google/Protobuf/Internal/MessageOptions.php                 \
+  php/src/Google/Protobuf/Internal/Message.php                        \
+  php/src/Google/Protobuf/Internal/MethodDescriptorProto.php          \
+  php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php \
+  php/src/Google/Protobuf/Internal/MethodOptions.php                  \
+  php/src/Google/Protobuf/Internal/OneofDescriptorProto.php           \
+  php/src/Google/Protobuf/Internal/OneofDescriptor.php                \
+  php/src/Google/Protobuf/Internal/OneofField.php                     \
+  php/src/Google/Protobuf/Internal/OneofOptions.php                   \
+  php/src/Google/Protobuf/Internal/RawInputStream.php                 \
+  php/src/Google/Protobuf/Internal/RepeatedFieldIter.php              \
+  php/src/Google/Protobuf/Internal/RepeatedField.php                  \
+  php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php         \
+  php/src/Google/Protobuf/Internal/ServiceOptions.php                 \
   php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php        \
   php/src/Google/Protobuf/Internal/SourceCodeInfo.php                 \
-  php/src/Google/Protobuf/Internal/EnumOptions.php                    \
-  php/src/Google/Protobuf/Internal/GPBLabel.php                       \
-  php/src/Google/Protobuf/Internal/EnumBuilderContext.php             \
-  php/src/Google/Protobuf/Internal/GPBUtil.php                        \
-  php/src/Google/Protobuf/Internal/FieldOptions_CType.php             \
-  php/src/Google/Protobuf/Internal/GPBDecodeException.php             \
-  php/src/Google/Protobuf/descriptor.php                              \
+  php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php   \
+  php/src/Google/Protobuf/Internal/UninterpretedOption.php            \
+  php/src/GPBMetadata/Google/Protobuf/Any.php                         \
+  php/src/GPBMetadata/Google/Protobuf/Duration.php                    \
+  php/src/GPBMetadata/Google/Protobuf/Timestamp.php                   \
   php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php         \
   php/tests/array_test.php                                            \
   php/tests/autoload.php                                              \
   php/tests/compatibility_test.sh                                     \
+  php/tests/descriptors_test.php                                      \
   php/tests/encode_decode_test.php                                    \
   php/tests/gdb_test.sh                                               \
   php/tests/generated_class_test.php                                  \
+  php/tests/generated_phpdoc_test.php                                 \
+  php/tests/generated_service_test.php                                \
   php/tests/map_field_test.php                                        \
   php/tests/memory_leak_test.php                                      \
   php/tests/php_implementation_test.php                               \
+  php/tests/proto/test_descriptors.proto                              \
+  php/tests/proto/test_empty_php_namespace.proto                      \
   php/tests/proto/test_import_descriptor_proto.proto                  \
   php/tests/proto/test_include.proto                                  \
   php/tests/proto/test.proto                                          \
-  php/tests/proto/test_prefix.proto                                   \
   php/tests/proto/test_no_namespace.proto                             \
+  php/tests/proto/test_php_namespace.proto                            \
+  php/tests/proto/test_prefix.proto                                   \
+  php/tests/proto/test_service.proto                                  \
+  php/tests/proto/test_service_namespace.proto                        \
   php/tests/test.sh                                                   \
   php/tests/test_base.php                                             \
   php/tests/test_util.php                                             \
   php/tests/well_known_test.php                                       \
+  php/tests/undefined_test.php                                        \
   php/README.md                                                       \
-  php/phpunit.xml                                                     \
   php/composer.json                                                   \
   php/generate_descriptor_protos.sh                                   \
+  php/phpunit.xml                                                     \
   composer.json
 
 python_EXTRA_DIST=                                                           \
@@ -730,6 +765,7 @@
   python/google/protobuf/json_format.py                                      \
   python/google/protobuf/message.py                                          \
   python/google/protobuf/message_factory.py                                  \
+  python/google/protobuf/python_protobuf.h                                   \
   python/google/protobuf/proto_builder.py                                    \
   python/google/protobuf/pyext/README                                        \
   python/google/protobuf/pyext/__init__.py                                   \
@@ -759,13 +795,13 @@
   python/google/protobuf/pyext/repeated_scalar_container.h                   \
   python/google/protobuf/pyext/safe_numerics.h                               \
   python/google/protobuf/pyext/scoped_pyobject_ptr.h                         \
-  python/google/protobuf/python_protobuf.h                                   \
   python/google/protobuf/reflection.py                                       \
   python/google/protobuf/service.py                                          \
   python/google/protobuf/service_reflection.py                               \
   python/google/protobuf/symbol_database.py                                  \
   python/google/protobuf/text_encoding.py                                    \
   python/google/protobuf/text_format.py                                      \
+  python/release.sh                                                          \
   python/mox.py                                                              \
   python/setup.cfg                                                           \
   python/setup.py                                                            \
@@ -885,6 +921,27 @@
   js/compatibility_tests/v3.0.0/testempty.proto                        \
   js/compatibility_tests/v3.0.0/test.proto                             \
   js/compatibility_tests/v3.0.0/test.sh                                \
+  js/compatibility_tests/v3.1.0/testempty.proto                        \
+  js/compatibility_tests/v3.1.0/testbinary.proto                       \
+  js/compatibility_tests/v3.1.0/test5.proto                            \
+  js/compatibility_tests/v3.1.0/test4.proto                            \
+  js/compatibility_tests/v3.1.0/test3.proto                            \
+  js/compatibility_tests/v3.1.0/test2.proto                            \
+  js/compatibility_tests/v3.1.0/test.proto                             \
+  js/compatibility_tests/v3.1.0/proto3_test.proto                      \
+  js/compatibility_tests/v3.1.0/proto3_test.js                         \
+  js/compatibility_tests/v3.1.0/message_test.js                        \
+  js/compatibility_tests/v3.1.0/maps_test.js                           \
+  js/compatibility_tests/v3.1.0/debug_test.js                          \
+  js/compatibility_tests/v3.1.0/data.proto                             \
+  js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto             \
+  js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto             \
+  js/compatibility_tests/v3.1.0/binary/writer_test.js                  \
+  js/compatibility_tests/v3.1.0/binary/utils_test.js                   \
+  js/compatibility_tests/v3.1.0/binary/reader_test.js                  \
+  js/compatibility_tests/v3.1.0/binary/proto_test.js                   \
+  js/compatibility_tests/v3.1.0/binary/decoder_test.js                 \
+  js/compatibility_tests/v3.1.0/binary/arith_test.js                   \
   js/data.proto                                                        \
   js/debug.js                                                          \
   js/debug_test.js                                                     \
@@ -938,25 +995,31 @@
   editors/README.txt                     \
   editors/proto.vim                      \
   editors/protobuf-mode.el               \
-  examples/CMakeLists.txt                \
-  examples/README.txt                    \
-  examples/Makefile                      \
-  examples/addressbook.proto             \
-  examples/add_person.cc                 \
-  examples/add_person.go                 \
-  examples/add_person_test.go            \
-  examples/list_people.cc                \
-  examples/list_people.go                \
   examples/AddPerson.java                \
+  examples/BUILD                         \
   examples/CMakeLists.txt                \
   examples/ListPeople.java               \
+  examples/Makefile                      \
+  examples/README.md                     \
+  examples/WORKSPACE                     \
+  examples/add_person.cc                 \
+  examples/add_person.go                 \
   examples/add_person.py                 \
+  examples/add_person_test.go            \
+  examples/addressbook.proto             \
+  examples/list_people.cc                \
+  examples/list_people.go                \
   examples/list_people.py                \
   examples/list_people_test.go           \
   protobuf.bzl                           \
+  python/release/wheel/build_wheel_manylinux.sh  \
+  python/release/wheel/Dockerfile                \
+  python/release/wheel/protobuf_optimized_pip.sh \
+  python/release/wheel/README.md         \
   six.BUILD                              \
   util/python/BUILD
 
+
 # Deletes all the files generated by autogen.sh.
 MAINTAINERCLEANFILES =   \
   aclocal.m4             \
diff --git a/Protobuf.podspec b/Protobuf.podspec
index 649f3ae..88bd5b7 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -5,7 +5,7 @@
 # dependent projects use the :git notation to refer to the library.
 Pod::Spec.new do |s|
   s.name     = 'Protobuf'
-  s.version  = '3.3.0'
+  s.version  = '3.4.0'
   s.summary  = 'Protocol Buffers v.3 runtime library for Objective-C.'
   s.homepage = 'https://github.com/google/protobuf'
   s.license  = '3-Clause BSD License'
@@ -36,6 +36,7 @@
 
   s.ios.deployment_target = '7.0'
   s.osx.deployment_target = '10.9'
+  s.tvos.deployment_target = '9.0'
   s.watchos.deployment_target = '2.0'
   s.requires_arc = false
 end
diff --git a/README.md b/README.md
index e456863..3a4e6ed 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@
 If you are looking for an old version that is not available in the release
 page, check out the maven repo here:
 
-  [http://repo1.maven.org/maven2/com/google/protobuf/protoc/](http://repo1.maven.org/maven2/com/google/protobuf/protoc/)
+  [https://repo1.maven.org/maven2/com/google/protobuf/protoc/](https://repo1.maven.org/maven2/com/google/protobuf/protoc/)
 
 These pre-built binaries are only provided for released versions. If you want
 to use the github master version at HEAD, or you need to modify protobuf code,
@@ -68,9 +68,19 @@
 | PHP                                  | [php](php)                                                  |
 | Dart                                 | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) |
 
+Quick Start
+-----------
 
-Usage
------
+The best way to learn how to use protobuf is to follow the tutorials in our
+developer guide:
+
+https://developers.google.com/protocol-buffers/docs/tutorials
+
+If you want to learn from code examples, take a look at the examples in the
+[examples](examples) directory.
+
+Documentation
+-------------
 
 The complete documentation for Protocol Buffers is available via the
 web at:
diff --git a/WORKSPACE b/WORKSPACE
index 2a49e37..1066a0e 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,3 +1,5 @@
+workspace(name = "com_google_protobuf")
+
 new_git_repository(
     name = "googletest",
     build_file = "gmock.BUILD",
diff --git a/autogen.sh b/autogen.sh
index 9f26642..9560aaf 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -35,7 +35,9 @@
   unzip -q release-1.7.0.zip
   rm release-1.7.0.zip
   mv googlemock-release-1.7.0 gmock
+fi
 
+if test ! -e gmock/gtest; then
   curl $curlopts -L -O https://github.com/google/googletest/archive/release-1.7.0.zip
   unzip -q release-1.7.0.zip
   rm release-1.7.0.zip
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in
index 245e917..deb6de3 100644
--- a/cmake/extract_includes.bat.in
+++ b/cmake/extract_includes.bat.in
@@ -18,6 +18,7 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h" include\google\protobuf\any.pb.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h" include\google\protobuf\api.pb.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h" include\google\protobuf\arena.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena_impl.h" include\google\protobuf\arena_impl.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h" include\google\protobuf\arenastring.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h" include\google\protobuf\compiler\code_generator.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h" include\google\protobuf\compiler\command_line_interface.h
@@ -36,7 +37,6 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\php\php_generator.h" include\google\protobuf\compiler\php\php_generator.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h" include\google\protobuf\compiler\plugin.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h" include\google\protobuf\compiler\plugin.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\profile.pb.h" include\google\protobuf\compiler\profile.pb.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h" include\google\protobuf\compiler\python\python_generator.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h" include\google\protobuf\compiler\ruby\ruby_generator.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h" include\google\protobuf\descriptor.h
@@ -50,6 +50,7 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h" include\google\protobuf\generated_enum_reflection.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h" include\google\protobuf\generated_enum_util.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h" include\google\protobuf\generated_message_reflection.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_table_driven.h" include\google\protobuf\generated_message_table_driven.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h
@@ -70,6 +71,7 @@
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h" include\google\protobuf\message.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h" include\google\protobuf\message_lite.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h" include\google\protobuf\metadata.h
+copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata_lite.h" include\google\protobuf\metadata_lite.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h" include\google\protobuf\reflection.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" include\google\protobuf\reflection_ops.h
 copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h
diff --git a/cmake/install.cmake b/cmake/install.cmake
index 28dc90d..441bf55 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -1,5 +1,10 @@
 include(GNUInstallDirs)
 
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protobuf.pc.cmake
+               ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/protobuf-lite.pc.cmake
+               ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc @ONLY)
+
 foreach(_library
   libprotobuf-lite
   libprotobuf
@@ -17,6 +22,8 @@
 install(TARGETS protoc EXPORT protobuf-targets
   RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
 
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
+
 file(STRINGS extract_includes.bat.in _extract_strings
   REGEX "^copy")
 foreach(_extract_string ${_extract_strings})
diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake
index 1ee9b9c..9e1fab0 100644
--- a/cmake/libprotobuf-lite.cmake
+++ b/cmake/libprotobuf-lite.cmake
@@ -2,6 +2,7 @@
   ${protobuf_source_dir}/src/google/protobuf/arena.cc
   ${protobuf_source_dir}/src/google/protobuf/arenastring.cc
   ${protobuf_source_dir}/src/google/protobuf/extension_set.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven_lite.cc
   ${protobuf_source_dir}/src/google/protobuf/generated_message_util.cc
   ${protobuf_source_dir}/src/google/protobuf/io/coded_stream.cc
   ${protobuf_source_dir}/src/google/protobuf/io/zero_copy_stream.cc
@@ -13,6 +14,7 @@
   ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/once.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 030924d..72db915 100644
--- a/cmake/libprotobuf.cmake
+++ b/cmake/libprotobuf.cmake
@@ -13,6 +13,7 @@
   ${protobuf_source_dir}/src/google/protobuf/extension_set_heavy.cc
   ${protobuf_source_dir}/src/google/protobuf/field_mask.pb.cc
   ${protobuf_source_dir}/src/google/protobuf/generated_message_reflection.cc
+  ${protobuf_source_dir}/src/google/protobuf/generated_message_table_driven.cc
   ${protobuf_source_dir}/src/google/protobuf/io/gzip_stream.cc
   ${protobuf_source_dir}/src/google/protobuf/io/printer.cc
   ${protobuf_source_dir}/src/google/protobuf/io/strtod.cc
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index 5122654..9f2aa0c 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -88,7 +88,6 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/php/php_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.cc
-  ${protobuf_source_dir}/src/google/protobuf/compiler/profile.pb.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/python/python_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.cc
@@ -104,7 +103,6 @@
   ${protobuf_source_dir}/src/google/protobuf/compiler/parser.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/plugin.pb.h
-  ${protobuf_source_dir}/src/google/protobuf/compiler/profile.pb.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.h
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_enum.h
diff --git a/cmake/protobuf-config-version.cmake.in b/cmake/protobuf-config-version.cmake.in
index fda748b..3fa0176 100644
--- a/cmake/protobuf-config-version.cmake.in
+++ b/cmake/protobuf-config-version.cmake.in
@@ -17,30 +17,32 @@
 
 set(PACKAGE_VERSION_COMPATIBLE TRUE) #Assume true until shown otherwise
 
-if(NOT PACKAGE_FIND_VERSION_MAJOR EQUAL "@protobuf_VERSION_MAJOR@")
-  set(PACKAGE_VERSION_COMPATIBLE FALSE)
-elseif(PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
-  set(PACKAGE_VERSION_COMPATIBLE FALSE)
-elseif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
-  # Do not match prerelease versions to non-prerelease version requests.
-  if(NOT "@protobuf_VERSION_PRERELEASE@" STREQUAL "" AND PACKAGE_FIND_VERSION_PRERELEASE STREQUAL "")
-    message(AUTHOR_WARNING "To use this prerelease version of ${PACKAGE_FIND_NAME}, set ${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE to '@protobuf_VERSION_PRERELEASE@' or greater.")
+if(PACKAGE_FIND_VERSION) #Only perform version checks if one is given
+  if(NOT PACKAGE_FIND_VERSION_MAJOR EQUAL "@protobuf_VERSION_MAJOR@")
     set(PACKAGE_VERSION_COMPATIBLE FALSE)
-  endif()
+  elseif(PACKAGE_FIND_VERSION VERSION_GREATER PACKAGE_VERSION)
+    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+  elseif(PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
+    # Do not match prerelease versions to non-prerelease version requests.
+      if(NOT "@protobuf_VERSION_PRERELEASE@" STREQUAL "" AND PACKAGE_FIND_VERSION_PRERELEASE STREQUAL "")
+      message(AUTHOR_WARNING "To use this prerelease version of ${PACKAGE_FIND_NAME}, set ${PACKAGE_FIND_NAME}_FIND_VERSION_PRERELEASE to '@protobuf_VERSION_PRERELEASE@' or greater.")
+      set(PACKAGE_VERSION_COMPATIBLE FALSE)
+    endif()
 
-  # Not robustly SemVer compliant, but protobuf never uses '.' separated prerelease identifiers.
-  if(PACKAGE_FIND_VERSION_PRERELEASE STRGREATER "@protobuf_VERSION_PRERELEASE@")
-    set(PACKAGE_VERSION_COMPATIBLE FALSE)
+    # Not robustly SemVer compliant, but protobuf never uses '.' separated prerelease identifiers.
+    if(PACKAGE_FIND_VERSION_PRERELEASE STRGREATER "@protobuf_VERSION_PRERELEASE@")
+      set(PACKAGE_VERSION_COMPATIBLE FALSE)
+    endif()
   endif()
 endif()
 
 # Check and save build options used to create this package
 macro(_check_and_save_build_option OPTION VALUE)
   if(DEFINED ${PACKAGE_FIND_NAME}_${OPTION} AND
-    NOT ${PACKAGE_FIND_NAME}_${OPTION} EQUAL VALUE)
+    NOT ${PACKAGE_FIND_NAME}_${OPTION} STREQUAL ${VALUE})
     set(PACKAGE_VERSION_UNSUITABLE TRUE)
   endif()
-  set(${PACKAGE_FIND_NAME}_${OPTION} ${VALUE})
+  set(${PACKAGE_FIND_NAME}_${OPTION} ${VALUE} PARENT_SCOPE)
 endmacro()
 _check_and_save_build_option(WITH_ZLIB @protobuf_WITH_ZLIB@)
 _check_and_save_build_option(MSVC_STATIC_RUNTIME @protobuf_MSVC_STATIC_RUNTIME@)
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index a044fe5..11a9b75 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -7,6 +7,110 @@
 # Imported targets
 include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake")
 
+function(protobuf_generate)
+  include(CMakeParseArguments)
+
+  set(_options APPEND_PATH)
+  set(_singleargs LANGUAGE OUT_VAR)
+  if(COMMAND target_sources)
+    list(APPEND _singleargs TARGET)
+  endif()
+  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS)
+
+  cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
+
+  if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
+    message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
+    return()
+  endif()
+
+  if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
+    message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
+    return()
+  endif()
+
+  if(NOT protobuf_generate_LANGUAGE)
+    set(protobuf_generate_LANGUAGE cpp)
+  endif()
+  string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
+
+  if(NOT protobuf_GENERATE_EXTENSIONS)
+    if(protobuf_generate_LANGUAGE STREQUAL cpp)
+      set(protobuf_GENERATE_EXTENSIONS .pb.h .pb.cc)
+    elseif(protobuf_generate_LANGUAGE STREQUAL python)
+      set(protobuf_GENERATE_EXTENSIONS _pb2.py)
+    else()
+      message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
+      return()
+    endif()
+  endif()
+
+  if(protobuf_generate_APPEND_PATH)
+    # Create an include path for each file specified
+    foreach(_file ${ARGN})
+      get_filename_component(_abs_file ${_file} ABSOLUTE)
+      get_filename_component(_abs_path ${_abs_file} PATH)
+      list(FIND _protobuf_include_path ${_abs_path} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${_abs_path})
+      endif()
+    endforeach()
+  else()
+    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+  endif()
+
+  foreach(DIR ${protobuf_generate_IMPORT_DIRS})
+    get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+    list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+    if(${_contains_already} EQUAL -1)
+        list(APPEND _protobuf_include_path -I ${ABS_PATH})
+    endif()
+  endforeach()
+
+  if(protobuf_generate_TARGET)
+    get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
+    foreach(_file ${_source_list})
+      if(_file MATCHES "proto$")
+        list(APPEND protobuf_generate_PROTOS ${_file})
+      endif()
+    endforeach()
+  endif()
+
+  if(NOT protobuf_generate_PROTOS)
+    message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
+    return()
+  endif()
+
+  set(_generated_srcs_all)
+  foreach(_proto ${protobuf_generate_PROTOS})
+    get_filename_component(_abs_file ${_proto} ABSOLUTE)
+    get_filename_component(_basename ${_proto} NAME_WE)
+
+    set(_generated_srcs)
+    foreach(_ext ${protobuf_GENERATE_EXTENSIONS})
+      list(APPEND _generated_srcs "${CMAKE_CURRENT_BINARY_DIR}/${_basename}${_ext}")
+    endforeach()
+    list(APPEND _generated_srcs_all ${_generated_srcs})
+
+    add_custom_command(
+      OUTPUT ${_generated_srcs}
+      COMMAND  protobuf::protoc
+      ARGS --${protobuf_generate_LANGUAGE}_out  ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${_abs_file}
+      DEPENDS ${ABS_FIL} protobuf::protoc
+      COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}"
+      VERBATIM )
+  endforeach()
+
+  set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
+  if(protobuf_generate_OUT_VAR)
+    set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
+  endif()
+  if(protobuf_generate_TARGET)
+    target_sources(${protobuf_generate_TARGET} PUBLIC ${_generated_srcs_all})
+  endif()
+
+endfunction()
+
 # CMake FindProtobuf module compatible file
 if(protobuf_MODULE_COMPATIBLE)
   include("${CMAKE_CURRENT_LIST_DIR}/protobuf-module.cmake")
diff --git a/cmake/protobuf-lite.pc.cmake b/cmake/protobuf-lite.pc.cmake
new file mode 100644
index 0000000..cbe5426
--- /dev/null
+++ b/cmake/protobuf-lite.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: Protocol Buffers
+Description: Google's Data Interchange Format
+Version: @protobuf_VERSION@
+Libs: -L${libdir} -lprotobuf-lite @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir} @CMAKE_THREAD_LIBS_INIT@
+Conflicts: protobuf
diff --git a/cmake/protobuf-module.cmake.in b/cmake/protobuf-module.cmake.in
index 614e4c0..8e4920a 100644
--- a/cmake/protobuf-module.cmake.in
+++ b/cmake/protobuf-module.cmake.in
@@ -1,3 +1,4 @@
+# This file contains backwards compatibility patches for various legacy functions and variables
 # Functions
 
 function(PROTOBUF_GENERATE_CPP SRCS HDRS)
@@ -7,49 +8,25 @@
   endif()
 
   if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
-    # Create an include path for each file specified
-    foreach(FIL ${ARGN})
-      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
-      get_filename_component(ABS_PATH ${ABS_FIL} PATH)
-      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
-      if(${_contains_already} EQUAL -1)
-          list(APPEND _protobuf_include_path -I ${ABS_PATH})
-      endif()
-    endforeach()
-  else()
-    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+    set(_append_arg APPEND_PATH)
   endif()
 
   if(DEFINED Protobuf_IMPORT_DIRS)
-    foreach(DIR ${Protobuf_IMPORT_DIRS})
-      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
-      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
-      if(${_contains_already} EQUAL -1)
-          list(APPEND _protobuf_include_path -I ${ABS_PATH})
-      endif()
-    endforeach()
+    set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
   endif()
 
+  set(_outvar)
+  protobuf_generate(${append_arg} LANGUAGE cpp OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN})
+
   set(${SRCS})
   set(${HDRS})
-  foreach(FIL ${ARGN})
-    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
-    get_filename_component(FIL_WE ${FIL} NAME_WE)
-
-    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
-    list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
-
-    add_custom_command(
-      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
-             "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
-      COMMAND  ${Protobuf_PROTOC_EXECUTABLE}
-      ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
-      DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
-      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
-      VERBATIM )
+  foreach(_file ${_outvar})
+    if(_file MATCHES "cc$")
+      list(APPEND ${SRCS} ${_file})
+    else()
+      list(APPEND ${HDRS} ${_file})
+    endif()
   endforeach()
-
-  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
   set(${SRCS} ${${SRCS}} PARENT_SCOPE)
   set(${HDRS} ${${HDRS}} PARENT_SCOPE)
 endfunction()
@@ -61,44 +38,16 @@
   endif()
 
   if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
-    # Create an include path for each file specified
-    foreach(FIL ${ARGN})
-      get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
-      get_filename_component(ABS_PATH ${ABS_FIL} PATH)
-      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
-      if(${_contains_already} EQUAL -1)
-          list(APPEND _protobuf_include_path -I ${ABS_PATH})
-      endif()
-    endforeach()
-  else()
-    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+    set(_append_arg APPEND_PATH)
   endif()
 
   if(DEFINED Protobuf_IMPORT_DIRS)
-    foreach(DIR ${Protobuf_IMPORT_DIRS})
-      get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
-      list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
-      if(${_contains_already} EQUAL -1)
-          list(APPEND _protobuf_include_path -I ${ABS_PATH})
-      endif()
-    endforeach()
+    set(_import_arg IMPORT_DIRS ${Protobuf_IMPORT_DIRS})
   endif()
 
-  set(${SRCS})
-  foreach(FIL ${ARGN})
-    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
-    get_filename_component(FIL_WE ${FIL} NAME_WE)
-
-    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py")
-    add_custom_command(
-      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py"
-      COMMAND  ${Protobuf_PROTOC_EXECUTABLE} --python_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
-      DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
-      COMMENT "Running Python protocol buffer compiler on ${FIL}"
-      VERBATIM )
-  endforeach()
-
-  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+  set(_outvar)
+  protobuf_generate(${append_arg} LANGUAGE cpp OUT_VAR _outvar ${_import_arg} PROTOS ${ARGN})
+  set(${SRCS} ${_outvar} PARENT_SCOPE)
 endfunction()
 
 # Environment
diff --git a/cmake/protobuf.pc.cmake b/cmake/protobuf.pc.cmake
new file mode 100644
index 0000000..d33e98c
--- /dev/null
+++ b/cmake/protobuf.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
+
+Name: Protocol Buffers
+Description: Google's Data Interchange Format
+Version: @protobuf_VERSION@
+Libs: -L${libdir} -lprotobuf @CMAKE_THREAD_LIBS_INIT@
+Cflags: -I${includedir} @CMAKE_THREAD_LIBS_INIT@
+Conflicts: protobuf-lite
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 38dc0b5..389f6a7 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -123,6 +123,7 @@
   ${protobuf_source_dir}/src/google/protobuf/arenastring_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/command_line_interface_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/cpp_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -160,6 +161,7 @@
   ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/int128_unittest.cc
+  ${protobuf_source_dir}/src/google/protobuf/stubs/io_win32_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc
   ${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc
diff --git a/composer.json b/composer.json
index 2b04e07..2c64ad2 100644
--- a/composer.json
+++ b/composer.json
@@ -11,13 +11,13 @@
   "require-dev": {
     "phpunit/phpunit": ">=4.8.0"
   },
+  "suggest": {
+    "ext-bcmath": "Need to support JSON deserialization"
+  },
   "autoload": {
     "psr-4": {
-      "Google\\Protobuf\\Internal\\": "php/src/Google/Protobuf/Internal",
-      "GPBMetadata\\Google\\Protobuf\\Internal\\": "php/src/GPBMetadata/Google/Protobuf/Internal"
-    },
-    "files": [
-      "php/src/Google/Protobuf/descriptor.php"
-    ]
+      "Google\\Protobuf\\": "php/src/Google/Protobuf",
+      "GPBMetadata\\Google\\Protobuf\\": "php/src/GPBMetadata/Google/Protobuf"
+    }
   }
 }
diff --git a/configure.ac b/configure.ac
index 82b221e..04f7eb7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
 # In the SVN trunk, the version should always be the next anticipated release
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.3.0],[[email protected]],[protobuf])
+AC_INIT([Protocol Buffers],[3.4.0],[[email protected]],[protobuf])
 
 AM_MAINTAINER_MODE([enable])
 
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java
index 7badf2a..596d113 100644
--- a/conformance/ConformanceJava.java
+++ b/conformance/ConformanceJava.java
@@ -1,12 +1,18 @@
 import com.google.protobuf.ByteString;
+import com.google.protobuf.AbstractMessage;
+import com.google.protobuf.Parser;
 import com.google.protobuf.CodedInputStream;
 import com.google.protobuf.conformance.Conformance;
 import com.google.protobuf.InvalidProtocolBufferException;
 import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
+import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
+import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
+import com.google.protobuf.ExtensionRegistry;
 import com.google.protobuf.util.JsonFormat;
 import com.google.protobuf.util.JsonFormat.TypeRegistry;
-import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
 
 class ConformanceJava {
   private int testCount = 0;
@@ -50,123 +56,100 @@
     buf[3] = (byte)(val >> 24);
     writeToStdout(buf);
   }
-
-  private enum BinaryDecoder {
-    BYTE_STRING_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        return TestMessagesProto3.TestAllTypes.parseFrom(bytes);
-      }
-    },
-    BYTE_ARRAY_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        return TestMessagesProto3.TestAllTypes.parseFrom(bytes.toByteArray());
-      }
-    },
-    ARRAY_BYTE_BUFFER_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
-        bytes.copyTo(buffer);
-        buffer.flip();
-        try {
-          return TestMessagesProto3.TestAllTypes.parseFrom(CodedInputStream.newInstance(buffer));
-        } catch (InvalidProtocolBufferException e) {
-          throw e;
-        } catch (IOException e) {
-          throw new RuntimeException(
-              "ByteString based ByteBuffer should not throw IOException.", e);
-        }
-      }
-    },
-    READONLY_ARRAY_BYTE_BUFFER_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        try {
-          return TestMessagesProto3.TestAllTypes.parseFrom(
-              CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()));
-        } catch (InvalidProtocolBufferException e) {
-          throw e;
-        } catch (IOException e) {
-          throw new RuntimeException(
-              "ByteString based ByteBuffer should not throw IOException.", e);
-        }
-      }
-    },
-    DIRECT_BYTE_BUFFER_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
-        bytes.copyTo(buffer);
-        buffer.flip();
-        try {
-          return TestMessagesProto3.TestAllTypes.parseFrom(CodedInputStream.newInstance(buffer));
-        } catch (InvalidProtocolBufferException e) {
-          throw e;
-        } catch (IOException e) {
-          throw new RuntimeException(
-              "ByteString based ByteBuffer should not throw IOException.", e);
-        }
-      }
-    },
-    READONLY_DIRECT_BYTE_BUFFER_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
-        bytes.copyTo(buffer);
-        buffer.flip();
-        try {
-          return TestMessagesProto3.TestAllTypes.parseFrom(
-              CodedInputStream.newInstance(buffer.asReadOnlyBuffer()));
-        } catch (InvalidProtocolBufferException e) {
-          throw e;
-        } catch (IOException e) {
-          throw new RuntimeException(
-              "ByteString based ByteBuffer should not throw IOException.", e);
-        }
-      }
-    },
-    INPUT_STREAM_DECODER() {
-      @Override
-      public TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-          throws InvalidProtocolBufferException {
-        try {
-          return TestMessagesProto3.TestAllTypes.parseFrom(bytes.newInput());
-        } catch (InvalidProtocolBufferException e) {
-          throw e;
-        } catch (IOException e) {
-          throw new RuntimeException(
-              "ByteString based InputStream should not throw IOException.", e);
-        }
-      }
-    };
-
-    public abstract TestMessagesProto3.TestAllTypes parse(ByteString bytes)
-        throws InvalidProtocolBufferException;
+  
+  private enum BinaryDecoderType {
+    BTYE_STRING_DECODER,
+    BYTE_ARRAY_DECODER,
+    ARRAY_BYTE_BUFFER_DECODER,
+    READONLY_ARRAY_BYTE_BUFFER_DECODER,
+    DIRECT_BYTE_BUFFER_DECODER,
+    READONLY_DIRECT_BYTE_BUFFER_DECODER,
+    INPUT_STREAM_DECODER;
   }
 
-  private TestMessagesProto3.TestAllTypes parseBinary(ByteString bytes)
+  private static class BinaryDecoder <MessageType extends AbstractMessage> {
+    public MessageType decode (ByteString bytes, BinaryDecoderType type, 
+        Parser <MessageType> parser, ExtensionRegistry extensions)
       throws InvalidProtocolBufferException {
-    TestMessagesProto3.TestAllTypes[] messages =
-        new TestMessagesProto3.TestAllTypes[BinaryDecoder.values().length];
-    InvalidProtocolBufferException[] exceptions =
-        new InvalidProtocolBufferException[BinaryDecoder.values().length];
+      switch (type) {
+        case BTYE_STRING_DECODER: 
+          return parser.parseFrom(bytes, extensions);
+        case BYTE_ARRAY_DECODER:
+          return parser.parseFrom(bytes.toByteArray(), extensions);
+        case ARRAY_BYTE_BUFFER_DECODER: {
+          ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
+          bytes.copyTo(buffer);
+          buffer.flip();
+          try {
+            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            throw e;
+          }
+        }
+        case READONLY_ARRAY_BYTE_BUFFER_DECODER: {
+          try {
+            return parser.parseFrom(
+                CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            throw e;
+          }
+        } 
+        case DIRECT_BYTE_BUFFER_DECODER: {
+          ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+          bytes.copyTo(buffer);
+          buffer.flip();
+          try {
+            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            throw e;
+          }
+        }
+        case READONLY_DIRECT_BYTE_BUFFER_DECODER: {
+          ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
+          bytes.copyTo(buffer);
+          buffer.flip();
+          try {
+            return parser.parseFrom(
+                CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            throw e;
+          }
+        }
+        case INPUT_STREAM_DECODER: {
+          try {
+            return parser.parseFrom(bytes.newInput(), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            throw e;
+          }
+        }
+        default :
+          return null;
+      }
+    }
+  }
+
+  private <MessageType extends AbstractMessage> MessageType parseBinary(
+      ByteString bytes, Parser <MessageType> parser, ExtensionRegistry extensions)
+      throws InvalidProtocolBufferException {
+    ArrayList <MessageType> messages = new ArrayList <MessageType> ();
+    ArrayList <InvalidProtocolBufferException> exceptions =
+        new ArrayList <InvalidProtocolBufferException>();
+    
+    for (int i = 0; i < BinaryDecoderType.values().length; i++) {
+      messages.add(null);
+      exceptions.add(null);
+    }
+    BinaryDecoder <MessageType> decoder = new BinaryDecoder <MessageType> ();
 
     boolean hasMessage = false;
     boolean hasException = false;
-    for (int i = 0; i < BinaryDecoder.values().length; ++i) {
+    for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
       try {
-        messages[i] = BinaryDecoder.values()[i].parse(bytes);
+        //= BinaryDecoderType.values()[i].parseProto3(bytes);
+        messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
         hasMessage = true;
       } catch (InvalidProtocolBufferException e) {
-        exceptions[i] = e;
+        exceptions.set(i, e);
         hasException = true;
       }
     }
@@ -174,9 +157,9 @@
     if (hasMessage && hasException) {
       StringBuilder sb =
           new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n");
-      for (int i = 0; i < BinaryDecoder.values().length; ++i) {
-        sb.append(BinaryDecoder.values()[i].name());
-        if (messages[i] != null) {
+      for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
+        sb.append(BinaryDecoderType.values()[i].name());
+        if (messages.get(i) != null) {
           sb.append(" accepted the payload.\n");
         } else {
           sb.append(" rejected the payload.\n");
@@ -188,14 +171,14 @@
     if (hasException) {
       // We do not check if exceptions are equal. Different implementations may return different
       // exception messages. Throw an arbitrary one out instead.
-      throw exceptions[0];
+      throw exceptions.get(0);
     }
 
     // Fast path comparing all the messages with the first message, assuming equality being
     // symmetric and transitive.
     boolean allEqual = true;
-    for (int i = 1; i < messages.length; ++i) {
-      if (!messages[0].equals(messages[i])) {
+    for (int i = 1; i < messages.size(); ++i) {
+      if (!messages.get(0).equals(messages.get(i))) {
         allEqual = false;
         break;
       }
@@ -204,12 +187,12 @@
     // Slow path: compare and find out all unequal pairs.
     if (!allEqual) {
       StringBuilder sb = new StringBuilder();
-      for (int i = 0; i < messages.length - 1; ++i) {
-        for (int j = i + 1; j < messages.length; ++j) {
-          if (!messages[i].equals(messages[j])) {
-            sb.append(BinaryDecoder.values()[i].name())
+      for (int i = 0; i < messages.size() - 1; ++i) {
+        for (int j = i + 1; j < messages.size(); ++j) {
+          if (!messages.get(i).equals(messages.get(j))) {
+            sb.append(BinaryDecoderType.values()[i].name())
                 .append(" and ")
-                .append(BinaryDecoder.values()[j].name())
+                .append(BinaryDecoderType.values()[j].name())
                 .append(" parsed the payload differently.\n");
           }
         }
@@ -217,24 +200,41 @@
       throw new RuntimeException(sb.toString());
     }
 
-    return messages[0];
+    return messages.get(0);
   }
 
   private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
-    TestMessagesProto3.TestAllTypes testMessage;
+    com.google.protobuf.AbstractMessage testMessage;
+    boolean isProto3 = request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
+    boolean isProto2 = request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");
 
     switch (request.getPayloadCase()) {
       case PROTOBUF_PAYLOAD: {
-        try {
-          testMessage = parseBinary(request.getProtobufPayload());
-        } catch (InvalidProtocolBufferException e) {
-          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+        if (isProto3) {
+          try {
+            ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+            TestMessagesProto3.registerAllExtensions(extensions);
+            testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+          }
+        } else if (isProto2) {
+          try {
+            ExtensionRegistry extensions = ExtensionRegistry.newInstance();
+            TestMessagesProto2.registerAllExtensions(extensions);
+            testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
+          } catch (InvalidProtocolBufferException e) {
+            return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+          }
+        } else {
+          throw new RuntimeException("Protobuf request doesn't have specific payload type.");
         }
         break;
       }
       case JSON_PAYLOAD: {
         try {
-          TestMessagesProto3.TestAllTypes.Builder builder = TestMessagesProto3.TestAllTypes.newBuilder();
+          TestMessagesProto3.TestAllTypesProto3.Builder builder = 
+              TestMessagesProto3.TestAllTypesProto3.newBuilder();
           JsonFormat.parser().usingTypeRegistry(typeRegistry)
               .merge(request.getJsonPayload(), builder);
           testMessage = builder.build();
@@ -256,8 +256,10 @@
       case UNSPECIFIED:
         throw new RuntimeException("Unspecified output format.");
 
-      case PROTOBUF:
-        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+      case PROTOBUF: {
+        ByteString MessageString = testMessage.toByteString(); 
+        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build();
+      }
 
       case JSON:
         try {
@@ -300,7 +302,7 @@
 
   public void run() throws Exception {
     typeRegistry = TypeRegistry.newBuilder().add(
-        TestMessagesProto3.TestAllTypes.getDescriptor()).build();
+        TestMessagesProto3.TestAllTypesProto3.getDescriptor()).build();
     while (doTestIo()) {
       this.testCount++;
     }
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index 1a8b574..f7ce053 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -4,6 +4,11 @@
   conformance.proto                                            \
   $(top_srcdir)/src/google/protobuf/test_messages_proto3.proto
 
+# proto2 input files, should be separated with proto3, as we
+# can't generate proto2 files for ruby, php and objc
+conformance_proto2_protoc_inputs =                             \
+  $(top_srcdir)/src/google/protobuf/test_messages_proto2.proto
+
 well_known_type_protoc_inputs =                                \
   $(top_srcdir)/src/google/protobuf/any.proto                  \
   $(top_srcdir)/src/google/protobuf/duration.proto             \
@@ -64,6 +69,7 @@
   com/google/protobuf/ValueOrBuilder.java                      \
   com/google/protobuf/WrappersProto.java                       \
   com/google/protobuf_test_messages/proto3/TestMessagesProto3.java \
+  com/google/protobuf_test_messages/proto2/TestMessagesProto2.java \
   google/protobuf/any.pb.cc                                    \
   google/protobuf/any.pb.h                                     \
   google/protobuf/any.rb                                       \
@@ -80,12 +86,17 @@
   google/protobuf/struct.pb.h                                  \
   google/protobuf/struct.rb                                    \
   google/protobuf/struct_pb2.py                                \
+  google/protobuf/TestMessagesProto2.pbobjc.h                  \
+  google/protobuf/TestMessagesProto2.pbobjc.m                  \
   google/protobuf/TestMessagesProto3.pbobjc.h                  \
   google/protobuf/TestMessagesProto3.pbobjc.m                  \
   google/protobuf/test_messages_proto3.pb.cc                   \
   google/protobuf/test_messages_proto3.pb.h                    \
+  google/protobuf/test_messages_proto2.pb.cc                   \
+  google/protobuf/test_messages_proto2.pb.h                    \
   google/protobuf/test_messages_proto3_pb.rb                   \
   google/protobuf/test_messages_proto3_pb2.py                  \
+  google/protobuf/test_messages_proto2_pb2.py                  \
   google/protobuf/timestamp.pb.cc                              \
   google/protobuf/timestamp.pb.h                               \
   google/protobuf/timestamp.rb                                 \
@@ -198,7 +209,7 @@
                                   conformance_test_runner.cc             \
                                   third_party/jsoncpp/json.h             \
                                   third_party/jsoncpp/jsoncpp.cpp
-nodist_conformance_test_runner_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc
+nodist_conformance_test_runner_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc
 conformance_test_runner_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)
 conformance_test_runner_CXXFLAGS = -std=c++11
 # Explicit deps beacuse BUILT_SOURCES are only done before a "make all/check"
@@ -208,7 +219,7 @@
 
 conformance_cpp_LDADD = $(top_srcdir)/src/libprotobuf.la
 conformance_cpp_SOURCES = conformance_cpp.cc
-nodist_conformance_cpp_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc
+nodist_conformance_cpp_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc
 conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
 # Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check"
 # so a direct "make test_cpp" could fail if parallel enough.
@@ -219,7 +230,7 @@
 bin_PROGRAMS += conformance-objc
 
 conformance_objc_SOURCES = conformance_objc.m ../objectivec/GPBProtocolBuffers.m
-nodist_conformance_objc_SOURCES = Conformance.pbobjc.m google/protobuf/TestMessagesProto3.pbobjc.m
+nodist_conformance_objc_SOURCES = Conformance.pbobjc.m google/protobuf/TestMessagesProto2.pbobjc.m google/protobuf/TestMessagesProto3.pbobjc.m
 # On travis, the build fails without the isysroot because whatever system
 # headers are being found don't include generics support for
 # NSArray/NSDictionary, the only guess is their image at one time had an odd
@@ -228,7 +239,7 @@
 conformance_objc_LDFLAGS = -framework Foundation
 # Explicit dep beacuse BUILT_SOURCES are only done before a "make all/check"
 # so a direct "make test_objc" could fail if parallel enough.
-conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h google/protobuf/TestMessagesProto3.pbobjc.h
+conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h google/protobuf/TestMessagesProto2.pbobjc.h google/protobuf/TestMessagesProto3.pbobjc.h
 
 endif
 
@@ -242,8 +253,9 @@
 if USE_EXTERNAL_PROTOC
 
 # Some implementations include pre-generated versions of well-known types.
-protoc_middleman: $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
+protoc_middleman: $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
 	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:. $(conformance_protoc_inputs)
+	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --objc_out=. --python_out=. --js_out=import_style=commonjs,binary:. $(conformance_proto2_protoc_inputs)
 	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. --php_out=. --js_out=import_style=commonjs,binary:google-protobuf $(well_known_type_protoc_inputs)
 	## $(PROTOC) -I$(srcdir) -I$(top_srcdir) --java_out=lite:lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs)
 	touch protoc_middleman
@@ -253,8 +265,9 @@
 # We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
 # relative to srcdir, which may not be the same as the current directory when
 # building out-of-tree.
-protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(conformance_protoc_inputs) $(conformance_proto2_protoc_inputs) $(well_known_type_protoc_inputs) google-protobuf
 	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --objc_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_protoc_inputs) )
+	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --objc_out=. --python_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd $(conformance_proto2_protoc_inputs) )
 	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd --java_out=$$oldpwd --ruby_out=$$oldpwd --python_out=$$oldpwd --php_out=$$oldpwd --js_out=import_style=commonjs,binary:$$oldpwd/google-protobuf $(well_known_type_protoc_inputs) )
 	## @mkdir -p lite
 	## oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --java_out=lite:$$oldpwd/lite $(conformance_protoc_inputs) $(well_known_type_protoc_inputs) )
@@ -274,7 +287,7 @@
   Makefile.in
 
 javac_middleman: ConformanceJava.java protoc_middleman $(other_language_protoc_outputs)
-	jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java com/google/protobuf_test_messages/proto3/TestMessagesProto3.java
+	jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java com/google/protobuf_test_messages/proto3/TestMessagesProto3.java com/google/protobuf_test_messages/proto2/TestMessagesProto2.java
 	@touch javac_middleman
 
 conformance-java: javac_middleman
@@ -305,7 +318,7 @@
 conformance-php:
 	@echo "Writing shortcut script conformance-php..."
 	@echo '#! /bin/sh' > conformance-php
-	@echo 'php  ./conformance_php.php' >> conformance-php
+	@echo 'php -d auto_prepend_file=autoload.php ./conformance_php.php' >> conformance-php
 	@chmod +x conformance-php
 
 conformance-php-c:
@@ -336,6 +349,9 @@
 test_php_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs)
 	./conformance-test-runner --enforce_recommended --failure_list failure_list_php_c.txt ./conformance-php-c
 
+test_php_zts_c: protoc_middleman conformance-test-runner conformance-php-c $(other_language_protoc_outputs)
+	./conformance-test-runner --enforce_recommended --failure_list failure_list_php_zts_c.txt ./conformance-php-c
+
 # These depend on library paths being properly set up.  The easiest way to
 # run them is to just use "tox" from the python dir.
 test_python: protoc_middleman conformance-test-runner
diff --git a/conformance/autoload.php b/conformance/autoload.php
new file mode 100644
index 0000000..2cee31c
--- /dev/null
+++ b/conformance/autoload.php
@@ -0,0 +1,21 @@
+<?php
+
+define("GOOGLE_INTERNAL_NAMESPACE", "Google\\Protobuf\\Internal\\");
+define("GOOGLE_NAMESPACE", "Google\\Protobuf\\");
+define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\Internal\\");
+
+function protobuf_autoloader_impl($class, $prefix) {
+    $length = strlen($prefix);
+    if ((substr($class, 0, $length) === $prefix)) {
+        $path = '../php/src/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php';
+        include_once $path;
+    }
+}
+
+function protobuf_autoloader($class) {
+    protobuf_autoloader_impl($class, GOOGLE_INTERNAL_NAMESPACE);
+    protobuf_autoloader_impl($class, GOOGLE_NAMESPACE);
+    protobuf_autoloader_impl($class, GOOGLE_GPBMETADATA_NAMESPACE);
+}
+
+spl_autoload_register('protobuf_autoloader');
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index 18e4b7b..525140e 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -77,6 +77,11 @@
 
   // Which format should the testee serialize its message to?
   WireFormat requested_output_format = 3;
+
+  // The full name for the test message to use; for the moment, either:
+  // protobuf_test_messages.proto3.TestAllTypesProto3 or
+  // protobuf_test_messages.proto2.TestAllTypesProto2.
+  string message_type = 4;
 }
 
 // Represents a single test case's output.
diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc
index b865cd9..bf70309 100644
--- a/conformance/conformance_cpp.cc
+++ b/conformance/conformance_cpp.cc
@@ -34,6 +34,8 @@
 
 #include "conformance.pb.h"
 #include <google/protobuf/test_messages_proto3.pb.h>
+#include <google/protobuf/test_messages_proto2.pb.h>
+#include <google/protobuf/message.h>
 #include <google/protobuf/util/json_util.h>
 #include <google/protobuf/util/type_resolver_util.h>
 
@@ -41,13 +43,15 @@
 using conformance::ConformanceResponse;
 using google::protobuf::Descriptor;
 using google::protobuf::DescriptorPool;
+using google::protobuf::Message;
+using google::protobuf::MessageFactory;
 using google::protobuf::internal::scoped_ptr;
 using google::protobuf::util::BinaryToJsonString;
 using google::protobuf::util::JsonToBinaryString;
 using google::protobuf::util::NewTypeResolverForDescriptorPool;
 using google::protobuf::util::Status;
 using google::protobuf::util::TypeResolver;
-using protobuf_test_messages::proto3::TestAllTypes;
+using protobuf_test_messages::proto3::TestAllTypesProto3;
 using std::string;
 
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
@@ -87,17 +91,24 @@
 }
 
 void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
-  TestAllTypes test_message;
+  Message *test_message;
+  const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(
+      request.message_type());
+  if (!descriptor) {
+    GOOGLE_LOG(FATAL) << "No such message type: " << request.message_type();
+  }
+  test_message = MessageFactory::generated_factory()->GetPrototype(descriptor)->New();
 
   switch (request.payload_case()) {
-    case ConformanceRequest::kProtobufPayload:
-      if (!test_message.ParseFromString(request.protobuf_payload())) {
+    case ConformanceRequest::kProtobufPayload: {
+      if (!test_message->ParseFromString(request.protobuf_payload())) {
         // Getting parse details would involve something like:
         //   http://stackoverflow.com/questions/22121922/how-can-i-get-more-details-about-errors-generated-during-protobuf-parsing-c
         response->set_parse_error("Parse error (no more details available).");
         return;
       }
       break;
+    }
 
     case ConformanceRequest::kJsonPayload: {
       string proto_binary;
@@ -109,7 +120,7 @@
         return;
       }
 
-      if (!test_message.ParseFromString(proto_binary)) {
+      if (!test_message->ParseFromString(proto_binary)) {
         response->set_runtime_error(
             "Parsing JSON generates invalid proto output.");
         return;
@@ -127,14 +138,14 @@
       GOOGLE_LOG(FATAL) << "Unspecified output format";
       break;
 
-    case conformance::PROTOBUF:
-      GOOGLE_CHECK(
-          test_message.SerializeToString(response->mutable_protobuf_payload()));
+    case conformance::PROTOBUF: {
+      GOOGLE_CHECK(test_message->SerializeToString(response->mutable_protobuf_payload()));
       break;
+    }
 
     case conformance::JSON: {
       string proto_binary;
-      GOOGLE_CHECK(test_message.SerializeToString(&proto_binary));
+      GOOGLE_CHECK(test_message->SerializeToString(&proto_binary));
       Status status = BinaryToJsonString(type_resolver, *type_url, proto_binary,
                                          response->mutable_json_payload());
       if (!status.ok()) {
@@ -197,7 +208,7 @@
 int main() {
   type_resolver = NewTypeResolverForDescriptorPool(
       kTypeUrlPrefix, DescriptorPool::generated_pool());
-  type_url = new string(GetTypeUrl(TestAllTypes::descriptor()));
+  type_url = new string(GetTypeUrl(TestAllTypesProto3::descriptor()));
   while (1) {
     if (!DoTestIo()) {
       fprintf(stderr, "conformance-cpp: received EOF from test runner "
diff --git a/conformance/conformance_nodejs.js b/conformance/conformance_nodejs.js
index 5ee3726..5d3955f 100755
--- a/conformance/conformance_nodejs.js
+++ b/conformance/conformance_nodejs.js
@@ -34,6 +34,7 @@
 
 var conformance = require('conformance_pb');
 var test_messages_proto3 = require('google/protobuf/test_messages_proto3_pb');
+var test_messages_proto2 = require('google/protobuf/test_messages_proto2_pb');
 var fs = require('fs');
 
 var testCount = 0;
@@ -49,14 +50,27 @@
     }
 
     switch (request.getPayloadCase()) {
-      case conformance.ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD:
-        try {
-          testMessage = test_messages_proto3.TestAllTypes.deserializeBinary(
-              request.getProtobufPayload());
-        } catch (err) {
-          response.setParseError(err.toString());
-          return response;
+      case conformance.ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD: {
+        if (request.getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") {
+          try {
+            testMessage = test_messages_proto3.TestAllTypesProto3.deserializeBinary(
+                request.getProtobufPayload());
+          } catch (err) {
+            response.setParseError(err.toString());
+            return response;
+          }
+        } else if (request.getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2"){
+          try {
+            testMessage = test_messages_proto2.TestAllTypesProto2.deserializeBinary(
+                request.getProtobufPayload());
+          } catch (err) {
+            response.setParseError(err.toString());
+            return response;
+          }
+        } else {
+          throw "Protobuf request doesn\'t have specific payload type";
         }
+      }
 
       case conformance.ConformanceRequest.PayloadCase.JSON_PAYLOAD:
         response.setSkipped("JSON not supported.");
diff --git a/conformance/conformance_objc.m b/conformance/conformance_objc.m
index ef037f8..84a4381 100644
--- a/conformance/conformance_objc.m
+++ b/conformance/conformance_objc.m
@@ -31,6 +31,7 @@
 #import <Foundation/Foundation.h>
 
 #import "Conformance.pbobjc.h"
+#import "google/protobuf/TestMessagesProto2.pbobjc.h"
 #import "google/protobuf/TestMessagesProto3.pbobjc.h"
 
 static void Die(NSString *format, ...) __dead2;
@@ -63,7 +64,7 @@
 
 static ConformanceResponse *DoTest(ConformanceRequest *request) {
   ConformanceResponse *response = [ConformanceResponse message];
-  TestAllTypes *testMessage = nil;
+  GPBMessage *testMessage = nil;
 
   switch (request.payloadOneOfCase) {
     case ConformanceRequest_Payload_OneOfCase_GPBUnsetOneOfCase:
@@ -71,9 +72,16 @@
       break;
 
     case ConformanceRequest_Payload_OneOfCase_ProtobufPayload: {
+      Class msgClass = nil;
+      if ([request.messageType isEqual:@"protobuf_test_messages.proto3.TestAllTypesProto3"]) {
+        msgClass = [Proto3TestAllTypesProto3 class];
+      } else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
+        msgClass = [TestAllTypesProto2 class];
+      } else {
+        Die(@"Protobuf request had an unknown message_type: %@", request.messageType);
+      }
       NSError *error = nil;
-      testMessage = [TestAllTypes parseFromData:request.protobufPayload
-                                          error:&error];
+      testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
       if (!testMessage) {
         response.parseError =
             [NSString stringWithFormat:@"Parse error: %@", error];
diff --git a/conformance/conformance_php.php b/conformance/conformance_php.php
index 20fb508..2e3f783 100755
--- a/conformance/conformance_php.php
+++ b/conformance/conformance_php.php
@@ -23,9 +23,9 @@
 require_once("Google/Protobuf/UInt64Value.php");
 require_once("Protobuf_test_messages/Proto3/ForeignMessage.php");
 require_once("Protobuf_test_messages/Proto3/ForeignEnum.php");
-require_once("Protobuf_test_messages/Proto3/TestAllTypes.php");
-require_once("Protobuf_test_messages/Proto3/TestAllTypes_NestedMessage.php");
-require_once("Protobuf_test_messages/Proto3/TestAllTypes_NestedEnum.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedMessage.php");
+require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3_NestedEnum.php");
 
 require_once("GPBMetadata/Conformance.php");
 require_once("GPBMetadata/Google/Protobuf/Any.php");
@@ -38,22 +38,33 @@
 
 use  \Conformance\WireFormat;
 
+if (!ini_get("date.timezone")) {
+  ini_set("date.timezone", "UTC");
+}
+
 $test_count = 0;
 
 function doTest($request)
 {
-    $test_message = new \Protobuf_test_messages\Proto3\TestAllTypes();
+    $test_message = new \Protobuf_test_messages\Proto3\TestAllTypesProto3();
     $response = new \Conformance\ConformanceResponse();
     if ($request->getPayload() == "protobuf_payload") {
-      try {
+      if ($request->getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") {
+        try {
           $test_message->mergeFromString($request->getProtobufPayload());
-      } catch (Exception $e) {
+        } catch (Exception $e) {
           $response->setParseError($e->getMessage());
           return $response;
+        }
+      } elseif ($request->getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2") {
+	$response->setSkipped("PHP doesn't support proto2");
+	return $response;
+      } else {
+	trigger_error("Protobuf request doesn't have specific payload type", E_USER_ERROR);
       }
     } elseif ($request->getPayload() == "json_payload") {
       try {
-          $test_message->jsonDecode($request->getJsonPayload());
+          $test_message->mergeFromJsonString($request->getJsonPayload());
       } catch (Exception $e) {
           $response->setParseError($e->getMessage());
           return $response;
@@ -67,7 +78,7 @@
     } elseif ($request->getRequestedOutputFormat() == WireFormat::PROTOBUF) {
       $response->setProtobufPayload($test_message->serializeToString());
     } elseif ($request->getRequestedOutputFormat() == WireFormat::JSON) {
-      $response->setJsonPayload($test_message->jsonEncode());
+      $response->setJsonPayload($test_message->serializeToJsonString());
     }
 
     return $response;
@@ -79,7 +90,8 @@
     if (strlen($length_bytes) == 0) {
       return false;   # EOF
     } elseif (strlen($length_bytes) != 4) {
-      trigger_error("I/O error", E_USER_ERROR);
+      fwrite(STDERR, "I/O error\n");
+      return false;
     }
 
     $length = unpack("V", $length_bytes)[1];
diff --git a/conformance/conformance_python.py b/conformance/conformance_python.py
index 7ace9b1..c5ba246 100755
--- a/conformance/conformance_python.py
+++ b/conformance/conformance_python.py
@@ -38,9 +38,12 @@
 import struct
 import sys
 import os
+from google.protobuf import descriptor
+from google.protobuf import descriptor_pool
 from google.protobuf import json_format
 from google.protobuf import message
 from google.protobuf import test_messages_proto3_pb2
+from google.protobuf import test_messages_proto2_pb2
 import conformance_pb2
 
 sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
@@ -53,9 +56,17 @@
   pass
 
 def do_test(request):
-  test_message = test_messages_proto3_pb2.TestAllTypes()
+  isProto3 = (request.message_type == "protobuf_test_messages.proto3.TestAllTypesProto3")
+  isJson = (request.WhichOneof('payload') == 'json_payload')
+  isProto2 = (request.message_type == "protobuf_test_messages.proto2.TestAllTypesProto2")
+  
+  if (not isProto3) and (not isJson) and (not isProto2):
+    raise ProtocolError("Protobuf request doesn't have specific payload type")
+      
+  test_message = test_messages_proto2_pb2.TestAllTypesProto2() if isProto2 else \
+    test_messages_proto3_pb2.TestAllTypesProto3()
+
   response = conformance_pb2.ConformanceResponse()
-  test_message = test_messages_proto3_pb2.TestAllTypes()
 
   try:
     if request.WhichOneof('payload') == 'protobuf_payload':
@@ -63,8 +74,8 @@
         test_message.ParseFromString(request.protobuf_payload)
       except message.DecodeError as e:
         response.parse_error = str(e)
-        return response
-
+        return response  
+      
     elif request.WhichOneof('payload') == 'json_payload':
       try:
         json_format.Parse(request.json_payload, test_message)
@@ -82,7 +93,7 @@
       response.protobuf_payload = test_message.SerializeToString()
 
     elif request.requested_output_format == conformance_pb2.JSON:
-      try:
+      try: 
         response.json_payload = json_format.MessageToJson(test_message)
       except Exception as e:
         response.serialize_error = str(e)
diff --git a/conformance/conformance_ruby.rb b/conformance/conformance_ruby.rb
index b7b7cf1..df63bf7 100755
--- a/conformance/conformance_ruby.rb
+++ b/conformance/conformance_ruby.rb
@@ -37,23 +37,30 @@
 $verbose = false
 
 def do_test(request)
-  test_message = ProtobufTestMessages::Proto3::TestAllTypes.new
+  test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.new
   response = Conformance::ConformanceResponse.new
 
   begin
     case request.payload
     when :protobuf_payload
-      begin
-        test_message = ProtobufTestMessages::Proto3::TestAllTypes.decode(
-            request.protobuf_payload)
-      rescue Google::Protobuf::ParseError => err
-        response.parse_error = err.message.encode('utf-8')
+      if request.message_type.eql?('protobuf_test_messages.proto3.TestAllTypesProto3')
+        begin
+          test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode(
+              request.protobuf_payload)
+        rescue Google::Protobuf::ParseError => err
+          response.parse_error = err.message.encode('utf-8')
+          return response
+        end
+      elsif request.message_type.eql?('protobuf_test_messages.proto2.TestAllTypesProto2')
+        response.skipped = "Ruby doesn't support proto2"
         return response
+      else 
+        fail "Protobuf request doesn't have specific payload type"
       end
 
     when :json_payload
       begin
-        test_message = ProtobufTestMessages::Proto3::TestAllTypes.decode_json(
+        test_message = ProtobufTestMessages::Proto3::TestAllTypesProto3.decode_json(
             request.json_payload)
       rescue Google::Protobuf::ParseError => err
         response.parse_error = err.message.encode('utf-8')
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index 0dd7787..b1ff688 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -35,6 +35,7 @@
 #include "conformance.pb.h"
 #include "conformance_test.h"
 #include <google/protobuf/test_messages_proto3.pb.h>
+#include <google/protobuf/test_messages_proto2.pb.h>
 
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringprintf.h>
@@ -59,7 +60,8 @@
 using google::protobuf::util::MessageDifferencer;
 using google::protobuf::util::NewTypeResolverForDescriptorPool;
 using google::protobuf::util::Status;
-using protobuf_test_messages::proto3::TestAllTypes;
+using protobuf_test_messages::proto3::TestAllTypesProto3;
+using protobuf_test_messages::proto2::TestAllTypesProto2;
 using std::string;
 
 namespace {
@@ -163,8 +165,10 @@
 #define UNKNOWN_FIELD 666
 
 const FieldDescriptor* GetFieldForType(FieldDescriptor::Type type,
-                                       bool repeated) {
-  const Descriptor* d = TestAllTypes().GetDescriptor();
+                                       bool repeated, bool isProto3) {
+
+  const Descriptor* d = isProto3 ?
+      TestAllTypesProto3().GetDescriptor() : TestAllTypesProto2().GetDescriptor();
   for (int i = 0; i < d->field_count(); i++) {
     const FieldDescriptor* f = d->field(i);
     if (f->type() == type && f->is_repeated() == repeated) {
@@ -271,10 +275,19 @@
 void ConformanceTestSuite::RunValidInputTest(
     const string& test_name, ConformanceLevel level, const string& input,
     WireFormat input_format, const string& equivalent_text_format,
-    WireFormat requested_output) {
-  TestAllTypes reference_message;
+    WireFormat requested_output, bool isProto3) {
+  auto newTestMessage = [&isProto3]() {
+    Message* newMessage;
+    if (isProto3) {
+      newMessage = new TestAllTypesProto3;
+    } else {
+      newMessage = new TestAllTypesProto2;
+    }
+    return newMessage;
+  };
+  Message* reference_message = newTestMessage();
   GOOGLE_CHECK(
-      TextFormat::ParseFromString(equivalent_text_format, &reference_message))
+      TextFormat::ParseFromString(equivalent_text_format, reference_message))
           << "Failed to parse data for test case: " << test_name
           << ", data: " << equivalent_text_format;
 
@@ -282,13 +295,21 @@
   ConformanceResponse response;
 
   switch (input_format) {
-    case conformance::PROTOBUF:
+    case conformance::PROTOBUF: {
       request.set_protobuf_payload(input);
+      if (isProto3) {
+        request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
+      } else {
+        request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2");
+      }
       break;
+    }
 
-    case conformance::JSON:
+    case conformance::JSON: {
+      request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
       request.set_json_payload(input);
       break;
+    }
 
     default:
       GOOGLE_LOG(FATAL) << "Unspecified input format";
@@ -298,7 +319,7 @@
 
   RunTest(test_name, request, &response);
 
-  TestAllTypes test_message;
+  Message *test_message = newTestMessage();
 
   switch (response.result_case()) {
     case ConformanceResponse::RESULT_NOT_SET:
@@ -334,10 +355,10 @@
         return;
       }
 
-      if (!test_message.ParseFromString(binary_protobuf)) {
+      if (!test_message->ParseFromString(binary_protobuf)) {
         ReportFailure(test_name, level, request, response,
-                      "INTERNAL ERROR: internal JSON->protobuf transcode "
-                      "yielded unparseable proto.");
+                    "INTERNAL ERROR: internal JSON->protobuf transcode "
+                    "yielded unparseable proto.");
         return;
       }
 
@@ -352,9 +373,9 @@
         return;
       }
 
-      if (!test_message.ParseFromString(response.protobuf_payload())) {
+      if (!test_message->ParseFromString(response.protobuf_payload())) {
         ReportFailure(test_name, level, request, response,
-                      "Protobuf output we received from test was unparseable.");
+                   "Protobuf output we received from test was unparseable.");
         return;
       }
 
@@ -373,7 +394,9 @@
   string differences;
   differencer.ReportDifferencesToString(&differences);
 
-  if (differencer.Compare(reference_message, test_message)) {
+  bool check;
+  check = differencer.Compare(*reference_message, *test_message);
+  if (check) {
     ReportSuccess(test_name);
   } else {
     ReportFailure(test_name, level, request, response,
@@ -381,14 +404,19 @@
                   differences.c_str());
   }
 }
-
-// Expect that this precise protobuf will cause a parse error.
-void ConformanceTestSuite::ExpectParseFailureForProto(
-    const string& proto, const string& test_name, ConformanceLevel level) {
+void ConformanceTestSuite::ExpectParseFailureForProtoWithProtoVersion (
+    const string& proto, const string& test_name, ConformanceLevel level,
+    bool isProto3) {
   ConformanceRequest request;
   ConformanceResponse response;
   request.set_protobuf_payload(proto);
+  if (isProto3) {
+    request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
+  } else {
+    request.set_message_type("protobuf_test_messages.proto2.TestAllTypesProto2");
+  }
   string effective_test_name = ConformanceLevelToString(level) +
+      (isProto3 ? ".Proto3" : ".Proto2") +
       ".ProtobufInput." + test_name;
 
   // We don't expect output, but if the program erroneously accepts the protobuf
@@ -406,6 +434,13 @@
   }
 }
 
+// Expect that this precise protobuf will cause a parse error.
+void ConformanceTestSuite::ExpectParseFailureForProto(
+    const string& proto, const string& test_name, ConformanceLevel level) {
+  ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, true);
+  ExpectParseFailureForProtoWithProtoVersion(proto, test_name, level, false);
+}
+
 // Expect that this protobuf will cause a parse error, even if it is followed
 // by valid protobuf data.  We can try running this twice: once with this
 // data verbatim and once with this data followed by some valid data.
@@ -420,41 +455,48 @@
     const string& test_name, ConformanceLevel level, const string& input_json,
     const string& equivalent_text_format) {
   RunValidInputTest(
-      ConformanceLevelToString(level) + ".JsonInput." + test_name +
+      ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name +
       ".ProtobufOutput", level, input_json, conformance::JSON,
-      equivalent_text_format, conformance::PROTOBUF);
+      equivalent_text_format, conformance::PROTOBUF, true);
   RunValidInputTest(
-      ConformanceLevelToString(level) + ".JsonInput." + test_name +
+      ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name +
       ".JsonOutput", level, input_json, conformance::JSON,
-      equivalent_text_format, conformance::JSON);
+      equivalent_text_format, conformance::JSON, true);
 }
 
 void ConformanceTestSuite::RunValidJsonTestWithProtobufInput(
-    const string& test_name, ConformanceLevel level, const TestAllTypes& input,
+    const string& test_name, ConformanceLevel level, const TestAllTypesProto3& input,
     const string& equivalent_text_format) {
   RunValidInputTest(
-      ConformanceLevelToString(level) + ".ProtobufInput." + test_name +
+      ConformanceLevelToString(level) + ".Proto3" + ".ProtobufInput." + test_name +
       ".JsonOutput", level, input.SerializeAsString(), conformance::PROTOBUF,
-      equivalent_text_format, conformance::JSON);
+      equivalent_text_format, conformance::JSON, true);
 }
 
 void ConformanceTestSuite::RunValidProtobufTest(
     const string& test_name, ConformanceLevel level,
-    const string& input_protobuf, const string& equivalent_text_format) {
+    const string& input_protobuf, const string& equivalent_text_format,
+    bool isProto3) {
+  string rname = ".Proto3";
+  if (!isProto3) {
+    rname = ".Proto2";
+  }
   RunValidInputTest(
-      ConformanceLevelToString(level) + ".ProtobufInput." + test_name +
+      ConformanceLevelToString(level) + rname + ".ProtobufInput." + test_name +
       ".ProtobufOutput", level, input_protobuf, conformance::PROTOBUF,
-      equivalent_text_format, conformance::PROTOBUF);
-  RunValidInputTest(
-      ConformanceLevelToString(level) + ".ProtobufInput." + test_name +
-      ".JsonOutput", level, input_protobuf, conformance::PROTOBUF,
-      equivalent_text_format, conformance::JSON);
+      equivalent_text_format, conformance::PROTOBUF, isProto3);
+  if (isProto3) {
+    RunValidInputTest(
+        ConformanceLevelToString(level) + rname + ".ProtobufInput." +  test_name +
+        ".JsonOutput", level, input_protobuf, conformance::PROTOBUF,
+        equivalent_text_format, conformance::JSON, isProto3);
+  }
 }
 
 void ConformanceTestSuite::RunValidProtobufTestWithMessage(
-    const string& test_name, ConformanceLevel level, const TestAllTypes& input,
-    const string& equivalent_text_format) {
-  RunValidProtobufTest(test_name, level, input.SerializeAsString(), equivalent_text_format);
+    const string& test_name, ConformanceLevel level, const Message *input,
+    const string& equivalent_text_format, bool isProto3) {
+  RunValidProtobufTest(test_name, level, input->SerializeAsString(), equivalent_text_format, isProto3);
 }
 
 // According to proto3 JSON specification, JSON serializers follow more strict
@@ -469,9 +511,10 @@
   ConformanceResponse response;
   request.set_json_payload(input_json);
   request.set_requested_output_format(conformance::JSON);
+  request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
 
   string effective_test_name = ConformanceLevelToString(level) +
-      ".JsonInput." + test_name + ".Validator";
+      ".Proto3.JsonInput." + test_name + ".Validator";
 
   RunTest(effective_test_name, request, &response);
 
@@ -507,8 +550,9 @@
   ConformanceRequest request;
   ConformanceResponse response;
   request.set_json_payload(input_json);
+  request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
   string effective_test_name =
-      ConformanceLevelToString(level) + ".JsonInput." + test_name;
+      ConformanceLevelToString(level) + ".Proto3.JsonInput." + test_name;
 
   // We don't expect output, but if the program erroneously accepts the protobuf
   // we let it send its response as this.  We must not leave it unspecified.
@@ -527,7 +571,7 @@
 
 void ConformanceTestSuite::ExpectSerializeFailureForJson(
     const string& test_name, ConformanceLevel level, const string& text_format) {
-  TestAllTypes payload_message;
+  TestAllTypesProto3 payload_message;
   GOOGLE_CHECK(
       TextFormat::ParseFromString(text_format, &payload_message))
           << "Failed to parse: " << text_format;
@@ -535,6 +579,7 @@
   ConformanceRequest request;
   ConformanceResponse response;
   request.set_protobuf_payload(payload_message.SerializeAsString());
+  request.set_message_type("protobuf_test_messages.proto3.TestAllTypesProto3");
   string effective_test_name =
       ConformanceLevelToString(level) + "." + test_name + ".JsonOutput";
   request.set_requested_output_format(conformance::JSON);
@@ -550,6 +595,7 @@
   }
 }
 
+//TODO: proto2?
 void ConformanceTestSuite::TestPrematureEOFForType(FieldDescriptor::Type type) {
   // Incomplete values for each wire type.
   static const string incompletes[6] = {
@@ -561,8 +607,8 @@
     string("abc")       // 32BIT
   };
 
-  const FieldDescriptor* field = GetFieldForType(type, false);
-  const FieldDescriptor* rep_field = GetFieldForType(type, true);
+  const FieldDescriptor* field = GetFieldForType(type, false, true);
+  const FieldDescriptor* rep_field = GetFieldForType(type, true, true);
   WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
       static_cast<WireFormatLite::FieldType>(type));
   const string& incomplete = incompletes[wire_type];
@@ -640,33 +686,36 @@
 void ConformanceTestSuite::TestValidDataForType(
     FieldDescriptor::Type type,
     std::vector<std::pair<std::string, std::string>> values) {
-  const string type_name =
-      UpperCase(string(".") + FieldDescriptor::TypeName(type));
-  WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
-      static_cast<WireFormatLite::FieldType>(type));
-  const FieldDescriptor* field = GetFieldForType(type, false);
-  const FieldDescriptor* rep_field = GetFieldForType(type, true);
+  for (int isProto3 = 0; isProto3 < 2; isProto3++) {
+    const string type_name =
+        UpperCase(string(".") + FieldDescriptor::TypeName(type));
+    WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
+        static_cast<WireFormatLite::FieldType>(type));
+    const FieldDescriptor* field = GetFieldForType(type, false, isProto3);
+    const FieldDescriptor* rep_field = GetFieldForType(type, true, isProto3);
 
-  RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED,
-                       cat(tag(field->number(), wire_type), values[0].first),
-                       field->name() + ": " + values[0].second);
+    RunValidProtobufTest("ValidDataScalar" + type_name, REQUIRED,
+                         cat(tag(field->number(), wire_type), values[0].first),
+                         field->name() + ": " + values[0].second, isProto3);
 
-  string proto;
-  string text = field->name() + ": " + values.back().second;
-  for (size_t i = 0; i < values.size(); i++) {
-    proto += cat(tag(field->number(), wire_type), values[i].first);
+    string proto;
+    string text = field->name() + ": " + values.back().second;
+    for (size_t i = 0; i < values.size(); i++) {
+      proto += cat(tag(field->number(), wire_type), values[i].first);
+    }
+    RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED,
+                         proto, text, isProto3);
+
+    proto.clear();
+    text.clear();
+
+    for (size_t i = 0; i < values.size(); i++) {
+      proto += cat(tag(rep_field->number(), wire_type), values[i].first);
+      text += rep_field->name() + ": " + values[i].second + " ";
+    }
+    RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED,
+                         proto, text, isProto3);
   }
-  RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED,
-                       proto, text);
-
-  proto.clear();
-  text.clear();
-
-  for (size_t i = 0; i < values.size(); i++) {
-    proto += cat(tag(rep_field->number(), wire_type), values[i].first);
-    text += rep_field->name() + ": " + values[i].second + " ";
-  }
-  RunValidProtobufTest("ValidDataRepeated" + type_name, REQUIRED, proto, text);
 }
 
 void ConformanceTestSuite::SetFailureList(const string& filename,
@@ -677,7 +726,7 @@
             std::inserter(expected_to_fail_, expected_to_fail_.end()));
 }
 
-bool ConformanceTestSuite::CheckSetEmpty(const set<string>& set_to_check,
+bool ConformanceTestSuite::CheckSetEmpty(const std::set<string>& set_to_check,
                                          const std::string& write_to_file,
                                          const std::string& msg) {
   if (set_to_check.empty()) {
@@ -685,7 +734,7 @@
   } else {
     StringAppendF(&output_, "\n");
     StringAppendF(&output_, "%s\n\n", msg.c_str());
-    for (set<string>::const_iterator iter = set_to_check.begin();
+    for (std::set<string>::const_iterator iter = set_to_check.begin();
          iter != set_to_check.end(); ++iter) {
       StringAppendF(&output_, "  %s\n", iter->c_str());
     }
@@ -694,7 +743,7 @@
     if (!write_to_file.empty()) {
       std::ofstream os(write_to_file);
       if (os) {
-        for (set<string>::const_iterator iter = set_to_check.begin();
+        for (std::set<string>::const_iterator iter = set_to_check.begin();
              iter != set_to_check.end(); ++iter) {
           os << *iter << "\n";
         }
@@ -708,6 +757,7 @@
   }
 }
 
+// TODO: proto2?
 void ConformanceTestSuite::TestIllegalTags() {
   // field num 0 is illegal
   string nullfield[] = {
@@ -722,6 +772,44 @@
     ExpectParseFailureForProto(nullfield[i], name, REQUIRED);
   }
 }
+template <class MessageType>
+void ConformanceTestSuite::TestOneofMessage (MessageType &message,
+                                             bool isProto3) {
+  message.set_oneof_uint32(0);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroUint32", RECOMMENDED, &message, "oneof_uint32: 0", isProto3);
+  message.mutable_oneof_nested_message()->set_a(0);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroMessage", RECOMMENDED, &message,
+      isProto3 ? "oneof_nested_message: {}" : "oneof_nested_message: {a: 0}",
+      isProto3);
+  message.mutable_oneof_nested_message()->set_a(1);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroMessageSetTwice", RECOMMENDED, &message,
+      "oneof_nested_message: {a: 1}",
+      isProto3);
+  message.set_oneof_string("");
+  RunValidProtobufTestWithMessage(
+      "OneofZeroString", RECOMMENDED, &message, "oneof_string: \"\"", isProto3);
+  message.set_oneof_bytes("");
+  RunValidProtobufTestWithMessage(
+      "OneofZeroBytes", RECOMMENDED, &message, "oneof_bytes: \"\"", isProto3);
+  message.set_oneof_bool(false);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroBool", RECOMMENDED, &message, "oneof_bool: false", isProto3);
+  message.set_oneof_uint64(0);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroUint64", RECOMMENDED, &message, "oneof_uint64: 0", isProto3);
+  message.set_oneof_float(0.0f);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroFloat", RECOMMENDED, &message, "oneof_float: 0", isProto3);
+  message.set_oneof_double(0.0);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroDouble", RECOMMENDED, &message, "oneof_double: 0", isProto3);
+  message.set_oneof_enum(MessageType::FOO);
+  RunValidProtobufTestWithMessage(
+      "OneofZeroEnum", RECOMMENDED, &message, "oneof_enum: FOO", isProto3);
+}
 
 bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
                                     std::string* output) {
@@ -734,7 +822,7 @@
   unexpected_succeeding_tests_.clear();
   type_resolver_.reset(NewTypeResolverForDescriptorPool(
       kTypeUrlPrefix, DescriptorPool::generated_pool()));
-  type_url_ = GetTypeUrl(TestAllTypes::descriptor());
+  type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor());
 
   output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n";
 
@@ -759,6 +847,7 @@
   });
   TestValidDataForType(FieldDescriptor::TYPE_FLOAT, {
     {flt(0.1), "0.1"},
+    {flt(1.00000075e-36), "1.00000075e-36"},
     {flt(3.402823e+38), "3.402823e+38"},  // 3.40282347e+38
     {flt(1.17549435e-38f), "1.17549435e-38"}
   });
@@ -1232,7 +1321,7 @@
       "Int32FieldNegativeWithLeadingZero", REQUIRED,
       R"({"optionalInt32": -01})");
   // String values must follow the same syntax rule. Specifically leading
-  // or traling spaces are not allowed.
+  // or trailing spaces are not allowed.
   ExpectParseFailureForJson(
       "Int32FieldLeadingSpace", REQUIRED,
       R"({"optionalInt32": " 1"})");
@@ -1329,7 +1418,7 @@
       "optional_float: -inf");
   // Non-cannonical Nan will be correctly normalized.
   {
-    TestAllTypes message;
+    TestAllTypesProto3 message;
     // IEEE floating-point standard 32-bit quiet NaN:
     //   0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
     message.set_optional_float(
@@ -1401,7 +1490,7 @@
       "optional_double: -inf");
   // Non-cannonical Nan will be correctly normalized.
   {
-    TestAllTypes message;
+    TestAllTypesProto3 message;
     message.set_optional_double(
         WireFormatLite::DecodeDouble(0x7FFA123456789ABCLL));
     RunValidJsonTestWithProtobufInput(
@@ -1516,9 +1605,10 @@
       "BytesField", REQUIRED,
       R"({"optionalBytes": "AQI="})",
       R"(optional_bytes: "\x01\x02")");
-  ExpectParseFailureForJson(
-      "BytesFieldInvalidBase64Characters", REQUIRED,
-      R"({"optionalBytes": "-_=="})");
+  RunValidJsonTest(
+      "BytesFieldBase64Url", RECOMMENDED,
+      R"({"optionalBytes": "-_"})",
+      R"(optional_bytes: "\xfb")");
 
   // Message fields.
   RunValidJsonTest(
@@ -1531,36 +1621,10 @@
       "OneofFieldDuplicate", REQUIRED,
       R"({"oneofUint32": 1, "oneofString": "test"})");
   // Ensure zero values for oneof make it out/backs.
-  {
-    TestAllTypes message;
-    message.set_oneof_uint32(0);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroUint32", RECOMMENDED, message, "oneof_uint32: 0");
-    message.mutable_oneof_nested_message()->set_a(0);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroMessage", RECOMMENDED, message, "oneof_nested_message: {}");
-    message.set_oneof_string("");
-    RunValidProtobufTestWithMessage(
-        "OneofZeroString", RECOMMENDED, message, "oneof_string: \"\"");
-    message.set_oneof_bytes("");
-    RunValidProtobufTestWithMessage(
-        "OneofZeroBytes", RECOMMENDED, message, "oneof_bytes: \"\"");
-    message.set_oneof_bool(false);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroBool", RECOMMENDED, message, "oneof_bool: false");
-    message.set_oneof_uint64(0);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroUint64", RECOMMENDED, message, "oneof_uint64: 0");
-    message.set_oneof_float(0.0f);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroFloat", RECOMMENDED, message, "oneof_float: 0");
-    message.set_oneof_double(0.0);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroDouble", RECOMMENDED, message, "oneof_double: 0");
-    message.set_oneof_enum(TestAllTypes::FOO);
-    RunValidProtobufTestWithMessage(
-        "OneofZeroEnum", RECOMMENDED, message, "oneof_enum: FOO");
-  }
+  TestAllTypesProto3 messageProto3;
+  TestAllTypesProto2 messageProto2;
+  TestOneofMessage(messageProto3, true);
+  TestOneofMessage(messageProto2, false);
   RunValidJsonTest(
       "OneofZeroUint32", RECOMMENDED,
       R"({"oneofUint32": 0})", "oneof_uint32: 0");
@@ -2202,13 +2266,13 @@
       "Any", REQUIRED,
       R"({
         "optionalAny": {
-          "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes",
+          "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
           "optionalInt32": 12345
         }
       })",
       R"(
         optional_any: {
-          [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes] {
+          [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
             optional_int32: 12345
           }
         }
@@ -2219,7 +2283,7 @@
         "optionalAny": {
           "@type": "type.googleapis.com/google.protobuf.Any",
           "value": {
-            "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes",
+            "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
             "optionalInt32": 12345
           }
         }
@@ -2227,7 +2291,7 @@
       R"(
         optional_any: {
           [type.googleapis.com/google.protobuf.Any] {
-            [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes] {
+            [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
               optional_int32: 12345
             }
           }
@@ -2239,12 +2303,12 @@
       R"({
         "optionalAny": {
           "optionalInt32": 12345,
-          "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes"
+          "@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
         }
       })",
       R"(
         optional_any: {
-          [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypes] {
+          [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
             optional_int32: 12345
           }
         }
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index 4e40a6a..d1a822e 100644
--- a/conformance/conformance_test.h
+++ b/conformance/conformance_test.h
@@ -53,7 +53,7 @@
 
 namespace protobuf_test_messages {
 namespace proto3 {
-class TestAllTypes;
+class TestAllTypesProto3;
 }  // namespace proto3
 }  // namespace protobuf_test_messages
 
@@ -165,7 +165,8 @@
                          const string& input,
                          conformance::WireFormat input_format,
                          const string& equivalent_text_format,
-                         conformance::WireFormat requested_output);
+                         conformance::WireFormat requested_output,
+                         bool isProto3);
   void RunValidJsonTest(const string& test_name,
                         ConformanceLevel level,
                         const string& input_json,
@@ -173,15 +174,17 @@
   void RunValidJsonTestWithProtobufInput(
       const string& test_name,
       ConformanceLevel level,
-      const protobuf_test_messages::proto3::TestAllTypes& input,
+      const protobuf_test_messages::proto3::TestAllTypesProto3& input,
       const string& equivalent_text_format);
   void RunValidProtobufTest(const string& test_name, ConformanceLevel level,
                             const string& input_protobuf,
-                            const string& equivalent_text_format);
+                            const string& equivalent_text_format,
+                            bool isProto3);
   void RunValidProtobufTestWithMessage(
       const string& test_name, ConformanceLevel level,
-      const protobuf_test_messages::proto3::TestAllTypes& input,
-      const string& equivalent_text_format);
+      const Message *input,
+      const string& equivalent_text_format,
+      bool isProto3);
 
   typedef std::function<bool(const Json::Value&)> Validator;
   void RunValidJsonTestWithValidator(const string& test_name,
@@ -194,6 +197,10 @@
   void ExpectSerializeFailureForJson(const string& test_name,
                                      ConformanceLevel level,
                                      const string& text_format);
+  void ExpectParseFailureForProtoWithProtoVersion (const string& proto,
+                                                   const string& test_name,
+                                                   ConformanceLevel level,
+                                                   bool isProto3);
   void ExpectParseFailureForProto(const std::string& proto,
                                   const std::string& test_name,
                                   ConformanceLevel level);
@@ -202,10 +209,13 @@
                                       ConformanceLevel level);
   void TestPrematureEOFForType(google::protobuf::FieldDescriptor::Type type);
   void TestIllegalTags();
+  template <class MessageType>
+  void TestOneofMessage (MessageType &message,
+                         bool isProto3);
   void TestValidDataForType(
       google::protobuf::FieldDescriptor::Type,
       std::vector<std::pair<std::string, std::string>> values);
-  bool CheckSetEmpty(const set<string>& set_to_check,
+  bool CheckSetEmpty(const std::set<string>& set_to_check,
                      const std::string& write_to_file, const std::string& msg);
   ConformanceTestRunner* runner_;
   int successes_;
diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt
index 8a4fa7e..8c32889 100644
--- a/conformance/failure_list_cpp.txt
+++ b/conformance/failure_list_cpp.txt
@@ -10,35 +10,48 @@
 Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
 Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.JsonInput.BoolFieldDoubleQuotedFalse
-Recommended.JsonInput.BoolFieldDoubleQuotedTrue
-Recommended.JsonInput.FieldMaskInvalidCharacter
-Recommended.JsonInput.FieldNameDuplicate
-Recommended.JsonInput.FieldNameDuplicateDifferentCasing1
-Recommended.JsonInput.FieldNameDuplicateDifferentCasing2
-Recommended.JsonInput.FieldNameNotQuoted
-Recommended.JsonInput.MapFieldValueIsNull
-Recommended.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.JsonInput.RepeatedFieldTrailingComma
-Recommended.JsonInput.RepeatedFieldTrailingCommaWithNewlines
-Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpace
-Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
-Recommended.JsonInput.StringFieldSingleQuoteBoth
-Recommended.JsonInput.StringFieldSingleQuoteKey
-Recommended.JsonInput.StringFieldSingleQuoteValue
-Recommended.JsonInput.StringFieldUppercaseEscapeLetter
-Recommended.JsonInput.TrailingCommaInAnObject
-Recommended.JsonInput.TrailingCommaInAnObjectWithNewlines
-Recommended.JsonInput.TrailingCommaInAnObjectWithSpace
-Recommended.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInPackedField.BOOL
-Required.ProtobufInput.PrematureEofInPackedField.ENUM
-Required.ProtobufInput.PrematureEofInPackedField.INT32
-Required.ProtobufInput.PrematureEofInPackedField.INT64
-Required.ProtobufInput.PrematureEofInPackedField.SINT32
-Required.ProtobufInput.PrematureEofInPackedField.SINT64
-Required.ProtobufInput.PrematureEofInPackedField.UINT32
-Required.ProtobufInput.PrematureEofInPackedField.UINT64
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Recommended.Proto3.JsonInput.FieldNameDuplicate
+Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1
+Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2
+Recommended.Proto3.JsonInput.FieldNameNotQuoted
+Recommended.Proto3.JsonInput.MapFieldValueIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingComma
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace
+Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
+Recommended.Proto3.JsonInput.StringFieldUppercaseEscapeLetter
+Recommended.Proto3.JsonInput.TrailingCommaInAnObject
+Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines
+Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace
+Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64
+
diff --git a/conformance/failure_list_csharp.txt b/conformance/failure_list_csharp.txt
index 922db94..2a20aa7 100644
--- a/conformance/failure_list_csharp.txt
+++ b/conformance/failure_list_csharp.txt
@@ -1,4 +1,2 @@
-Required.ProtobufInput.IllegalZeroFieldNum_Case_0
-Required.ProtobufInput.IllegalZeroFieldNum_Case_1
-Required.ProtobufInput.IllegalZeroFieldNum_Case_2
-Required.ProtobufInput.IllegalZeroFieldNum_Case_3
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
diff --git a/conformance/failure_list_java.txt b/conformance/failure_list_java.txt
index 632940e..5116c56 100644
--- a/conformance/failure_list_java.txt
+++ b/conformance/failure_list_java.txt
@@ -7,39 +7,41 @@
 Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
 Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.JsonInput.BoolFieldAllCapitalFalse
-Recommended.JsonInput.BoolFieldAllCapitalTrue
-Recommended.JsonInput.BoolFieldCamelCaseFalse
-Recommended.JsonInput.BoolFieldCamelCaseTrue
-Recommended.JsonInput.BoolFieldDoubleQuotedFalse
-Recommended.JsonInput.BoolFieldDoubleQuotedTrue
-Recommended.JsonInput.BoolMapFieldKeyNotQuoted
-Recommended.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.JsonInput.DoubleFieldNanNotQuoted
-Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.JsonInput.FieldMaskInvalidCharacter
-Recommended.JsonInput.FieldNameDuplicate
-Recommended.JsonInput.FieldNameNotQuoted
-Recommended.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.JsonInput.FloatFieldNanNotQuoted
-Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Recommended.JsonInput.Int32MapFieldKeyNotQuoted
-Recommended.JsonInput.Int64MapFieldKeyNotQuoted
-Recommended.JsonInput.JsonWithComments
-Recommended.JsonInput.StringFieldSingleQuoteBoth
-Recommended.JsonInput.StringFieldSingleQuoteKey
-Recommended.JsonInput.StringFieldSingleQuoteValue
-Recommended.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.JsonInput.Uint32MapFieldKeyNotQuoted
-Recommended.JsonInput.Uint64MapFieldKeyNotQuoted
-Required.JsonInput.EnumFieldNotQuoted
-Required.JsonInput.Int32FieldLeadingZero
-Required.JsonInput.Int32FieldNegativeWithLeadingZero
-Required.JsonInput.Int32FieldPlusSign
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-Required.JsonInput.StringFieldNotAString
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
+Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
+Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse
+Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
+Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
+Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Recommended.Proto3.JsonInput.FieldNameDuplicate
+Recommended.Proto3.JsonInput.FieldNameNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.JsonWithComments
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
+Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
+Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
+Required.Proto3.JsonInput.EnumFieldNotQuoted
+Required.Proto3.JsonInput.Int32FieldLeadingZero
+Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
+Required.Proto3.JsonInput.Int32FieldPlusSign
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.Proto3.JsonInput.StringFieldNotAString
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
\ No newline at end of file
diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt
index 5414a2f..eb20f65 100644
--- a/conformance/failure_list_js.txt
+++ b/conformance/failure_list_js.txt
@@ -1,15 +1,19 @@
-Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
+Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
+Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
+Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
+Required.Proto2.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
+Required.Proto2.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
diff --git a/conformance/failure_list_objc.txt b/conformance/failure_list_objc.txt
index 6e0da6c..e34501e 100644
--- a/conformance/failure_list_objc.txt
+++ b/conformance/failure_list_objc.txt
@@ -1,6 +1,2 @@
 # JSON input or output tests are skipped (in conformance_objc.m) as mobile
 # platforms don't support JSON wire format to avoid code bloat.
-Required.ProtobufInput.IllegalZeroFieldNum_Case_0
-Required.ProtobufInput.IllegalZeroFieldNum_Case_1
-Required.ProtobufInput.IllegalZeroFieldNum_Case_2
-Required.ProtobufInput.IllegalZeroFieldNum_Case_3
diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt
index 6dd9391..c1713cb 100644
--- a/conformance/failure_list_php.txt
+++ b/conformance/failure_list_php.txt
@@ -1,611 +1,105 @@
 Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
 Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.JsonInput.BoolFieldAllCapitalFalse
-Recommended.JsonInput.BoolFieldAllCapitalTrue
-Recommended.JsonInput.BoolFieldCamelCaseFalse
-Recommended.JsonInput.BoolFieldCamelCaseTrue
-Recommended.JsonInput.BoolFieldDoubleQuotedFalse
-Recommended.JsonInput.BoolFieldDoubleQuotedTrue
-Recommended.JsonInput.BoolFieldIntegerOne
-Recommended.JsonInput.BoolFieldIntegerZero
-Recommended.JsonInput.BoolMapFieldKeyNotQuoted
-Recommended.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.JsonInput.DoubleFieldNanNotQuoted
-Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.JsonInput.DurationHas9FractionalDigits.Validator
-Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
-Recommended.JsonInput.FieldMaskInvalidCharacter
-Recommended.JsonInput.FieldNameDuplicate
-Recommended.JsonInput.FieldNameDuplicateDifferentCasing1
-Recommended.JsonInput.FieldNameDuplicateDifferentCasing2
-Recommended.JsonInput.FieldNameNotQuoted
-Recommended.JsonInput.FieldNameWithDoubleUnderscores.JsonOutput
-Recommended.JsonInput.FieldNameWithDoubleUnderscores.ProtobufOutput
-Recommended.JsonInput.FieldNameWithDoubleUnderscores.Validator
-Recommended.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.JsonInput.FloatFieldNanNotQuoted
-Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Recommended.JsonInput.Int32MapFieldKeyNotQuoted
-Recommended.JsonInput.Int64FieldBeString.Validator
-Recommended.JsonInput.Int64MapFieldKeyNotQuoted
-Recommended.JsonInput.JsonWithComments
-Recommended.JsonInput.MapFieldKeyIsNull
-Recommended.JsonInput.MapFieldValueIsNull
-Recommended.JsonInput.MissingCommaMultiline
-Recommended.JsonInput.MissingCommaOneLine
-Recommended.JsonInput.MultilineNoSpaces.JsonOutput
-Recommended.JsonInput.MultilineNoSpaces.ProtobufOutput
-Recommended.JsonInput.MultilineWithSpaces.JsonOutput
-Recommended.JsonInput.MultilineWithSpaces.ProtobufOutput
-Recommended.JsonInput.OneLineNoSpaces.JsonOutput
-Recommended.JsonInput.OneLineNoSpaces.ProtobufOutput
-Recommended.JsonInput.OneLineWithSpaces.JsonOutput
-Recommended.JsonInput.OneLineWithSpaces.ProtobufOutput
-Recommended.JsonInput.OneofZeroBool.JsonOutput
-Recommended.JsonInput.OneofZeroBool.ProtobufOutput
-Recommended.JsonInput.OneofZeroBytes.JsonOutput
-Recommended.JsonInput.OneofZeroBytes.ProtobufOutput
-Recommended.JsonInput.OneofZeroDouble.JsonOutput
-Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
-Recommended.JsonInput.OneofZeroEnum.JsonOutput
-Recommended.JsonInput.OneofZeroEnum.ProtobufOutput
-Recommended.JsonInput.OneofZeroFloat.JsonOutput
-Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
-Recommended.JsonInput.OneofZeroMessage.JsonOutput
-Recommended.JsonInput.OneofZeroMessage.ProtobufOutput
-Recommended.JsonInput.OneofZeroString.JsonOutput
-Recommended.JsonInput.OneofZeroString.ProtobufOutput
-Recommended.JsonInput.OneofZeroUint32.JsonOutput
-Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
-Recommended.JsonInput.OneofZeroUint64.JsonOutput
-Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
-Recommended.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.JsonInput.RepeatedFieldTrailingComma
-Recommended.JsonInput.RepeatedFieldTrailingCommaWithNewlines
-Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpace
-Recommended.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
-Recommended.JsonInput.StringEndsWithEscapeChar
-Recommended.JsonInput.StringFieldInvalidEscape
-Recommended.JsonInput.StringFieldSingleQuoteBoth
-Recommended.JsonInput.StringFieldSingleQuoteKey
-Recommended.JsonInput.StringFieldSingleQuoteValue
-Recommended.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.JsonInput.StringFieldUnterminatedEscape
-Recommended.JsonInput.StringFieldUppercaseEscapeLetter
-Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
-Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
-Recommended.JsonInput.TimestampZeroNormalized.Validator
-Recommended.JsonInput.TrailingCommaInAnObject
-Recommended.JsonInput.TrailingCommaInAnObjectWithNewlines
-Recommended.JsonInput.TrailingCommaInAnObjectWithSpace
-Recommended.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
-Recommended.JsonInput.Uint32MapFieldKeyNotQuoted
-Recommended.JsonInput.Uint64FieldBeString.Validator
-Recommended.JsonInput.Uint64MapFieldKeyNotQuoted
-Recommended.ProtobufInput.OneofZeroBool.JsonOutput
-Recommended.ProtobufInput.OneofZeroBool.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroBytes.JsonOutput
-Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroDouble.JsonOutput
-Recommended.ProtobufInput.OneofZeroDouble.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroEnum.JsonOutput
-Recommended.ProtobufInput.OneofZeroEnum.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroFloat.JsonOutput
-Recommended.ProtobufInput.OneofZeroFloat.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroMessage.JsonOutput
-Recommended.ProtobufInput.OneofZeroMessage.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroString.JsonOutput
-Recommended.ProtobufInput.OneofZeroString.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroUint32.JsonOutput
-Recommended.ProtobufInput.OneofZeroUint32.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroUint64.JsonOutput
-Recommended.ProtobufInput.OneofZeroUint64.ProtobufOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
 Required.DurationProtoInputTooLarge.JsonOutput
 Required.DurationProtoInputTooSmall.JsonOutput
-Required.JsonInput.AllFieldAcceptNull.JsonOutput
-Required.JsonInput.AllFieldAcceptNull.ProtobufOutput
-Required.JsonInput.Any.JsonOutput
-Required.JsonInput.Any.ProtobufOutput
-Required.JsonInput.AnyNested.JsonOutput
-Required.JsonInput.AnyNested.ProtobufOutput
-Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
-Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
-Required.JsonInput.AnyWithDuration.JsonOutput
-Required.JsonInput.AnyWithDuration.ProtobufOutput
-Required.JsonInput.AnyWithFieldMask.JsonOutput
-Required.JsonInput.AnyWithFieldMask.ProtobufOutput
-Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
-Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
-Required.JsonInput.AnyWithStruct.JsonOutput
-Required.JsonInput.AnyWithStruct.ProtobufOutput
-Required.JsonInput.AnyWithTimestamp.JsonOutput
-Required.JsonInput.AnyWithTimestamp.ProtobufOutput
-Required.JsonInput.AnyWithValueForInteger.JsonOutput
-Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
-Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
-Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-Required.JsonInput.BoolFieldFalse.JsonOutput
-Required.JsonInput.BoolFieldFalse.ProtobufOutput
-Required.JsonInput.BoolFieldTrue.JsonOutput
-Required.JsonInput.BoolFieldTrue.ProtobufOutput
-Required.JsonInput.BoolMapEscapedKey.JsonOutput
-Required.JsonInput.BoolMapEscapedKey.ProtobufOutput
-Required.JsonInput.BoolMapField.JsonOutput
-Required.JsonInput.BoolMapField.ProtobufOutput
-Required.JsonInput.BytesField.JsonOutput
-Required.JsonInput.BytesField.ProtobufOutput
-Required.JsonInput.BytesFieldInvalidBase64Characters
-Required.JsonInput.BytesRepeatedField.JsonOutput
-Required.JsonInput.BytesRepeatedField.ProtobufOutput
-Required.JsonInput.DoubleFieldInfinity.JsonOutput
-Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
-Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
-Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
-Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.JsonInput.DoubleFieldNan.JsonOutput
-Required.JsonInput.DoubleFieldNan.ProtobufOutput
-Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
-Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
-Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
-Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
-Required.JsonInput.DoubleFieldTooLarge
-Required.JsonInput.DoubleFieldTooSmall
-Required.JsonInput.DurationJsonInputTooLarge
-Required.JsonInput.DurationJsonInputTooSmall
-Required.JsonInput.DurationMaxValue.JsonOutput
-Required.JsonInput.DurationMaxValue.ProtobufOutput
-Required.JsonInput.DurationMinValue.JsonOutput
-Required.JsonInput.DurationMinValue.ProtobufOutput
-Required.JsonInput.DurationMissingS
-Required.JsonInput.DurationRepeatedValue.JsonOutput
-Required.JsonInput.DurationRepeatedValue.ProtobufOutput
-Required.JsonInput.EnumField.JsonOutput
-Required.JsonInput.EnumField.ProtobufOutput
-Required.JsonInput.EnumFieldNotQuoted
-Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
-Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-Required.JsonInput.EnumFieldUnknownValue.Validator
-Required.JsonInput.EnumRepeatedField.JsonOutput
-Required.JsonInput.EnumRepeatedField.ProtobufOutput
-Required.JsonInput.FieldMask.JsonOutput
-Required.JsonInput.FieldMask.ProtobufOutput
-Required.JsonInput.FieldNameEscaped.JsonOutput
-Required.JsonInput.FieldNameEscaped.ProtobufOutput
-Required.JsonInput.FieldNameInLowerCamelCase.Validator
-Required.JsonInput.FieldNameInSnakeCase.JsonOutput
-Required.JsonInput.FieldNameInSnakeCase.ProtobufOutput
-Required.JsonInput.FieldNameWithMixedCases.JsonOutput
-Required.JsonInput.FieldNameWithMixedCases.ProtobufOutput
-Required.JsonInput.FieldNameWithMixedCases.Validator
-Required.JsonInput.FieldNameWithNumbers.JsonOutput
-Required.JsonInput.FieldNameWithNumbers.ProtobufOutput
-Required.JsonInput.FieldNameWithNumbers.Validator
-Required.JsonInput.FloatFieldInfinity.JsonOutput
-Required.JsonInput.FloatFieldInfinity.ProtobufOutput
-Required.JsonInput.FloatFieldMaxNegativeValue.JsonOutput
-Required.JsonInput.FloatFieldMaxNegativeValue.ProtobufOutput
-Required.JsonInput.FloatFieldMaxPositiveValue.JsonOutput
-Required.JsonInput.FloatFieldMaxPositiveValue.ProtobufOutput
-Required.JsonInput.FloatFieldMinNegativeValue.JsonOutput
-Required.JsonInput.FloatFieldMinNegativeValue.ProtobufOutput
-Required.JsonInput.FloatFieldMinPositiveValue.JsonOutput
-Required.JsonInput.FloatFieldMinPositiveValue.ProtobufOutput
-Required.JsonInput.FloatFieldNan.JsonOutput
-Required.JsonInput.FloatFieldNan.ProtobufOutput
-Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
-Required.JsonInput.FloatFieldQuotedValue.JsonOutput
-Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
-Required.JsonInput.FloatFieldTooLarge
-Required.JsonInput.FloatFieldTooSmall
-Required.JsonInput.HelloWorld.JsonOutput
-Required.JsonInput.HelloWorld.ProtobufOutput
-Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
-Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
-Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
-Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
-Required.JsonInput.Int32FieldLeadingSpace
-Required.JsonInput.Int32FieldLeadingZero
-Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
-Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-Required.JsonInput.Int32FieldMaxValue.JsonOutput
-Required.JsonInput.Int32FieldMaxValue.ProtobufOutput
-Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
-Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
-Required.JsonInput.Int32FieldMinValue.JsonOutput
-Required.JsonInput.Int32FieldMinValue.ProtobufOutput
-Required.JsonInput.Int32FieldNegativeWithLeadingZero
-Required.JsonInput.Int32FieldNotInteger
-Required.JsonInput.Int32FieldNotNumber
-Required.JsonInput.Int32FieldPlusSign
-Required.JsonInput.Int32FieldStringValue.JsonOutput
-Required.JsonInput.Int32FieldStringValue.ProtobufOutput
-Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
-Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
-Required.JsonInput.Int32FieldTooLarge
-Required.JsonInput.Int32FieldTooSmall
-Required.JsonInput.Int32FieldTrailingSpace
-Required.JsonInput.Int32MapEscapedKey.JsonOutput
-Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
-Required.JsonInput.Int32MapField.JsonOutput
-Required.JsonInput.Int32MapField.ProtobufOutput
-Required.JsonInput.Int64FieldMaxValue.JsonOutput
-Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
-Required.JsonInput.Int64FieldMaxValueNotQuoted.JsonOutput
-Required.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
-Required.JsonInput.Int64FieldMinValue.JsonOutput
-Required.JsonInput.Int64FieldMinValue.ProtobufOutput
-Required.JsonInput.Int64FieldMinValueNotQuoted.JsonOutput
-Required.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
-Required.JsonInput.Int64FieldNotInteger
-Required.JsonInput.Int64FieldNotNumber
-Required.JsonInput.Int64FieldTooLarge
-Required.JsonInput.Int64FieldTooSmall
-Required.JsonInput.Int64MapEscapedKey.JsonOutput
-Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
-Required.JsonInput.Int64MapField.JsonOutput
-Required.JsonInput.Int64MapField.ProtobufOutput
-Required.JsonInput.MessageField.JsonOutput
-Required.JsonInput.MessageField.ProtobufOutput
-Required.JsonInput.MessageMapField.JsonOutput
-Required.JsonInput.MessageMapField.ProtobufOutput
-Required.JsonInput.MessageRepeatedField.JsonOutput
-Required.JsonInput.MessageRepeatedField.ProtobufOutput
-Required.JsonInput.OneofFieldDuplicate
-Required.JsonInput.OptionalBoolWrapper.JsonOutput
-Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
-Required.JsonInput.OptionalBytesWrapper.JsonOutput
-Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
-Required.JsonInput.OptionalDoubleWrapper.JsonOutput
-Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
-Required.JsonInput.OptionalFloatWrapper.JsonOutput
-Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
-Required.JsonInput.OptionalInt32Wrapper.JsonOutput
-Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
-Required.JsonInput.OptionalInt64Wrapper.JsonOutput
-Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
-Required.JsonInput.OptionalStringWrapper.JsonOutput
-Required.JsonInput.OptionalStringWrapper.ProtobufOutput
-Required.JsonInput.OptionalUint32Wrapper.JsonOutput
-Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
-Required.JsonInput.OptionalUint64Wrapper.JsonOutput
-Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
-Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
-Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
-Required.JsonInput.OriginalProtoFieldName.JsonOutput
-Required.JsonInput.OriginalProtoFieldName.ProtobufOutput
-Required.JsonInput.PrimitiveRepeatedField.JsonOutput
-Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
-Required.JsonInput.RepeatedBoolWrapper.JsonOutput
-Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
-Required.JsonInput.RepeatedBytesWrapper.JsonOutput
-Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
-Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
-Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotMessage
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotString
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotBool
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotString
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotMessage
-Required.JsonInput.RepeatedFloatWrapper.JsonOutput
-Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
-Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
-Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
-Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedStringWrapper.JsonOutput
-Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
-Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
-Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
-Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
-Required.JsonInput.StringField.JsonOutput
-Required.JsonInput.StringField.ProtobufOutput
-Required.JsonInput.StringFieldEscape.JsonOutput
-Required.JsonInput.StringFieldEscape.ProtobufOutput
-Required.JsonInput.StringFieldNotAString
-Required.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.JsonInput.StringFieldUnicode.JsonOutput
-Required.JsonInput.StringFieldUnicode.ProtobufOutput
-Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
-Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
-Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
-Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
-Required.JsonInput.StringRepeatedField.JsonOutput
-Required.JsonInput.StringRepeatedField.ProtobufOutput
-Required.JsonInput.Struct.JsonOutput
-Required.JsonInput.Struct.ProtobufOutput
-Required.JsonInput.TimestampJsonInputLowercaseT
-Required.JsonInput.TimestampJsonInputLowercaseZ
-Required.JsonInput.TimestampJsonInputMissingT
-Required.JsonInput.TimestampJsonInputMissingZ
-Required.JsonInput.TimestampJsonInputTooLarge
-Required.JsonInput.TimestampJsonInputTooSmall
-Required.JsonInput.TimestampMaxValue.JsonOutput
-Required.JsonInput.TimestampMaxValue.ProtobufOutput
-Required.JsonInput.TimestampMinValue.JsonOutput
-Required.JsonInput.TimestampMinValue.ProtobufOutput
-Required.JsonInput.TimestampRepeatedValue.JsonOutput
-Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
-Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
-Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
-Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
-Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
-Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
-Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-Required.JsonInput.Uint32FieldMaxValue.JsonOutput
-Required.JsonInput.Uint32FieldMaxValue.ProtobufOutput
-Required.JsonInput.Uint32FieldNotInteger
-Required.JsonInput.Uint32FieldNotNumber
-Required.JsonInput.Uint32FieldTooLarge
-Required.JsonInput.Uint32MapField.JsonOutput
-Required.JsonInput.Uint32MapField.ProtobufOutput
-Required.JsonInput.Uint64FieldMaxValue.JsonOutput
-Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
-Required.JsonInput.Uint64FieldMaxValueNotQuoted.JsonOutput
-Required.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
-Required.JsonInput.Uint64FieldNotInteger
-Required.JsonInput.Uint64FieldNotNumber
-Required.JsonInput.Uint64FieldTooLarge
-Required.JsonInput.Uint64MapField.JsonOutput
-Required.JsonInput.Uint64MapField.ProtobufOutput
-Required.JsonInput.ValueAcceptBool.JsonOutput
-Required.JsonInput.ValueAcceptBool.ProtobufOutput
-Required.JsonInput.ValueAcceptFloat.JsonOutput
-Required.JsonInput.ValueAcceptFloat.ProtobufOutput
-Required.JsonInput.ValueAcceptInteger.JsonOutput
-Required.JsonInput.ValueAcceptInteger.ProtobufOutput
-Required.JsonInput.ValueAcceptList.JsonOutput
-Required.JsonInput.ValueAcceptList.ProtobufOutput
-Required.JsonInput.ValueAcceptNull.JsonOutput
-Required.JsonInput.ValueAcceptNull.ProtobufOutput
-Required.JsonInput.ValueAcceptObject.JsonOutput
-Required.JsonInput.ValueAcceptObject.ProtobufOutput
-Required.JsonInput.ValueAcceptString.JsonOutput
-Required.JsonInput.ValueAcceptString.ProtobufOutput
-Required.JsonInput.WrapperTypesWithNullValue.JsonOutput
-Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput
-Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.BOOL
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.BYTES
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.DOUBLE
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.ENUM
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FIXED32
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FIXED64
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.FLOAT
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.INT32
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.INT64
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SFIXED32
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SFIXED64
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SINT32
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.SINT64
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.STRING
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.UINT32
-Required.ProtobufInput.PrematureEofBeforeKnownNonRepeatedValue.UINT64
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.BOOL
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.BYTES
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.DOUBLE
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.ENUM
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FIXED32
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FIXED64
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.FLOAT
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.INT32
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.INT64
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SFIXED32
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SFIXED64
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SINT32
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.SINT64
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.STRING
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.UINT32
-Required.ProtobufInput.PrematureEofBeforeKnownRepeatedValue.UINT64
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.BOOL
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.BYTES
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.DOUBLE
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.ENUM
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.FIXED32
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.FIXED64
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.FLOAT
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.INT32
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.INT64
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.MESSAGE
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED32
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.SFIXED64
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.SINT32
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.SINT64
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.STRING
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.UINT32
-Required.ProtobufInput.PrematureEofBeforeUnknownValue.UINT64
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.BYTES
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.STRING
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.BYTES
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.STRING
-Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.BYTES
-Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.MESSAGE
-Required.ProtobufInput.PrematureEofInDelimitedDataForUnknownValue.STRING
-Required.ProtobufInput.PrematureEofInPackedField.BOOL
-Required.ProtobufInput.PrematureEofInPackedField.DOUBLE
-Required.ProtobufInput.PrematureEofInPackedField.ENUM
-Required.ProtobufInput.PrematureEofInPackedField.FIXED32
-Required.ProtobufInput.PrematureEofInPackedField.FIXED64
-Required.ProtobufInput.PrematureEofInPackedField.FLOAT
-Required.ProtobufInput.PrematureEofInPackedField.INT32
-Required.ProtobufInput.PrematureEofInPackedField.INT64
-Required.ProtobufInput.PrematureEofInPackedField.SFIXED32
-Required.ProtobufInput.PrematureEofInPackedField.SFIXED64
-Required.ProtobufInput.PrematureEofInPackedField.SINT32
-Required.ProtobufInput.PrematureEofInPackedField.SINT64
-Required.ProtobufInput.PrematureEofInPackedField.UINT32
-Required.ProtobufInput.PrematureEofInPackedField.UINT64
-Required.ProtobufInput.PrematureEofInPackedFieldValue.BOOL
-Required.ProtobufInput.PrematureEofInPackedFieldValue.DOUBLE
-Required.ProtobufInput.PrematureEofInPackedFieldValue.ENUM
-Required.ProtobufInput.PrematureEofInPackedFieldValue.FIXED32
-Required.ProtobufInput.PrematureEofInPackedFieldValue.FIXED64
-Required.ProtobufInput.PrematureEofInPackedFieldValue.FLOAT
-Required.ProtobufInput.PrematureEofInPackedFieldValue.INT32
-Required.ProtobufInput.PrematureEofInPackedFieldValue.INT64
-Required.ProtobufInput.PrematureEofInPackedFieldValue.SFIXED32
-Required.ProtobufInput.PrematureEofInPackedFieldValue.SFIXED64
-Required.ProtobufInput.PrematureEofInPackedFieldValue.SINT32
-Required.ProtobufInput.PrematureEofInPackedFieldValue.SINT64
-Required.ProtobufInput.PrematureEofInPackedFieldValue.UINT32
-Required.ProtobufInput.PrematureEofInPackedFieldValue.UINT64
-Required.ProtobufInput.PrematureEofInSubmessageValue.MESSAGE
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BOOL
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.BYTES
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.DOUBLE
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.ENUM
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FIXED32
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FIXED64
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.FLOAT
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT32
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.INT64
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SFIXED32
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SFIXED64
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT32
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.SINT64
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.STRING
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT32
-Required.ProtobufInput.PrematureEofInsideKnownNonRepeatedValue.UINT64
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.BOOL
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.BYTES
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.DOUBLE
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.ENUM
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FIXED32
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FIXED64
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.FLOAT
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.INT32
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.INT64
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SFIXED32
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SFIXED64
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SINT32
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.SINT64
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.STRING
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.UINT32
-Required.ProtobufInput.PrematureEofInsideKnownRepeatedValue.UINT64
-Required.ProtobufInput.PrematureEofInsideUnknownValue.BOOL
-Required.ProtobufInput.PrematureEofInsideUnknownValue.BYTES
-Required.ProtobufInput.PrematureEofInsideUnknownValue.DOUBLE
-Required.ProtobufInput.PrematureEofInsideUnknownValue.ENUM
-Required.ProtobufInput.PrematureEofInsideUnknownValue.FIXED32
-Required.ProtobufInput.PrematureEofInsideUnknownValue.FIXED64
-Required.ProtobufInput.PrematureEofInsideUnknownValue.FLOAT
-Required.ProtobufInput.PrematureEofInsideUnknownValue.INT32
-Required.ProtobufInput.PrematureEofInsideUnknownValue.INT64
-Required.ProtobufInput.PrematureEofInsideUnknownValue.MESSAGE
-Required.ProtobufInput.PrematureEofInsideUnknownValue.SFIXED32
-Required.ProtobufInput.PrematureEofInsideUnknownValue.SFIXED64
-Required.ProtobufInput.PrematureEofInsideUnknownValue.SINT32
-Required.ProtobufInput.PrematureEofInsideUnknownValue.SINT64
-Required.ProtobufInput.PrematureEofInsideUnknownValue.STRING
-Required.ProtobufInput.PrematureEofInsideUnknownValue.UINT32
-Required.ProtobufInput.PrematureEofInsideUnknownValue.UINT64
-Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.BOOL.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.DOUBLE.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FLOAT.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.INT32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.INT64.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.INT64.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SFIXED64.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SINT32.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SINT32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SINT64.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.SINT64.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.UINT32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.BOOL.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.BOOL.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.DOUBLE.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.DOUBLE.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.FIXED32.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.FIXED32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.FIXED64.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.FIXED64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.FLOAT.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.INT32.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.INT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.INT64.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.INT64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SFIXED32.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.SFIXED32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SFIXED64.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.SFIXED64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SINT32.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.SINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.SINT64.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.SINT64.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.UINT32.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.UINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataRepeated.UINT64.JsonOutput
-Required.ProtobufInput.ValidDataRepeated.UINT64.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.BOOL.JsonOutput
-Required.ProtobufInput.ValidDataScalar.BOOL.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.DOUBLE.JsonOutput
-Required.ProtobufInput.ValidDataScalar.DOUBLE.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.FIXED32.JsonOutput
-Required.ProtobufInput.ValidDataScalar.FIXED32.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.FIXED64.JsonOutput
-Required.ProtobufInput.ValidDataScalar.FIXED64.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.FLOAT.JsonOutput
-Required.ProtobufInput.ValidDataScalar.FLOAT.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.INT32.JsonOutput
-Required.ProtobufInput.ValidDataScalar.INT32.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.INT64.JsonOutput
-Required.ProtobufInput.ValidDataScalar.INT64.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.SFIXED32.JsonOutput
-Required.ProtobufInput.ValidDataScalar.SFIXED32.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.SFIXED64.JsonOutput
-Required.ProtobufInput.ValidDataScalar.SFIXED64.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.SINT32.JsonOutput
-Required.ProtobufInput.ValidDataScalar.SINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.SINT64.JsonOutput
-Required.ProtobufInput.ValidDataScalar.SINT64.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.UINT32.JsonOutput
-Required.ProtobufInput.ValidDataScalar.UINT32.ProtobufOutput
-Required.ProtobufInput.ValidDataScalar.UINT64.JsonOutput
-Required.ProtobufInput.ValidDataScalar.UINT64.ProtobufOutput
+Required.Proto3.JsonInput.Any.JsonOutput
+Required.Proto3.JsonInput.Any.ProtobufOutput
+Required.Proto3.JsonInput.AnyNested.JsonOutput
+Required.Proto3.JsonInput.AnyNested.ProtobufOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
+Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
+Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMinValue.JsonOutput
+Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.FieldMask.JsonOutput
+Required.Proto3.JsonInput.FieldMask.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.Struct.JsonOutput
+Required.Proto3.JsonInput.Struct.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptString.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
 Required.TimestampProtoInputTooLarge.JsonOutput
 Required.TimestampProtoInputTooSmall.JsonOutput
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.Int32FieldNotInteger
+Required.Proto3.JsonInput.Int64FieldNotInteger
+Required.Proto3.JsonInput.Uint32FieldNotInteger
+Required.Proto3.JsonInput.Uint64FieldNotInteger
+Required.Proto3.JsonInput.Int32FieldLeadingSpace
+Required.Proto3.JsonInput.OneofFieldDuplicate
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt
index f53449f..088708e 100644
--- a/conformance/failure_list_php_c.txt
+++ b/conformance/failure_list_php_c.txt
@@ -1,227 +1,182 @@
 Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
 Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.JsonInput.BoolFieldIntegerOne
-Recommended.JsonInput.BoolFieldIntegerZero
-Recommended.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.JsonInput.DurationHas9FractionalDigits.Validator
-Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
-Recommended.JsonInput.Int64FieldBeString.Validator
-Recommended.JsonInput.MapFieldValueIsNull
-Recommended.JsonInput.OneofZeroBool.JsonOutput
-Recommended.JsonInput.OneofZeroBool.ProtobufOutput
-Recommended.JsonInput.OneofZeroBytes.JsonOutput
-Recommended.JsonInput.OneofZeroBytes.ProtobufOutput
-Recommended.JsonInput.OneofZeroDouble.JsonOutput
-Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
-Recommended.JsonInput.OneofZeroEnum.JsonOutput
-Recommended.JsonInput.OneofZeroEnum.ProtobufOutput
-Recommended.JsonInput.OneofZeroFloat.JsonOutput
-Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
-Recommended.JsonInput.OneofZeroString.JsonOutput
-Recommended.JsonInput.OneofZeroString.ProtobufOutput
-Recommended.JsonInput.OneofZeroUint32.JsonOutput
-Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
-Recommended.JsonInput.OneofZeroUint64.JsonOutput
-Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
-Recommended.JsonInput.RepeatedFieldMessageElementIsNull
-Recommended.JsonInput.RepeatedFieldPrimitiveElementIsNull
-Recommended.JsonInput.StringEndsWithEscapeChar
-Recommended.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
-Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
-Recommended.JsonInput.TimestampZeroNormalized.Validator
-Recommended.JsonInput.Uint64FieldBeString.Validator
-Recommended.ProtobufInput.OneofZeroBool.JsonOutput
-Recommended.ProtobufInput.OneofZeroBool.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroBytes.JsonOutput
-Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroDouble.JsonOutput
-Recommended.ProtobufInput.OneofZeroDouble.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroEnum.JsonOutput
-Recommended.ProtobufInput.OneofZeroEnum.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroFloat.JsonOutput
-Recommended.ProtobufInput.OneofZeroFloat.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroString.JsonOutput
-Recommended.ProtobufInput.OneofZeroString.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroUint32.JsonOutput
-Recommended.ProtobufInput.OneofZeroUint32.ProtobufOutput
-Recommended.ProtobufInput.OneofZeroUint64.JsonOutput
-Recommended.ProtobufInput.OneofZeroUint64.ProtobufOutput
+Recommended.Proto3.JsonInput.BoolFieldIntegerOne
+Recommended.Proto3.JsonInput.BoolFieldIntegerZero
+Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.Int64FieldBeString.Validator
+Recommended.Proto3.JsonInput.MapFieldValueIsNull
+Recommended.Proto3.JsonInput.OneofZeroBytes.JsonOutput
+Recommended.Proto3.JsonInput.OneofZeroBytes.ProtobufOutput
+Recommended.Proto3.JsonInput.OneofZeroString.JsonOutput
+Recommended.Proto3.JsonInput.OneofZeroString.ProtobufOutput
+Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
+Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator
+Recommended.Proto3.ProtobufInput.OneofZeroBytes.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroBytes.ProtobufOutput
+Recommended.Proto3.ProtobufInput.OneofZeroString.JsonOutput
+Recommended.Proto3.ProtobufInput.OneofZeroString.ProtobufOutput
 Required.DurationProtoInputTooLarge.JsonOutput
 Required.DurationProtoInputTooSmall.JsonOutput
-Required.JsonInput.AllFieldAcceptNull.ProtobufOutput
-Required.JsonInput.Any.JsonOutput
-Required.JsonInput.Any.ProtobufOutput
-Required.JsonInput.AnyNested.JsonOutput
-Required.JsonInput.AnyNested.ProtobufOutput
-Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
-Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
-Required.JsonInput.AnyWithDuration.JsonOutput
-Required.JsonInput.AnyWithDuration.ProtobufOutput
-Required.JsonInput.AnyWithFieldMask.JsonOutput
-Required.JsonInput.AnyWithFieldMask.ProtobufOutput
-Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
-Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
-Required.JsonInput.AnyWithStruct.JsonOutput
-Required.JsonInput.AnyWithStruct.ProtobufOutput
-Required.JsonInput.AnyWithTimestamp.JsonOutput
-Required.JsonInput.AnyWithTimestamp.ProtobufOutput
-Required.JsonInput.AnyWithValueForInteger.JsonOutput
-Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
-Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
-Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-Required.JsonInput.BoolFieldFalse.ProtobufOutput
-Required.JsonInput.BoolMapField.JsonOutput
-Required.JsonInput.DoubleFieldInfinity.JsonOutput
-Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
-Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
-Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
-Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.JsonInput.DoubleFieldNan.JsonOutput
-Required.JsonInput.DoubleFieldNan.ProtobufOutput
-Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
-Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
-Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
-Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
-Required.JsonInput.DurationMaxValue.JsonOutput
-Required.JsonInput.DurationMaxValue.ProtobufOutput
-Required.JsonInput.DurationMinValue.JsonOutput
-Required.JsonInput.DurationMinValue.ProtobufOutput
-Required.JsonInput.DurationRepeatedValue.JsonOutput
-Required.JsonInput.DurationRepeatedValue.ProtobufOutput
-Required.JsonInput.EnumField.ProtobufOutput
-Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
-Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-Required.JsonInput.EnumFieldUnknownValue.Validator
-Required.JsonInput.FieldMask.JsonOutput
-Required.JsonInput.FieldMask.ProtobufOutput
-Required.JsonInput.FloatFieldInfinity.JsonOutput
-Required.JsonInput.FloatFieldInfinity.ProtobufOutput
-Required.JsonInput.FloatFieldNan.JsonOutput
-Required.JsonInput.FloatFieldNan.ProtobufOutput
-Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
-Required.JsonInput.FloatFieldQuotedValue.JsonOutput
-Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
-Required.JsonInput.FloatFieldTooLarge
-Required.JsonInput.FloatFieldTooSmall
-Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
-Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
-Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
-Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
-Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
-Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
-Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
-Required.JsonInput.Int32FieldStringValue.JsonOutput
-Required.JsonInput.Int32FieldStringValue.ProtobufOutput
-Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
-Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
-Required.JsonInput.Int64FieldMaxValue.JsonOutput
-Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
-Required.JsonInput.Int64FieldMinValue.JsonOutput
-Required.JsonInput.Int64FieldMinValue.ProtobufOutput
-Required.JsonInput.MessageField.JsonOutput
-Required.JsonInput.MessageField.ProtobufOutput
-Required.JsonInput.OptionalBoolWrapper.JsonOutput
-Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
-Required.JsonInput.OptionalBytesWrapper.JsonOutput
-Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
-Required.JsonInput.OptionalDoubleWrapper.JsonOutput
-Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
-Required.JsonInput.OptionalFloatWrapper.JsonOutput
-Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
-Required.JsonInput.OptionalInt32Wrapper.JsonOutput
-Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
-Required.JsonInput.OptionalInt64Wrapper.JsonOutput
-Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
-Required.JsonInput.OptionalStringWrapper.JsonOutput
-Required.JsonInput.OptionalStringWrapper.ProtobufOutput
-Required.JsonInput.OptionalUint32Wrapper.JsonOutput
-Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
-Required.JsonInput.OptionalUint64Wrapper.JsonOutput
-Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
-Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
-Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
-Required.JsonInput.RepeatedBoolWrapper.JsonOutput
-Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
-Required.JsonInput.RepeatedBytesWrapper.JsonOutput
-Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
-Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
-Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-Required.JsonInput.RepeatedFloatWrapper.JsonOutput
-Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
-Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
-Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
-Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedStringWrapper.JsonOutput
-Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
-Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
-Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
-Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
-Required.JsonInput.StringFieldEscape.JsonOutput
-Required.JsonInput.StringFieldEscape.ProtobufOutput
-Required.JsonInput.StringFieldNotAString
-Required.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
-Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
-Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
-Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
-Required.JsonInput.Struct.JsonOutput
-Required.JsonInput.Struct.ProtobufOutput
-Required.JsonInput.TimestampMaxValue.JsonOutput
-Required.JsonInput.TimestampMaxValue.ProtobufOutput
-Required.JsonInput.TimestampMinValue.JsonOutput
-Required.JsonInput.TimestampMinValue.ProtobufOutput
-Required.JsonInput.TimestampRepeatedValue.JsonOutput
-Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
-Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
-Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
-Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
-Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
-Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
-Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-Required.JsonInput.Uint64FieldMaxValue.JsonOutput
-Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
-Required.JsonInput.ValueAcceptBool.JsonOutput
-Required.JsonInput.ValueAcceptBool.ProtobufOutput
-Required.JsonInput.ValueAcceptFloat.JsonOutput
-Required.JsonInput.ValueAcceptFloat.ProtobufOutput
-Required.JsonInput.ValueAcceptInteger.JsonOutput
-Required.JsonInput.ValueAcceptInteger.ProtobufOutput
-Required.JsonInput.ValueAcceptList.JsonOutput
-Required.JsonInput.ValueAcceptList.ProtobufOutput
-Required.JsonInput.ValueAcceptNull.JsonOutput
-Required.JsonInput.ValueAcceptNull.ProtobufOutput
-Required.JsonInput.ValueAcceptObject.JsonOutput
-Required.JsonInput.ValueAcceptObject.ProtobufOutput
-Required.JsonInput.ValueAcceptString.JsonOutput
-Required.JsonInput.ValueAcceptString.ProtobufOutput
-Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput
-Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
-Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
+Required.Proto3.JsonInput.Any.JsonOutput
+Required.Proto3.JsonInput.Any.ProtobufOutput
+Required.Proto3.JsonInput.AnyNested.JsonOutput
+Required.Proto3.JsonInput.AnyNested.ProtobufOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
+Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
+Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.BoolMapField.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldInfinity.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldInfinity.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldNan.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldQuotedValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMinValue.JsonOutput
+Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueZero.JsonOutput
+Required.Proto3.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator
+Required.Proto3.JsonInput.FieldMask.JsonOutput
+Required.Proto3.JsonInput.FieldMask.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldInfinity.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNan.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldQuotedValue.JsonOutput
+Required.Proto3.JsonInput.FloatFieldQuotedValue.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.Int32FieldExponentialFormat.JsonOutput
+Required.Proto3.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldMaxFloatValue.JsonOutput
+Required.Proto3.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldMinFloatValue.JsonOutput
+Required.Proto3.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldStringValue.JsonOutput
+Required.Proto3.JsonInput.Int32FieldStringValue.ProtobufOutput
+Required.Proto3.JsonInput.Int32FieldStringValueEscaped.JsonOutput
+Required.Proto3.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
+Required.Proto3.JsonInput.Int64FieldMaxValue.JsonOutput
+Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.Int64FieldMinValue.JsonOutput
+Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput
+Required.Proto3.JsonInput.MessageField.JsonOutput
+Required.Proto3.JsonInput.MessageField.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingMessagesGotInt
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldEscape.JsonOutput
+Required.Proto3.JsonInput.StringFieldEscape.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldNotAString
+Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
+Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscape.JsonOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
+Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
+Required.Proto3.JsonInput.Struct.JsonOutput
+Required.Proto3.JsonInput.Struct.ProtobufOutput
+Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+Required.Proto3.JsonInput.Uint64FieldMaxValue.JsonOutput
+Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptString.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
 Required.TimestampProtoInputTooLarge.JsonOutput
 Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_php_zts_c.txt b/conformance/failure_list_php_zts_c.txt
new file mode 100644
index 0000000..d9a8fe3
--- /dev/null
+++ b/conformance/failure_list_php_zts_c.txt
@@ -0,0 +1,225 @@
+Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
+Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
+Recommended.FieldMaskTooManyUnderscore.JsonOutput
+Recommended.JsonInput.BoolFieldIntegerOne
+Recommended.JsonInput.BoolFieldIntegerZero
+Recommended.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.JsonInput.Int64FieldBeString.Validator
+Recommended.JsonInput.OneofZeroBytes.JsonOutput
+Recommended.JsonInput.OneofZeroBytes.ProtobufOutput
+Recommended.JsonInput.OneofZeroDouble.JsonOutput
+Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
+Recommended.JsonInput.OneofZeroFloat.JsonOutput
+Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
+Recommended.JsonInput.OneofZeroString.JsonOutput
+Recommended.JsonInput.OneofZeroString.ProtobufOutput
+Recommended.JsonInput.OneofZeroUint32.JsonOutput
+Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
+Recommended.JsonInput.OneofZeroUint64.JsonOutput
+Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
+Recommended.JsonInput.StringEndsWithEscapeChar
+Recommended.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
+Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
+Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
+Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
+Recommended.JsonInput.TimestampZeroNormalized.Validator
+Recommended.JsonInput.Uint64FieldBeString.Validator
+Recommended.ProtobufInput.OneofZeroBytes.JsonOutput
+Recommended.ProtobufInput.OneofZeroBytes.ProtobufOutput
+Recommended.ProtobufInput.OneofZeroString.JsonOutput
+Recommended.ProtobufInput.OneofZeroString.ProtobufOutput
+Required.DurationProtoInputTooLarge.JsonOutput
+Required.DurationProtoInputTooSmall.JsonOutput
+Required.JsonInput.AllFieldAcceptNull.ProtobufOutput
+Required.JsonInput.Any.JsonOutput
+Required.JsonInput.Any.ProtobufOutput
+Required.JsonInput.AnyNested.JsonOutput
+Required.JsonInput.AnyNested.ProtobufOutput
+Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.JsonInput.AnyWithDuration.JsonOutput
+Required.JsonInput.AnyWithDuration.ProtobufOutput
+Required.JsonInput.AnyWithFieldMask.JsonOutput
+Required.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.JsonInput.AnyWithStruct.JsonOutput
+Required.JsonInput.AnyWithStruct.ProtobufOutput
+Required.JsonInput.AnyWithTimestamp.JsonOutput
+Required.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.JsonInput.BoolFieldFalse.ProtobufOutput
+Required.JsonInput.BoolMapField.JsonOutput
+Required.JsonInput.DoubleFieldInfinity.JsonOutput
+Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
+Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
+Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
+Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
+Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
+Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+Required.JsonInput.DoubleFieldNan.JsonOutput
+Required.JsonInput.DoubleFieldNan.ProtobufOutput
+Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
+Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
+Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
+Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
+Required.JsonInput.DurationMaxValue.JsonOutput
+Required.JsonInput.DurationMaxValue.ProtobufOutput
+Required.JsonInput.DurationMinValue.JsonOutput
+Required.JsonInput.DurationMinValue.ProtobufOutput
+Required.JsonInput.DurationRepeatedValue.JsonOutput
+Required.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.JsonInput.EnumField.ProtobufOutput
+Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
+Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
+Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
+Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
+Required.JsonInput.EnumFieldUnknownValue.Validator
+Required.JsonInput.FieldMask.JsonOutput
+Required.JsonInput.FieldMask.ProtobufOutput
+Required.JsonInput.FloatFieldInfinity.JsonOutput
+Required.JsonInput.FloatFieldInfinity.ProtobufOutput
+Required.JsonInput.FloatFieldNan.JsonOutput
+Required.JsonInput.FloatFieldNan.ProtobufOutput
+Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
+Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
+Required.JsonInput.FloatFieldQuotedValue.JsonOutput
+Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
+Required.JsonInput.FloatFieldTooLarge
+Required.JsonInput.FloatFieldTooSmall
+Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
+Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
+Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
+Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
+Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
+Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
+Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
+Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
+Required.JsonInput.Int32FieldStringValue.JsonOutput
+Required.JsonInput.Int32FieldStringValue.ProtobufOutput
+Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
+Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
+Required.JsonInput.Int32MapEscapedKey.JsonOutput
+Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
+Required.JsonInput.Int32MapField.JsonOutput
+Required.JsonInput.Int32MapField.ProtobufOutput
+Required.JsonInput.Int64FieldMaxValue.JsonOutput
+Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
+Required.JsonInput.Int64FieldMinValue.JsonOutput
+Required.JsonInput.Int64FieldMinValue.ProtobufOutput
+Required.JsonInput.Int64MapEscapedKey.JsonOutput
+Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
+Required.JsonInput.Int64MapField.JsonOutput
+Required.JsonInput.Int64MapField.ProtobufOutput
+Required.JsonInput.MessageField.JsonOutput
+Required.JsonInput.MessageField.ProtobufOutput
+Required.JsonInput.MessageMapField.JsonOutput
+Required.JsonInput.MessageMapField.ProtobufOutput
+Required.JsonInput.MessageRepeatedField.JsonOutput
+Required.JsonInput.MessageRepeatedField.ProtobufOutput
+Required.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.JsonInput.OptionalStringWrapper.JsonOutput
+Required.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.JsonInput.PrimitiveRepeatedField.JsonOutput
+Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
+Required.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
+Required.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.JsonInput.StringFieldEscape.JsonOutput
+Required.JsonInput.StringFieldEscape.ProtobufOutput
+Required.JsonInput.StringFieldNotAString
+Required.JsonInput.StringFieldSurrogatePair.JsonOutput
+Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
+Required.JsonInput.StringFieldUnicodeEscape.JsonOutput
+Required.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
+Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.JsonOutput
+Required.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
+Required.JsonInput.Struct.JsonOutput
+Required.JsonInput.Struct.ProtobufOutput
+Required.JsonInput.TimestampMaxValue.JsonOutput
+Required.JsonInput.TimestampMaxValue.ProtobufOutput
+Required.JsonInput.TimestampMinValue.JsonOutput
+Required.JsonInput.TimestampMinValue.ProtobufOutput
+Required.JsonInput.TimestampRepeatedValue.JsonOutput
+Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
+Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
+Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
+Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
+Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
+Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
+Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
+Required.JsonInput.Uint32MapField.JsonOutput
+Required.JsonInput.Uint32MapField.ProtobufOutput
+Required.JsonInput.Uint64FieldMaxValue.JsonOutput
+Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
+Required.JsonInput.Uint64MapField.JsonOutput
+Required.JsonInput.Uint64MapField.ProtobufOutput
+Required.JsonInput.ValueAcceptBool.JsonOutput
+Required.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.JsonInput.ValueAcceptFloat.JsonOutput
+Required.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.JsonInput.ValueAcceptInteger.JsonOutput
+Required.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.JsonInput.ValueAcceptList.JsonOutput
+Required.JsonInput.ValueAcceptList.ProtobufOutput
+Required.JsonInput.ValueAcceptNull.JsonOutput
+Required.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.JsonInput.ValueAcceptObject.JsonOutput
+Required.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.JsonInput.ValueAcceptString.JsonOutput
+Required.JsonInput.ValueAcceptString.ProtobufOutput
+Required.JsonInput.WrapperTypesWithNullValue.ProtobufOutput
+Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED32.ProtobufOutput
+Required.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
+Required.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
+Required.TimestampProtoInputTooLarge.JsonOutput
+Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt
index 965b821..062c22a 100644
--- a/conformance/failure_list_python.txt
+++ b/conformance/failure_list_python.txt
@@ -1,17 +1,22 @@
-Recommended.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.JsonInput.DoubleFieldNanNotQuoted
-Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.JsonInput.FloatFieldNanNotQuoted
-Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Required.JsonInput.BytesFieldInvalidBase64Characters
-Required.JsonInput.DoubleFieldTooSmall
-Required.JsonInput.EnumFieldUnknownValue.Validator
-Required.JsonInput.FloatFieldTooLarge
-Required.JsonInput.FloatFieldTooSmall
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-Required.JsonInput.TimestampJsonInputLowercaseT
-Required.ProtobufInput.IllegalZeroFieldNum_Case_0
-Required.ProtobufInput.IllegalZeroFieldNum_Case_1
-Required.ProtobufInput.IllegalZeroFieldNum_Case_2
-Required.ProtobufInput.IllegalZeroFieldNum_Case_3
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+Required.Proto3.JsonInput.TimestampJsonInputLowercaseT
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_0
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_1
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_2
+Required.Proto2.ProtobufInput.IllegalZeroFieldNum_Case_3
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_0
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_1
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_2
+Required.Proto3.ProtobufInput.IllegalZeroFieldNum_Case_3
diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt
index 92404d2..e2c258d 100644
--- a/conformance/failure_list_python_cpp.txt
+++ b/conformance/failure_list_python_cpp.txt
@@ -7,32 +7,49 @@
 # TODO(haberman): insert links to corresponding bugs tracking the issue.
 # Should we use GitHub issues or the Google-internal bug tracker?
 
-Recommended.JsonInput.DoubleFieldInfinityNotQuoted
-Recommended.JsonInput.DoubleFieldNanNotQuoted
-Recommended.JsonInput.DoubleFieldNegativeInfinityNotQuoted
-Recommended.JsonInput.FloatFieldInfinityNotQuoted
-Recommended.JsonInput.FloatFieldNanNotQuoted
-Recommended.JsonInput.FloatFieldNegativeInfinityNotQuoted
-Required.JsonInput.BytesFieldInvalidBase64Characters
-Required.JsonInput.DoubleFieldTooSmall
-Required.JsonInput.EnumFieldUnknownValue.Validator
-Required.JsonInput.FloatFieldTooLarge
-Required.JsonInput.FloatFieldTooSmall
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
-Required.JsonInput.TimestampJsonInputLowercaseT
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
-Required.ProtobufInput.PrematureEofInPackedField.BOOL
-Required.ProtobufInput.PrematureEofInPackedField.DOUBLE
-Required.ProtobufInput.PrematureEofInPackedField.ENUM
-Required.ProtobufInput.PrematureEofInPackedField.FIXED32
-Required.ProtobufInput.PrematureEofInPackedField.FIXED64
-Required.ProtobufInput.PrematureEofInPackedField.FLOAT
-Required.ProtobufInput.PrematureEofInPackedField.INT32
-Required.ProtobufInput.PrematureEofInPackedField.INT64
-Required.ProtobufInput.PrematureEofInPackedField.SFIXED32
-Required.ProtobufInput.PrematureEofInPackedField.SFIXED64
-Required.ProtobufInput.PrematureEofInPackedField.SINT32
-Required.ProtobufInput.PrematureEofInPackedField.SINT64
-Required.ProtobufInput.PrematureEofInPackedField.UINT32
-Required.ProtobufInput.PrematureEofInPackedField.UINT64
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted
+Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted
+Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
+Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.EnumFieldUnknownValue.Validator
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingIntegersGotBool
+Required.Proto3.JsonInput.TimestampJsonInputLowercaseT
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.DOUBLE
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.FIXED64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.FLOAT
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SFIXED64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto3.ProtobufInput.PrematureEofInPackedField.UINT64
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.BOOL
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.DOUBLE
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.ENUM
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.FIXED64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.FLOAT
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.INT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SFIXED64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.SINT64
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT32
+Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 1de6c43..45cfaca 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -1,203 +1,137 @@
 Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
 Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
-Recommended.JsonInput.BoolFieldIntegerOne
-Recommended.JsonInput.BoolFieldIntegerZero
-Recommended.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.JsonInput.DurationHas9FractionalDigits.Validator
-Recommended.JsonInput.DurationHasZeroFractionalDigit.Validator
-Recommended.JsonInput.Int64FieldBeString.Validator
-Recommended.JsonInput.OneofZeroDouble.JsonOutput
-Recommended.JsonInput.OneofZeroDouble.ProtobufOutput
-Recommended.JsonInput.OneofZeroFloat.JsonOutput
-Recommended.JsonInput.OneofZeroFloat.ProtobufOutput
-Recommended.JsonInput.OneofZeroUint32.JsonOutput
-Recommended.JsonInput.OneofZeroUint32.ProtobufOutput
-Recommended.JsonInput.OneofZeroUint64.JsonOutput
-Recommended.JsonInput.OneofZeroUint64.ProtobufOutput
-Recommended.JsonInput.StringEndsWithEscapeChar
-Recommended.JsonInput.StringFieldSurrogateInWrongOrder
-Recommended.JsonInput.StringFieldUnpairedHighSurrogate
-Recommended.JsonInput.StringFieldUnpairedLowSurrogate
-Recommended.JsonInput.TimestampHas3FractionalDigits.Validator
-Recommended.JsonInput.TimestampHas6FractionalDigits.Validator
-Recommended.JsonInput.TimestampHas9FractionalDigits.Validator
-Recommended.JsonInput.TimestampHasZeroFractionalDigit.Validator
-Recommended.JsonInput.TimestampZeroNormalized.Validator
-Recommended.JsonInput.Uint64FieldBeString.Validator
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
+Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
+Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.Int64FieldBeString.Validator
+Recommended.Proto3.JsonInput.MapFieldValueIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
+Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
+Recommended.Proto3.JsonInput.StringEndsWithEscapeChar
+Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder
+Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate
+Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate
+Recommended.Proto3.JsonInput.TimestampHas3FractionalDigits.Validator
+Recommended.Proto3.JsonInput.TimestampHas6FractionalDigits.Validator
+Recommended.Proto3.JsonInput.TimestampHas9FractionalDigits.Validator
+Recommended.Proto3.JsonInput.TimestampHasZeroFractionalDigit.Validator
+Recommended.Proto3.JsonInput.TimestampZeroNormalized.Validator
+Recommended.Proto3.JsonInput.Uint64FieldBeString.Validator
 Required.DurationProtoInputTooLarge.JsonOutput
 Required.DurationProtoInputTooSmall.JsonOutput
-Required.JsonInput.Any.JsonOutput
-Required.JsonInput.Any.ProtobufOutput
-Required.JsonInput.AnyNested.JsonOutput
-Required.JsonInput.AnyNested.ProtobufOutput
-Required.JsonInput.AnyUnorderedTypeTag.JsonOutput
-Required.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
-Required.JsonInput.AnyWithDuration.JsonOutput
-Required.JsonInput.AnyWithDuration.ProtobufOutput
-Required.JsonInput.AnyWithFieldMask.JsonOutput
-Required.JsonInput.AnyWithFieldMask.ProtobufOutput
-Required.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
-Required.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
-Required.JsonInput.AnyWithStruct.JsonOutput
-Required.JsonInput.AnyWithStruct.ProtobufOutput
-Required.JsonInput.AnyWithTimestamp.JsonOutput
-Required.JsonInput.AnyWithTimestamp.ProtobufOutput
-Required.JsonInput.AnyWithValueForInteger.JsonOutput
-Required.JsonInput.AnyWithValueForInteger.ProtobufOutput
-Required.JsonInput.AnyWithValueForJsonObject.JsonOutput
-Required.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
-Required.JsonInput.DoubleFieldInfinity.JsonOutput
-Required.JsonInput.DoubleFieldInfinity.ProtobufOutput
-Required.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
-Required.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMaxPositiveValue.JsonOutput
-Required.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMinNegativeValue.JsonOutput
-Required.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
-Required.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
-Required.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
-Required.JsonInput.DoubleFieldNan.JsonOutput
-Required.JsonInput.DoubleFieldNan.ProtobufOutput
-Required.JsonInput.DoubleFieldNegativeInfinity.JsonOutput
-Required.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
-Required.JsonInput.DoubleFieldQuotedValue.JsonOutput
-Required.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
-Required.JsonInput.DurationMaxValue.JsonOutput
-Required.JsonInput.DurationMaxValue.ProtobufOutput
-Required.JsonInput.DurationMinValue.JsonOutput
-Required.JsonInput.DurationMinValue.ProtobufOutput
-Required.JsonInput.DurationRepeatedValue.JsonOutput
-Required.JsonInput.DurationRepeatedValue.ProtobufOutput
-Required.JsonInput.EnumFieldNumericValueNonZero.JsonOutput
-Required.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
-Required.JsonInput.EnumFieldNumericValueZero.JsonOutput
-Required.JsonInput.EnumFieldNumericValueZero.ProtobufOutput
-Required.JsonInput.EnumFieldUnknownValue.Validator
-Required.JsonInput.FieldMask.JsonOutput
-Required.JsonInput.FieldMask.ProtobufOutput
-Required.JsonInput.FloatFieldInfinity.JsonOutput
-Required.JsonInput.FloatFieldInfinity.ProtobufOutput
-Required.JsonInput.FloatFieldNan.JsonOutput
-Required.JsonInput.FloatFieldNan.ProtobufOutput
-Required.JsonInput.FloatFieldNegativeInfinity.JsonOutput
-Required.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
-Required.JsonInput.FloatFieldQuotedValue.JsonOutput
-Required.JsonInput.FloatFieldQuotedValue.ProtobufOutput
-Required.JsonInput.FloatFieldTooLarge
-Required.JsonInput.FloatFieldTooSmall
-Required.JsonInput.Int32FieldExponentialFormat.JsonOutput
-Required.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
-Required.JsonInput.Int32FieldFloatTrailingZero.JsonOutput
-Required.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
-Required.JsonInput.Int32FieldMaxFloatValue.JsonOutput
-Required.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
-Required.JsonInput.Int32FieldMinFloatValue.JsonOutput
-Required.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
-Required.JsonInput.Int32FieldStringValue.JsonOutput
-Required.JsonInput.Int32FieldStringValue.ProtobufOutput
-Required.JsonInput.Int32FieldStringValueEscaped.JsonOutput
-Required.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
-Required.JsonInput.Int32MapEscapedKey.JsonOutput
-Required.JsonInput.Int32MapEscapedKey.ProtobufOutput
-Required.JsonInput.Int32MapField.JsonOutput
-Required.JsonInput.Int32MapField.ProtobufOutput
-Required.JsonInput.Int64FieldMaxValue.JsonOutput
-Required.JsonInput.Int64FieldMaxValue.ProtobufOutput
-Required.JsonInput.Int64FieldMinValue.JsonOutput
-Required.JsonInput.Int64FieldMinValue.ProtobufOutput
-Required.JsonInput.Int64MapEscapedKey.JsonOutput
-Required.JsonInput.Int64MapEscapedKey.ProtobufOutput
-Required.JsonInput.Int64MapField.JsonOutput
-Required.JsonInput.Int64MapField.ProtobufOutput
-Required.JsonInput.MessageField.JsonOutput
-Required.JsonInput.MessageField.ProtobufOutput
-Required.JsonInput.MessageMapField.JsonOutput
-Required.JsonInput.MessageMapField.ProtobufOutput
-Required.JsonInput.MessageRepeatedField.JsonOutput
-Required.JsonInput.MessageRepeatedField.ProtobufOutput
-Required.JsonInput.OptionalBoolWrapper.JsonOutput
-Required.JsonInput.OptionalBoolWrapper.ProtobufOutput
-Required.JsonInput.OptionalBytesWrapper.JsonOutput
-Required.JsonInput.OptionalBytesWrapper.ProtobufOutput
-Required.JsonInput.OptionalDoubleWrapper.JsonOutput
-Required.JsonInput.OptionalDoubleWrapper.ProtobufOutput
-Required.JsonInput.OptionalFloatWrapper.JsonOutput
-Required.JsonInput.OptionalFloatWrapper.ProtobufOutput
-Required.JsonInput.OptionalInt32Wrapper.JsonOutput
-Required.JsonInput.OptionalInt32Wrapper.ProtobufOutput
-Required.JsonInput.OptionalInt64Wrapper.JsonOutput
-Required.JsonInput.OptionalInt64Wrapper.ProtobufOutput
-Required.JsonInput.OptionalStringWrapper.JsonOutput
-Required.JsonInput.OptionalStringWrapper.ProtobufOutput
-Required.JsonInput.OptionalUint32Wrapper.JsonOutput
-Required.JsonInput.OptionalUint32Wrapper.ProtobufOutput
-Required.JsonInput.OptionalUint64Wrapper.JsonOutput
-Required.JsonInput.OptionalUint64Wrapper.ProtobufOutput
-Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
-Required.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
-Required.JsonInput.PrimitiveRepeatedField.JsonOutput
-Required.JsonInput.PrimitiveRepeatedField.ProtobufOutput
-Required.JsonInput.RepeatedBoolWrapper.JsonOutput
-Required.JsonInput.RepeatedBoolWrapper.ProtobufOutput
-Required.JsonInput.RepeatedBytesWrapper.JsonOutput
-Required.JsonInput.RepeatedBytesWrapper.ProtobufOutput
-Required.JsonInput.RepeatedDoubleWrapper.JsonOutput
-Required.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
-Required.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
-Required.JsonInput.RepeatedFloatWrapper.JsonOutput
-Required.JsonInput.RepeatedFloatWrapper.ProtobufOutput
-Required.JsonInput.RepeatedInt32Wrapper.JsonOutput
-Required.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedInt64Wrapper.JsonOutput
-Required.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedStringWrapper.JsonOutput
-Required.JsonInput.RepeatedStringWrapper.ProtobufOutput
-Required.JsonInput.RepeatedUint32Wrapper.JsonOutput
-Required.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
-Required.JsonInput.RepeatedUint64Wrapper.JsonOutput
-Required.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
-Required.JsonInput.StringFieldNotAString
-Required.JsonInput.StringFieldSurrogatePair.JsonOutput
-Required.JsonInput.StringFieldSurrogatePair.ProtobufOutput
-Required.JsonInput.Struct.JsonOutput
-Required.JsonInput.Struct.ProtobufOutput
-Required.JsonInput.TimestampMaxValue.JsonOutput
-Required.JsonInput.TimestampMaxValue.ProtobufOutput
-Required.JsonInput.TimestampMinValue.JsonOutput
-Required.JsonInput.TimestampMinValue.ProtobufOutput
-Required.JsonInput.TimestampRepeatedValue.JsonOutput
-Required.JsonInput.TimestampRepeatedValue.ProtobufOutput
-Required.JsonInput.TimestampWithNegativeOffset.JsonOutput
-Required.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
-Required.JsonInput.TimestampWithPositiveOffset.JsonOutput
-Required.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
-Required.JsonInput.Uint32FieldMaxFloatValue.JsonOutput
-Required.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
-Required.JsonInput.Uint32MapField.JsonOutput
-Required.JsonInput.Uint32MapField.ProtobufOutput
-Required.JsonInput.Uint64FieldMaxValue.JsonOutput
-Required.JsonInput.Uint64FieldMaxValue.ProtobufOutput
-Required.JsonInput.Uint64MapField.JsonOutput
-Required.JsonInput.Uint64MapField.ProtobufOutput
-Required.JsonInput.ValueAcceptBool.JsonOutput
-Required.JsonInput.ValueAcceptBool.ProtobufOutput
-Required.JsonInput.ValueAcceptFloat.JsonOutput
-Required.JsonInput.ValueAcceptFloat.ProtobufOutput
-Required.JsonInput.ValueAcceptInteger.JsonOutput
-Required.JsonInput.ValueAcceptInteger.ProtobufOutput
-Required.JsonInput.ValueAcceptList.JsonOutput
-Required.JsonInput.ValueAcceptList.ProtobufOutput
-Required.JsonInput.ValueAcceptNull.JsonOutput
-Required.JsonInput.ValueAcceptNull.ProtobufOutput
-Required.JsonInput.ValueAcceptObject.JsonOutput
-Required.JsonInput.ValueAcceptObject.ProtobufOutput
-Required.JsonInput.ValueAcceptString.JsonOutput
-Required.JsonInput.ValueAcceptString.ProtobufOutput
-Required.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
-Required.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
-Required.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
-Required.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.JsonInput.Any.JsonOutput
+Required.Proto3.JsonInput.Any.ProtobufOutput
+Required.Proto3.JsonInput.AnyNested.JsonOutput
+Required.Proto3.JsonInput.AnyNested.ProtobufOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.JsonOutput
+Required.Proto3.JsonInput.AnyUnorderedTypeTag.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithDuration.JsonOutput
+Required.Proto3.JsonInput.AnyWithDuration.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.JsonOutput
+Required.Proto3.JsonInput.AnyWithFieldMask.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.JsonOutput
+Required.Proto3.JsonInput.AnyWithInt32ValueWrapper.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithStruct.JsonOutput
+Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.JsonOutput
+Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.JsonOutput
+Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.JsonOutput
+Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
+Required.Proto3.JsonInput.DoubleFieldNan.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.JsonOutput
+Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationMinValue.JsonOutput
+Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.FieldMask.JsonOutput
+Required.Proto3.JsonInput.FieldMask.ProtobufOutput
+Required.Proto3.JsonInput.FloatFieldInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNan.JsonOutput
+Required.Proto3.JsonInput.FloatFieldNegativeInfinity.JsonOutput
+Required.Proto3.JsonInput.FloatFieldTooLarge
+Required.Proto3.JsonInput.FloatFieldTooSmall
+Required.Proto3.JsonInput.OneofFieldDuplicate
+Required.Proto3.JsonInput.OptionalBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
+Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.JsonOutput
+Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
+Required.Proto3.JsonInput.StringFieldSurrogatePair.JsonOutput
+Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
+Required.Proto3.JsonInput.Struct.JsonOutput
+Required.Proto3.JsonInput.Struct.ProtobufOutput
+Required.Proto3.JsonInput.TimestampMaxValue.JsonOutput
+Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
+Required.Proto3.JsonInput.TimestampMinValue.JsonOutput
+Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
+Required.Proto3.JsonInput.TimestampRepeatedValue.JsonOutput
+Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
+Required.Proto3.JsonInput.TimestampWithNegativeOffset.JsonOutput
+Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
+Required.Proto3.JsonInput.TimestampWithPositiveOffset.JsonOutput
+Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptBool.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptList.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptList.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptNull.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptObject.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
+Required.Proto3.JsonInput.ValueAcceptString.JsonOutput
+Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.DoubleFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeQuietNan.JsonOutput
+Required.Proto3.ProtobufInput.FloatFieldNormalizeSignalingNan.JsonOutput
+Required.Proto3.ProtobufInput.ValidDataRepeated.FLOAT.JsonOutput
 Required.TimestampProtoInputTooLarge.JsonOutput
 Required.TimestampProtoInputTooSmall.JsonOutput
diff --git a/conformance/update_failure_list.py b/conformance/update_failure_list.py
index 63f453d..ad42ed3 100755
--- a/conformance/update_failure_list.py
+++ b/conformance/update_failure_list.py
@@ -35,7 +35,6 @@
 """
 
 import argparse
-import fileinput
 
 parser = argparse.ArgumentParser(
     description='Adds/removes failures from the failure list.')
@@ -62,7 +61,8 @@
 
 add_list = sorted(add_set, reverse=True)
 
-existing_list = file(args.filename).read()
+with open(args.filename) as in_file:
+    existing_list = in_file.read()
 
 with open(args.filename, "w") as f:
   for line in existing_list.splitlines(True):
diff --git a/csharp/Google.Protobuf.Tools.nuspec b/csharp/Google.Protobuf.Tools.nuspec
index 182309b..d32fd94 100644
--- a/csharp/Google.Protobuf.Tools.nuspec
+++ b/csharp/Google.Protobuf.Tools.nuspec
@@ -5,7 +5,7 @@
     <title>Google Protocol Buffers tools</title>
     <summary>Tools for Protocol Buffers - Google's data interchange format.</summary>
     <description>See project site for more info.</description>
-    <version>3.3.0</version>
+    <version>3.4.0</version>
     <authors>Google Inc.</authors>
     <owners>protobuf-packages</owners>
     <licenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</licenseUrl>
diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index c0a9ffd..ff44895 100644
--- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -403,7 +403,7 @@
                 output.Flush();

 

                 ms.Position = 0;

-                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0);

+                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0, false);

 

                 uint tag = input.ReadTag();

                 Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));

diff --git a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 48bf6d6..01bd321 100644
--- a/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/compatibility_tests/v3.0.0/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -334,7 +334,7 @@
             }

             // Now test Input stream:

             {

-                CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0);

+                CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0, false);

                 Assert.AreEqual(0, cin.Position);

                 // Field 1:

                 uint tag = cin.ReadTag();

diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs
index 75ed071..e595e58 100644
--- a/csharp/src/AddressBook/Addressbook.cs
+++ b/csharp/src/AddressBook/Addressbook.cs
@@ -22,19 +22,21 @@
     static AddressbookReflection() {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
-            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwi1QEKBlBlcnNvbhIMCgRu",
-            "YW1lGAEgASgJEgoKAmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25l",
-            "cxgEIAMoCzIcLnR1dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchpHCgtQaG9u",
-            "ZU51bWJlchIOCgZudW1iZXIYASABKAkSKAoEdHlwZRgCIAEoDjIaLnR1dG9y",
-            "aWFsLlBlcnNvbi5QaG9uZVR5cGUiKwoJUGhvbmVUeXBlEgoKBk1PQklMRRAA",
-            "EggKBEhPTUUQARIICgRXT1JLEAIiLwoLQWRkcmVzc0Jvb2sSIAoGcGVvcGxl",
-            "GAEgAygLMhAudHV0b3JpYWwuUGVyc29uQlAKFGNvbS5leGFtcGxlLnR1dG9y",
-            "aWFsQhFBZGRyZXNzQm9va1Byb3Rvc6oCJEdvb2dsZS5Qcm90b2J1Zi5FeGFt",
-            "cGxlcy5BZGRyZXNzQm9va2IGcHJvdG8z"));
+            "ChFhZGRyZXNzYm9vay5wcm90bxIIdHV0b3JpYWwaH2dvb2dsZS9wcm90b2J1",
+            "Zi90aW1lc3RhbXAucHJvdG8ihwIKBlBlcnNvbhIMCgRuYW1lGAEgASgJEgoK",
+            "AmlkGAIgASgFEg0KBWVtYWlsGAMgASgJEiwKBnBob25lcxgEIAMoCzIcLnR1",
+            "dG9yaWFsLlBlcnNvbi5QaG9uZU51bWJlchIwCgxsYXN0X3VwZGF0ZWQYBSAB",
+            "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wGkcKC1Bob25lTnVtYmVy",
+            "Eg4KBm51bWJlchgBIAEoCRIoCgR0eXBlGAIgASgOMhoudHV0b3JpYWwuUGVy",
+            "c29uLlBob25lVHlwZSIrCglQaG9uZVR5cGUSCgoGTU9CSUxFEAASCAoESE9N",
+            "RRABEggKBFdPUksQAiIvCgtBZGRyZXNzQm9vaxIgCgZwZW9wbGUYASADKAsy",
+            "EC50dXRvcmlhbC5QZXJzb25CUAoUY29tLmV4YW1wbGUudHV0b3JpYWxCEUFk",
+            "ZHJlc3NCb29rUHJvdG9zqgIkR29vZ2xlLlByb3RvYnVmLkV4YW1wbGVzLkFk",
+            "ZHJlc3NCb29rYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { },
+          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person), global::Google.Protobuf.Examples.AddressBook.Person.Parser, new[]{ "Name", "Id", "Email", "Phones", "LastUpdated" }, null, new[]{ typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber), global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneNumber.Parser, new[]{ "Number", "Type" }, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Examples.AddressBook.AddressBook), global::Google.Protobuf.Examples.AddressBook.AddressBook.Parser, new[]{ "People" }, null, null, null)
           }));
     }
@@ -73,6 +75,7 @@
       id_ = other.id_;
       email_ = other.email_;
       phones_ = other.phones_.Clone();
+      LastUpdated = other.lastUpdated_ != null ? other.LastUpdated.Clone() : null;
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -126,6 +129,17 @@
       get { return phones_; }
     }
 
+    /// <summary>Field number for the "last_updated" field.</summary>
+    public const int LastUpdatedFieldNumber = 5;
+    private global::Google.Protobuf.WellKnownTypes.Timestamp lastUpdated_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public global::Google.Protobuf.WellKnownTypes.Timestamp LastUpdated {
+      get { return lastUpdated_; }
+      set {
+        lastUpdated_ = value;
+      }
+    }
+
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
       return Equals(other as Person);
@@ -143,6 +157,7 @@
       if (Id != other.Id) return false;
       if (Email != other.Email) return false;
       if(!phones_.Equals(other.phones_)) return false;
+      if (!object.Equals(LastUpdated, other.LastUpdated)) return false;
       return true;
     }
 
@@ -153,6 +168,7 @@
       if (Id != 0) hash ^= Id.GetHashCode();
       if (Email.Length != 0) hash ^= Email.GetHashCode();
       hash ^= phones_.GetHashCode();
+      if (lastUpdated_ != null) hash ^= LastUpdated.GetHashCode();
       return hash;
     }
 
@@ -176,6 +192,10 @@
         output.WriteString(Email);
       }
       phones_.WriteTo(output, _repeated_phones_codec);
+      if (lastUpdated_ != null) {
+        output.WriteRawTag(42);
+        output.WriteMessage(LastUpdated);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -191,6 +211,9 @@
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Email);
       }
       size += phones_.CalculateSize(_repeated_phones_codec);
+      if (lastUpdated_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(LastUpdated);
+      }
       return size;
     }
 
@@ -209,6 +232,12 @@
         Email = other.Email;
       }
       phones_.Add(other.phones_);
+      if (other.lastUpdated_ != null) {
+        if (lastUpdated_ == null) {
+          lastUpdated_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+        }
+        LastUpdated.MergeFrom(other.LastUpdated);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -235,6 +264,13 @@
             phones_.AddEntriesFrom(input, _repeated_phones_codec);
             break;
           }
+          case 42: {
+            if (lastUpdated_ == null) {
+              lastUpdated_ = new global::Google.Protobuf.WellKnownTypes.Timestamp();
+            }
+            input.ReadMessage(lastUpdated_);
+            break;
+          }
         }
       }
     }
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
index 1a835ae..394607b 100644
--- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -22,21 +22,21 @@
     static ConformanceReflection() {
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
-            "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UijQEKEkNvbmZvcm1h",
+            "ChFjb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2UiowEKEkNvbmZvcm1h",
             "bmNlUmVxdWVzdBIaChBwcm90b2J1Zl9wYXlsb2FkGAEgASgMSAASFgoManNv",
             "bl9wYXlsb2FkGAIgASgJSAASOAoXcmVxdWVzdGVkX291dHB1dF9mb3JtYXQY",
-            "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0QgkKB3BheWxvYWQisQEK",
-            "E0NvbmZvcm1hbmNlUmVzcG9uc2USFQoLcGFyc2VfZXJyb3IYASABKAlIABIZ",
-            "Cg9zZXJpYWxpemVfZXJyb3IYBiABKAlIABIXCg1ydW50aW1lX2Vycm9yGAIg",
-            "ASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgDIAEoDEgAEhYKDGpzb25fcGF5",
-            "bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSABKAlIAEIICgZyZXN1bHQqNQoK",
-            "V2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoE",
-            "SlNPThACQiEKH2NvbS5nb29nbGUucHJvdG9idWYuY29uZm9ybWFuY2ViBnBy",
-            "b3RvMw=="));
+            "AyABKA4yFy5jb25mb3JtYW5jZS5XaXJlRm9ybWF0EhQKDG1lc3NhZ2VfdHlw",
+            "ZRgEIAEoCUIJCgdwYXlsb2FkIrEBChNDb25mb3JtYW5jZVJlc3BvbnNlEhUK",
+            "C3BhcnNlX2Vycm9yGAEgASgJSAASGQoPc2VyaWFsaXplX2Vycm9yGAYgASgJ",
+            "SAASFwoNcnVudGltZV9lcnJvchgCIAEoCUgAEhoKEHByb3RvYnVmX3BheWxv",
+            "YWQYAyABKAxIABIWCgxqc29uX3BheWxvYWQYBCABKAlIABIRCgdza2lwcGVk",
+            "GAUgASgJSABCCAoGcmVzdWx0KjUKCldpcmVGb3JtYXQSDwoLVU5TUEVDSUZJ",
+            "RUQQABIMCghQUk9UT0JVRhABEggKBEpTT04QAkIhCh9jb20uZ29vZ2xlLnBy",
+            "b3RvYnVmLmNvbmZvcm1hbmNlYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), }, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat" }, new[]{ "Payload" }, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "RequestedOutputFormat", "MessageType" }, new[]{ "Payload" }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped" }, new[]{ "Result" }, null, null)
           }));
     }
@@ -85,6 +85,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ConformanceRequest(ConformanceRequest other) : this() {
       requestedOutputFormat_ = other.requestedOutputFormat_;
+      messageType_ = other.messageType_;
       switch (other.PayloadCase) {
         case PayloadOneofCase.ProtobufPayload:
           ProtobufPayload = other.ProtobufPayload;
@@ -137,6 +138,22 @@
       }
     }
 
+    /// <summary>Field number for the "message_type" field.</summary>
+    public const int MessageTypeFieldNumber = 4;
+    private string messageType_ = "";
+    /// <summary>
+    /// The full name for the test message to use; for the moment, either:
+    /// protobuf_test_messages.proto3.TestAllTypesProto3 or
+    /// protobuf_test_messages.proto2.TestAllTypesProto2.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public string MessageType {
+      get { return messageType_; }
+      set {
+        messageType_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
     private object payload_;
     /// <summary>Enum of possible cases for the "payload" oneof.</summary>
     public enum PayloadOneofCase {
@@ -172,6 +189,7 @@
       if (ProtobufPayload != other.ProtobufPayload) return false;
       if (JsonPayload != other.JsonPayload) return false;
       if (RequestedOutputFormat != other.RequestedOutputFormat) return false;
+      if (MessageType != other.MessageType) return false;
       if (PayloadCase != other.PayloadCase) return false;
       return true;
     }
@@ -182,6 +200,7 @@
       if (payloadCase_ == PayloadOneofCase.ProtobufPayload) hash ^= ProtobufPayload.GetHashCode();
       if (payloadCase_ == PayloadOneofCase.JsonPayload) hash ^= JsonPayload.GetHashCode();
       if (RequestedOutputFormat != 0) hash ^= RequestedOutputFormat.GetHashCode();
+      if (MessageType.Length != 0) hash ^= MessageType.GetHashCode();
       hash ^= (int) payloadCase_;
       return hash;
     }
@@ -205,6 +224,10 @@
         output.WriteRawTag(24);
         output.WriteEnum((int) RequestedOutputFormat);
       }
+      if (MessageType.Length != 0) {
+        output.WriteRawTag(34);
+        output.WriteString(MessageType);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -219,6 +242,9 @@
       if (RequestedOutputFormat != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) RequestedOutputFormat);
       }
+      if (MessageType.Length != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageType);
+      }
       return size;
     }
 
@@ -230,6 +256,9 @@
       if (other.RequestedOutputFormat != 0) {
         RequestedOutputFormat = other.RequestedOutputFormat;
       }
+      if (other.MessageType.Length != 0) {
+        MessageType = other.MessageType;
+      }
       switch (other.PayloadCase) {
         case PayloadOneofCase.ProtobufPayload:
           ProtobufPayload = other.ProtobufPayload;
@@ -261,6 +290,10 @@
             requestedOutputFormat_ = (global::Conformance.WireFormat) input.ReadEnum();
             break;
           }
+          case 34: {
+            MessageType = input.ReadString();
+            break;
+          }
         }
       }
     }
diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs
index 00ee64f..96dc354 100644
--- a/csharp/src/Google.Protobuf.Conformance/Program.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Program.cs
@@ -48,7 +48,7 @@
             // This way we get the binary streams instead of readers/writers.
             var input = new BinaryReader(Console.OpenStandardInput());
             var output = new BinaryWriter(Console.OpenStandardOutput());
-            var typeRegistry = TypeRegistry.FromMessages(ProtobufTestMessages.Proto3.TestAllTypes.Descriptor);
+            var typeRegistry = TypeRegistry.FromMessages(ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor);
 
             int count = 0;
             while (RunTest(input, output, typeRegistry))
@@ -81,18 +81,31 @@
 
         private static ConformanceResponse PerformRequest(ConformanceRequest request, TypeRegistry typeRegistry)
         {
-            ProtobufTestMessages.Proto3.TestAllTypes message;
+            ProtobufTestMessages.Proto3.TestAllTypesProto3 message;
             try
             {
                 switch (request.PayloadCase)
                 {
                     case ConformanceRequest.PayloadOneofCase.JsonPayload:
                         var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
-                        message = parser.Parse<ProtobufTestMessages.Proto3.TestAllTypes>(request.JsonPayload);
+                        message = parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(request.JsonPayload);
                         break;
-                    case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
-                        message = ProtobufTestMessages.Proto3.TestAllTypes.Parser.ParseFrom(request.ProtobufPayload);
+                    case ConformanceRequest.PayloadOneofCase.ProtobufPayload: 
+                    {
+                        if (request.MessageType.Equals("protobuf_test_messages.proto3.TestAllTypesProto3"))
+                        {
+                            message = ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload);
+                        }							
+                        else if (request.MessageType.Equals("protobuf_test_messages.proto2.TestAllTypesProto2")) 
+                        {
+                            return new ConformanceResponse { Skipped = "CSharp doesn't support proto2" };
+                        }
+                        else 
+                        {
+                            throw new Exception(" Protobuf request doesn't have specific payload type");
+                        }
                         break;
+                    }
                     default:
                         throw new Exception("Unsupported request payload: " + request.PayloadCase);
                 }
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index c0a9ffd..e7c6b80 100644
--- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -284,6 +284,20 @@
             Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());

         }

 

+        // Representations of a tag for field 0 with various wire types

+        [Test]

+        [TestCase(0)]

+        [TestCase(1)]

+        [TestCase(2)]

+        [TestCase(3)]

+        [TestCase(4)]

+        [TestCase(5)]

+        public void ReadTag_ZeroFieldRejected(byte tag)

+        {

+            CodedInputStream cis = new CodedInputStream(new byte[] { tag });

+            Assert.Throws<InvalidProtocolBufferException>(() => cis.ReadTag());

+        }

+

         internal static TestRecursiveMessage MakeRecursiveMessage(int depth)

         {

             if (depth == 0)

@@ -403,7 +417,7 @@
                 output.Flush();

 

                 ms.Position = 0;

-                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0);

+                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0, false);

 

                 uint tag = input.ReadTag();

                 Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));

@@ -594,5 +608,12 @@
             }

             Assert.IsTrue(memoryStream.CanRead); // We left the stream open

         }

+

+        [Test]

+        public void Dispose_FromByteArray()

+        {

+            var stream = new CodedInputStream(new byte[10]);

+            stream.Dispose();

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 48bf6d6..98cabd5 100644
--- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -334,7 +334,7 @@
             }

             // Now test Input stream:

             {

-                CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0);

+                CodedInputStream cin = new CodedInputStream(new MemoryStream(bytes), new byte[50], 0, 0, false);

                 Assert.AreEqual(0, cin.Position);

                 // Field 1:

                 uint tag = cin.ReadTag();

@@ -415,5 +415,12 @@
             Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream

             Assert.IsTrue(memoryStream.CanWrite); // We left the stream open

         }

+

+        [Test]

+        public void Dispose_FromByteArray()

+        {

+            var stream = new CodedOutputStream(new byte[10]);

+            stream.Dispose();

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
index 9d3d69a..68b4de4 100644
--- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
@@ -540,6 +540,22 @@
             Assert.Throws<ArgumentException>(() => map.ToString());
         }
 
+#if !NET35
+        [Test]
+        public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            CollectionAssert.AreEquivalent(((IDictionary<string, string>)map).Keys, ((IReadOnlyDictionary<string, string>)map).Keys);
+        }
+
+        [Test]
+        public void IDictionaryValues_Equals_IReadOnlyDictionaryValues()
+        {
+            var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
+            CollectionAssert.AreEquivalent(((IDictionary<string, string>)map).Values, ((IReadOnlyDictionary<string, string>)map).Values);
+        }
+#endif
+
         private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
         {
             return new KeyValuePair<TKey, TValue>(key, value);
diff --git a/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
index fbeb512..6607be7 100644
--- a/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
+++ b/csharp/src/Google.Protobuf.Test/TestProtos/TestMessagesProto3.cs
@@ -27,180 +27,184 @@
             "dWYvYW55LnByb3RvGh5nb29nbGUvcHJvdG9idWYvZHVyYXRpb24ucHJvdG8a",
             "IGdvb2dsZS9wcm90b2J1Zi9maWVsZF9tYXNrLnByb3RvGhxnb29nbGUvcHJv",
             "dG9idWYvc3RydWN0LnByb3RvGh9nb29nbGUvcHJvdG9idWYvdGltZXN0YW1w",
-            "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8i+DkKDFRl",
-            "c3RBbGxUeXBlcxIWCg5vcHRpb25hbF9pbnQzMhgBIAEoBRIWCg5vcHRpb25h",
-            "bF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25hbF91aW50MzIYAyABKA0SFwoPb3B0",
-            "aW9uYWxfdWludDY0GAQgASgEEhcKD29wdGlvbmFsX3NpbnQzMhgFIAEoERIX",
-            "Cg9vcHRpb25hbF9zaW50NjQYBiABKBISGAoQb3B0aW9uYWxfZml4ZWQzMhgH",
-            "IAEoBxIYChBvcHRpb25hbF9maXhlZDY0GAggASgGEhkKEW9wdGlvbmFsX3Nm",
-            "aXhlZDMyGAkgASgPEhkKEW9wdGlvbmFsX3NmaXhlZDY0GAogASgQEhYKDm9w",
-            "dGlvbmFsX2Zsb2F0GAsgASgCEhcKD29wdGlvbmFsX2RvdWJsZRgMIAEoARIV",
-            "Cg1vcHRpb25hbF9ib29sGA0gASgIEhcKD29wdGlvbmFsX3N0cmluZxgOIAEo",
-            "CRIWCg5vcHRpb25hbF9ieXRlcxgPIAEoDBJaChdvcHRpb25hbF9uZXN0ZWRf",
-            "bWVzc2FnZRgSIAEoCzI5LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8z",
-            "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlEk8KGG9wdGlvbmFsX2ZvcmVp",
-            "Z25fbWVzc2FnZRgTIAEoCzItLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv",
-            "dG8zLkZvcmVpZ25NZXNzYWdlElQKFG9wdGlvbmFsX25lc3RlZF9lbnVtGBUg",
-            "ASgOMjYucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5",
-            "cGVzLk5lc3RlZEVudW0SSQoVb3B0aW9uYWxfZm9yZWlnbl9lbnVtGBYgASgO",
-            "MioucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuRm9yZWlnbkVudW0S",
-            "IQoVb3B0aW9uYWxfc3RyaW5nX3BpZWNlGBggASgJQgIIAhIZCg1vcHRpb25h",
-            "bF9jb3JkGBkgASgJQgIIARJGChFyZWN1cnNpdmVfbWVzc2FnZRgbIAEoCzIr",
-            "LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlcxIW",
-            "Cg5yZXBlYXRlZF9pbnQzMhgfIAMoBRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMo",
-            "AxIXCg9yZXBlYXRlZF91aW50MzIYISADKA0SFwoPcmVwZWF0ZWRfdWludDY0",
-            "GCIgAygEEhcKD3JlcGVhdGVkX3NpbnQzMhgjIAMoERIXCg9yZXBlYXRlZF9z",
-            "aW50NjQYJCADKBISGAoQcmVwZWF0ZWRfZml4ZWQzMhglIAMoBxIYChByZXBl",
-            "YXRlZF9maXhlZDY0GCYgAygGEhkKEXJlcGVhdGVkX3NmaXhlZDMyGCcgAygP",
-            "EhkKEXJlcGVhdGVkX3NmaXhlZDY0GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0",
-            "GCkgAygCEhcKD3JlcGVhdGVkX2RvdWJsZRgqIAMoARIVCg1yZXBlYXRlZF9i",
-            "b29sGCsgAygIEhcKD3JlcGVhdGVkX3N0cmluZxgsIAMoCRIWCg5yZXBlYXRl",
-            "ZF9ieXRlcxgtIAMoDBJaChdyZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMo",
-            "CzI5LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBl",
-            "cy5OZXN0ZWRNZXNzYWdlEk8KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZRgx",
-            "IAMoCzItLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25N",
-            "ZXNzYWdlElQKFHJlcGVhdGVkX25lc3RlZF9lbnVtGDMgAygOMjYucHJvdG9i",
-            "dWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzLk5lc3RlZEVu",
-            "dW0SSQoVcmVwZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygOMioucHJvdG9idWZf",
-            "dGVzdF9tZXNzYWdlcy5wcm90bzMuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRf",
-            "c3RyaW5nX3BpZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJ",
-            "QgIIARJXCg9tYXBfaW50MzJfaW50MzIYOCADKAsyPi5wcm90b2J1Zl90ZXN0",
-            "X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwSW50MzJJbnQzMkVu",
-            "dHJ5ElcKD21hcF9pbnQ2NF9pbnQ2NBg5IAMoCzI+LnByb3RvYnVmX3Rlc3Rf",
-            "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlcy5NYXBJbnQ2NEludDY0RW50",
-            "cnkSWwoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyQC5wcm90b2J1Zl90ZXN0",
-            "X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwVWludDMyVWludDMy",
-            "RW50cnkSWwoRbWFwX3VpbnQ2NF91aW50NjQYOyADKAsyQC5wcm90b2J1Zl90",
-            "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwVWludDY0VWlu",
-            "dDY0RW50cnkSWwoRbWFwX3NpbnQzMl9zaW50MzIYPCADKAsyQC5wcm90b2J1",
-            "Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwU2ludDMy",
-            "U2ludDMyRW50cnkSWwoRbWFwX3NpbnQ2NF9zaW50NjQYPSADKAsyQC5wcm90",
-            "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwU2lu",
-            "dDY0U2ludDY0RW50cnkSXwoTbWFwX2ZpeGVkMzJfZml4ZWQzMhg+IAMoCzJC",
-            "LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlcy5N",
-            "YXBGaXhlZDMyRml4ZWQzMkVudHJ5El8KE21hcF9maXhlZDY0X2ZpeGVkNjQY",
-            "PyADKAsyQi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxs",
-            "VHlwZXMuTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJjChVtYXBfc2ZpeGVkMzJf",
-            "c2ZpeGVkMzIYQCADKAsyRC5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3Rv",
-            "My5UZXN0QWxsVHlwZXMuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5EmMKFW1h",
-            "cF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzJELnByb3RvYnVmX3Rlc3RfbWVz",
-            "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlcy5NYXBTZml4ZWQ2NFNmaXhlZDY0",
-            "RW50cnkSVwoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMj4ucHJvdG9idWZfdGVz",
-            "dF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzLk1hcEludDMyRmxvYXRF",
-            "bnRyeRJZChBtYXBfaW50MzJfZG91YmxlGEMgAygLMj8ucHJvdG9idWZfdGVz",
-            "dF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzLk1hcEludDMyRG91Ymxl",
-            "RW50cnkSUwoNbWFwX2Jvb2xfYm9vbBhEIAMoCzI8LnByb3RvYnVmX3Rlc3Rf",
-            "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlcy5NYXBCb29sQm9vbEVudHJ5",
-            "ElsKEW1hcF9zdHJpbmdfc3RyaW5nGEUgAygLMkAucHJvdG9idWZfdGVzdF9t",
-            "ZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzLk1hcFN0cmluZ1N0cmluZ0Vu",
-            "dHJ5ElkKEG1hcF9zdHJpbmdfYnl0ZXMYRiADKAsyPy5wcm90b2J1Zl90ZXN0",
-            "X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nQnl0ZXNF",
-            "bnRyeRJqChltYXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMkcucHJv",
-            "dG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzLk1hcFN0",
-            "cmluZ05lc3RlZE1lc3NhZ2VFbnRyeRJsChptYXBfc3RyaW5nX2ZvcmVpZ25f",
-            "bWVzc2FnZRhIIAMoCzJILnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8z",
-            "LlRlc3RBbGxUeXBlcy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5EmQK",
-            "Fm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsyRC5wcm90b2J1Zl90ZXN0",
-            "X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTWFwU3RyaW5nTmVzdGVk",
-            "RW51bUVudHJ5EmYKF21hcF9zdHJpbmdfZm9yZWlnbl9lbnVtGEogAygLMkUu",
-            "cHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzLk1h",
-            "cFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25lb2ZfdWludDMyGG8gASgN",
-            "SAASWQoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCABKAsyOS5wcm90b2J1Zl90",
-            "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2Fn",
-            "ZUgAEhYKDG9uZW9mX3N0cmluZxhxIAEoCUgAEhUKC29uZW9mX2J5dGVzGHIg",
-            "ASgMSAASFAoKb25lb2ZfYm9vbBhzIAEoCEgAEhYKDG9uZW9mX3VpbnQ2NBh0",
-            "IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUgASgCSAASFgoMb25lb2ZfZG91Ymxl",
-            "GHYgASgBSAASTAoKb25lb2ZfZW51bRh3IAEoDjI2LnByb3RvYnVmX3Rlc3Rf",
-            "bWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlcy5OZXN0ZWRFbnVtSAASOgoV",
-            "b3B0aW9uYWxfYm9vbF93cmFwcGVyGMkBIAEoCzIaLmdvb2dsZS5wcm90b2J1",
-            "Zi5Cb29sVmFsdWUSPAoWb3B0aW9uYWxfaW50MzJfd3JhcHBlchjKASABKAsy",
-            "Gy5nb29nbGUucHJvdG9idWYuSW50MzJWYWx1ZRI8ChZvcHRpb25hbF9pbnQ2",
-            "NF93cmFwcGVyGMsBIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVl",
-            "Ej4KF29wdGlvbmFsX3VpbnQzMl93cmFwcGVyGMwBIAEoCzIcLmdvb2dsZS5w",
-            "cm90b2J1Zi5VSW50MzJWYWx1ZRI+ChdvcHRpb25hbF91aW50NjRfd3JhcHBl",
-            "chjNASABKAsyHC5nb29nbGUucHJvdG9idWYuVUludDY0VmFsdWUSPAoWb3B0",
-            "aW9uYWxfZmxvYXRfd3JhcHBlchjOASABKAsyGy5nb29nbGUucHJvdG9idWYu",
-            "RmxvYXRWYWx1ZRI+ChdvcHRpb25hbF9kb3VibGVfd3JhcHBlchjPASABKAsy",
-            "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSPgoXb3B0aW9uYWxfc3Ry",
-            "aW5nX3dyYXBwZXIY0AEgASgLMhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1Zh",
-            "bHVlEjwKFm9wdGlvbmFsX2J5dGVzX3dyYXBwZXIY0QEgASgLMhsuZ29vZ2xl",
-            "LnByb3RvYnVmLkJ5dGVzVmFsdWUSOgoVcmVwZWF0ZWRfYm9vbF93cmFwcGVy",
-            "GNMBIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWUSPAoWcmVwZWF0",
-            "ZWRfaW50MzJfd3JhcHBlchjUASADKAsyGy5nb29nbGUucHJvdG9idWYuSW50",
-            "MzJWYWx1ZRI8ChZyZXBlYXRlZF9pbnQ2NF93cmFwcGVyGNUBIAMoCzIbLmdv",
-            "b2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEj4KF3JlcGVhdGVkX3VpbnQzMl93",
-            "cmFwcGVyGNYBIAMoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1ZRI+",
-            "ChdyZXBlYXRlZF91aW50NjRfd3JhcHBlchjXASADKAsyHC5nb29nbGUucHJv",
-            "dG9idWYuVUludDY0VmFsdWUSPAoWcmVwZWF0ZWRfZmxvYXRfd3JhcHBlchjY",
-            "ASADKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRI+ChdyZXBlYXRl",
-            "ZF9kb3VibGVfd3JhcHBlchjZASADKAsyHC5nb29nbGUucHJvdG9idWYuRG91",
-            "YmxlVmFsdWUSPgoXcmVwZWF0ZWRfc3RyaW5nX3dyYXBwZXIY2gEgAygLMhwu",
-            "Z29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjwKFnJlcGVhdGVkX2J5dGVz",
-            "X3dyYXBwZXIY2wEgAygLMhsuZ29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFsdWUS",
-            "NQoRb3B0aW9uYWxfZHVyYXRpb24YrQIgASgLMhkuZ29vZ2xlLnByb3RvYnVm",
-            "LkR1cmF0aW9uEjcKEm9wdGlvbmFsX3RpbWVzdGFtcBiuAiABKAsyGi5nb29n",
-            "bGUucHJvdG9idWYuVGltZXN0YW1wEjgKE29wdGlvbmFsX2ZpZWxkX21hc2sY",
-            "rwIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFzaxIxCg9vcHRpb25h",
-            "bF9zdHJ1Y3QYsAIgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdBIrCgxv",
-            "cHRpb25hbF9hbnkYsQIgASgLMhQuZ29vZ2xlLnByb3RvYnVmLkFueRIvCg5v",
-            "cHRpb25hbF92YWx1ZRiyAiABKAsyFi5nb29nbGUucHJvdG9idWYuVmFsdWUS",
-            "NQoRcmVwZWF0ZWRfZHVyYXRpb24YtwIgAygLMhkuZ29vZ2xlLnByb3RvYnVm",
-            "LkR1cmF0aW9uEjcKEnJlcGVhdGVkX3RpbWVzdGFtcBi4AiADKAsyGi5nb29n",
-            "bGUucHJvdG9idWYuVGltZXN0YW1wEjcKEnJlcGVhdGVkX2ZpZWxkbWFzaxi5",
-            "AiADKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrEjEKD3JlcGVhdGVk",
-            "X3N0cnVjdBjEAiADKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0EisKDHJl",
-            "cGVhdGVkX2FueRi7AiADKAsyFC5nb29nbGUucHJvdG9idWYuQW55Ei8KDnJl",
-            "cGVhdGVkX3ZhbHVlGLwCIAMoCzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRIT",
-            "CgpmaWVsZG5hbWUxGJEDIAEoBRIUCgtmaWVsZF9uYW1lMhiSAyABKAUSFQoM",
-            "X2ZpZWxkX25hbWUzGJMDIAEoBRIWCg1maWVsZF9fbmFtZTRfGJQDIAEoBRIU",
-            "CgtmaWVsZDBuYW1lNRiVAyABKAUSFgoNZmllbGRfMF9uYW1lNhiWAyABKAUS",
-            "EwoKZmllbGROYW1lNxiXAyABKAUSEwoKRmllbGROYW1lOBiYAyABKAUSFAoL",
-            "ZmllbGRfTmFtZTkYmQMgASgFEhUKDEZpZWxkX05hbWUxMBiaAyABKAUSFQoM",
-            "RklFTERfTkFNRTExGJsDIAEoBRIVCgxGSUVMRF9uYW1lMTIYnAMgASgFEhcK",
-            "Dl9fZmllbGRfbmFtZTEzGJ0DIAEoBRIXCg5fX0ZpZWxkX25hbWUxNBieAyAB",
-            "KAUSFgoNZmllbGRfX25hbWUxNRifAyABKAUSFgoNZmllbGRfX05hbWUxNhig",
-            "AyABKAUSFwoOZmllbGRfbmFtZTE3X18YoQMgASgFEhcKDkZpZWxkX25hbWUx",
-            "OF9fGKIDIAEoBRpcCg1OZXN0ZWRNZXNzYWdlEgkKAWEYASABKAUSQAoLY29y",
-            "ZWN1cnNpdmUYAiABKAsyKy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3Rv",
-            "My5UZXN0QWxsVHlwZXMaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tleRgB",
-            "IAEoBRINCgV2YWx1ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVudHJ5",
-            "EgsKA2tleRgBIAEoAxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWludDMy",
-            "VWludDMyRW50cnkSCwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4ARo2",
-            "ChRNYXBVaW50NjRVaW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFsdWUY",
-            "AiABKAQ6AjgBGjYKFE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgBIAEo",
-            "ERINCgV2YWx1ZRgCIAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50cnkS",
-            "CwoDa2V5GAEgASgSEg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhlZDMy",
-            "Rml4ZWQzMkVudHJ5EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoCOAEa",
-            "OAoWTWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoFdmFs",
-            "dWUYAiABKAY6AjgBGjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRILCgNr",
-            "ZXkYASABKA8SDQoFdmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0U2Zp",
-            "eGVkNjRFbnRyeRILCgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgBGjQK",
-            "Ek1hcEludDMyRmxvYXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiAB",
-            "KAI6AjgBGjUKE01hcEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgFEg0K",
-            "BXZhbHVlGAIgASgBOgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tleRgB",
-            "IAEoCBINCgV2YWx1ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5nRW50",
-            "cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4ARo1ChNNYXBTdHJp",
-            "bmdCeXRlc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoDDoCOAEa",
-            "eAobTWFwU3RyaW5nTmVzdGVkTWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRJI",
-            "CgV2YWx1ZRgCIAEoCzI5LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8z",
-            "LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlOgI4ARptChxNYXBTdHJpbmdG",
-            "b3JlaWduTWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRI8CgV2YWx1ZRgCIAEo",
-            "CzItLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNz",
-            "YWdlOgI4ARpyChhNYXBTdHJpbmdOZXN0ZWRFbnVtRW50cnkSCwoDa2V5GAEg",
-            "ASgJEkUKBXZhbHVlGAIgASgOMjYucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5w",
-            "cm90bzMuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06AjgBGmcKGU1hcFN0cmlu",
+            "LnByb3RvGh5nb29nbGUvcHJvdG9idWYvd3JhcHBlcnMucHJvdG8irDsKElRl",
+            "c3RBbGxUeXBlc1Byb3RvMxIWCg5vcHRpb25hbF9pbnQzMhgBIAEoBRIWCg5v",
+            "cHRpb25hbF9pbnQ2NBgCIAEoAxIXCg9vcHRpb25hbF91aW50MzIYAyABKA0S",
+            "FwoPb3B0aW9uYWxfdWludDY0GAQgASgEEhcKD29wdGlvbmFsX3NpbnQzMhgF",
+            "IAEoERIXCg9vcHRpb25hbF9zaW50NjQYBiABKBISGAoQb3B0aW9uYWxfZml4",
+            "ZWQzMhgHIAEoBxIYChBvcHRpb25hbF9maXhlZDY0GAggASgGEhkKEW9wdGlv",
+            "bmFsX3NmaXhlZDMyGAkgASgPEhkKEW9wdGlvbmFsX3NmaXhlZDY0GAogASgQ",
+            "EhYKDm9wdGlvbmFsX2Zsb2F0GAsgASgCEhcKD29wdGlvbmFsX2RvdWJsZRgM",
+            "IAEoARIVCg1vcHRpb25hbF9ib29sGA0gASgIEhcKD29wdGlvbmFsX3N0cmlu",
+            "ZxgOIAEoCRIWCg5vcHRpb25hbF9ieXRlcxgPIAEoDBJgChdvcHRpb25hbF9u",
+            "ZXN0ZWRfbWVzc2FnZRgSIAEoCzI/LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMu",
+            "cHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRNZXNzYWdlEk8KGG9w",
+            "dGlvbmFsX2ZvcmVpZ25fbWVzc2FnZRgTIAEoCzItLnByb3RvYnVmX3Rlc3Rf",
+            "bWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlEloKFG9wdGlvbmFsX25l",
+            "c3RlZF9lbnVtGBUgASgOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90",
+            "bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW0SSQoVb3B0aW9uYWxf",
+            "Zm9yZWlnbl9lbnVtGBYgASgOMioucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5w",
+            "cm90bzMuRm9yZWlnbkVudW0SIQoVb3B0aW9uYWxfc3RyaW5nX3BpZWNlGBgg",
+            "ASgJQgIIAhIZCg1vcHRpb25hbF9jb3JkGBkgASgJQgIIARJMChFyZWN1cnNp",
+            "dmVfbWVzc2FnZRgbIAEoCzIxLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJv",
+            "dG8zLlRlc3RBbGxUeXBlc1Byb3RvMxIWCg5yZXBlYXRlZF9pbnQzMhgfIAMo",
+            "BRIWCg5yZXBlYXRlZF9pbnQ2NBggIAMoAxIXCg9yZXBlYXRlZF91aW50MzIY",
+            "ISADKA0SFwoPcmVwZWF0ZWRfdWludDY0GCIgAygEEhcKD3JlcGVhdGVkX3Np",
+            "bnQzMhgjIAMoERIXCg9yZXBlYXRlZF9zaW50NjQYJCADKBISGAoQcmVwZWF0",
+            "ZWRfZml4ZWQzMhglIAMoBxIYChByZXBlYXRlZF9maXhlZDY0GCYgAygGEhkK",
+            "EXJlcGVhdGVkX3NmaXhlZDMyGCcgAygPEhkKEXJlcGVhdGVkX3NmaXhlZDY0",
+            "GCggAygQEhYKDnJlcGVhdGVkX2Zsb2F0GCkgAygCEhcKD3JlcGVhdGVkX2Rv",
+            "dWJsZRgqIAMoARIVCg1yZXBlYXRlZF9ib29sGCsgAygIEhcKD3JlcGVhdGVk",
+            "X3N0cmluZxgsIAMoCRIWCg5yZXBlYXRlZF9ieXRlcxgtIAMoDBJgChdyZXBl",
+            "YXRlZF9uZXN0ZWRfbWVzc2FnZRgwIAMoCzI/LnByb3RvYnVmX3Rlc3RfbWVz",
+            "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5OZXN0ZWRNZXNzYWdl",
+            "Ek8KGHJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZRgxIAMoCzItLnByb3RvYnVm",
+            "X3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlEloKFHJlcGVh",
+            "dGVkX25lc3RlZF9lbnVtGDMgAygOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdl",
+            "cy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW0SSQoVcmVw",
+            "ZWF0ZWRfZm9yZWlnbl9lbnVtGDQgAygOMioucHJvdG9idWZfdGVzdF9tZXNz",
+            "YWdlcy5wcm90bzMuRm9yZWlnbkVudW0SIQoVcmVwZWF0ZWRfc3RyaW5nX3Bp",
+            "ZWNlGDYgAygJQgIIAhIZCg1yZXBlYXRlZF9jb3JkGDcgAygJQgIIARJdCg9t",
+            "YXBfaW50MzJfaW50MzIYOCADKAsyRC5wcm90b2J1Zl90ZXN0X21lc3NhZ2Vz",
+            "LnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwSW50MzJJbnQzMkVudHJ5",
+            "El0KD21hcF9pbnQ2NF9pbnQ2NBg5IAMoCzJELnByb3RvYnVmX3Rlc3RfbWVz",
+            "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBJbnQ2NEludDY0",
+            "RW50cnkSYQoRbWFwX3VpbnQzMl91aW50MzIYOiADKAsyRi5wcm90b2J1Zl90",
+            "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwVWlu",
+            "dDMyVWludDMyRW50cnkSYQoRbWFwX3VpbnQ2NF91aW50NjQYOyADKAsyRi5w",
+            "cm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90",
+            "bzMuTWFwVWludDY0VWludDY0RW50cnkSYQoRbWFwX3NpbnQzMl9zaW50MzIY",
+            "PCADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxs",
+            "VHlwZXNQcm90bzMuTWFwU2ludDMyU2ludDMyRW50cnkSYQoRbWFwX3NpbnQ2",
+            "NF9zaW50NjQYPSADKAsyRi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3Rv",
+            "My5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU2ludDY0U2ludDY0RW50cnkSZQoT",
+            "bWFwX2ZpeGVkMzJfZml4ZWQzMhg+IAMoCzJILnByb3RvYnVmX3Rlc3RfbWVz",
+            "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBGaXhlZDMyRml4",
+            "ZWQzMkVudHJ5EmUKE21hcF9maXhlZDY0X2ZpeGVkNjQYPyADKAsySC5wcm90",
+            "b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMu",
+            "TWFwRml4ZWQ2NEZpeGVkNjRFbnRyeRJpChVtYXBfc2ZpeGVkMzJfc2ZpeGVk",
+            "MzIYQCADKAsySi5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0",
+            "QWxsVHlwZXNQcm90bzMuTWFwU2ZpeGVkMzJTZml4ZWQzMkVudHJ5EmkKFW1h",
+            "cF9zZml4ZWQ2NF9zZml4ZWQ2NBhBIAMoCzJKLnByb3RvYnVmX3Rlc3RfbWVz",
+            "c2FnZXMucHJvdG8zLlRlc3RBbGxUeXBlc1Byb3RvMy5NYXBTZml4ZWQ2NFNm",
+            "aXhlZDY0RW50cnkSXQoPbWFwX2ludDMyX2Zsb2F0GEIgAygLMkQucHJvdG9i",
+            "dWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1h",
+            "cEludDMyRmxvYXRFbnRyeRJfChBtYXBfaW50MzJfZG91YmxlGEMgAygLMkUu",
+            "cHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJv",
+            "dG8zLk1hcEludDMyRG91YmxlRW50cnkSWQoNbWFwX2Jvb2xfYm9vbBhEIAMo",
+            "CzJCLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBl",
+            "c1Byb3RvMy5NYXBCb29sQm9vbEVudHJ5EmEKEW1hcF9zdHJpbmdfc3RyaW5n",
+            "GEUgAygLMkYucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFs",
+            "bFR5cGVzUHJvdG8zLk1hcFN0cmluZ1N0cmluZ0VudHJ5El8KEG1hcF9zdHJp",
+            "bmdfYnl0ZXMYRiADKAsyRS5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3Rv",
+            "My5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU3RyaW5nQnl0ZXNFbnRyeRJwChlt",
+            "YXBfc3RyaW5nX25lc3RlZF9tZXNzYWdlGEcgAygLMk0ucHJvdG9idWZfdGVz",
+            "dF9tZXNzYWdlcy5wcm90bzMuVGVzdEFsbFR5cGVzUHJvdG8zLk1hcFN0cmlu",
+            "Z05lc3RlZE1lc3NhZ2VFbnRyeRJyChptYXBfc3RyaW5nX2ZvcmVpZ25fbWVz",
+            "c2FnZRhIIAMoCzJOLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRl",
+            "c3RBbGxUeXBlc1Byb3RvMy5NYXBTdHJpbmdGb3JlaWduTWVzc2FnZUVudHJ5",
+            "EmoKFm1hcF9zdHJpbmdfbmVzdGVkX2VudW0YSSADKAsySi5wcm90b2J1Zl90",
+            "ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90bzMuTWFwU3Ry",
+            "aW5nTmVzdGVkRW51bUVudHJ5EmwKF21hcF9zdHJpbmdfZm9yZWlnbl9lbnVt",
+            "GEogAygLMksucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuVGVzdEFs",
+            "bFR5cGVzUHJvdG8zLk1hcFN0cmluZ0ZvcmVpZ25FbnVtRW50cnkSFgoMb25l",
+            "b2ZfdWludDMyGG8gASgNSAASXwoUb25lb2ZfbmVzdGVkX21lc3NhZ2UYcCAB",
+            "KAsyPy5wcm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlw",
+            "ZXNQcm90bzMuTmVzdGVkTWVzc2FnZUgAEhYKDG9uZW9mX3N0cmluZxhxIAEo",
+            "CUgAEhUKC29uZW9mX2J5dGVzGHIgASgMSAASFAoKb25lb2ZfYm9vbBhzIAEo",
+            "CEgAEhYKDG9uZW9mX3VpbnQ2NBh0IAEoBEgAEhUKC29uZW9mX2Zsb2F0GHUg",
+            "ASgCSAASFgoMb25lb2ZfZG91YmxlGHYgASgBSAASUgoKb25lb2ZfZW51bRh3",
+            "IAEoDjI8LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxU",
+            "eXBlc1Byb3RvMy5OZXN0ZWRFbnVtSAASOgoVb3B0aW9uYWxfYm9vbF93cmFw",
+            "cGVyGMkBIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5Cb29sVmFsdWUSPAoWb3B0",
+            "aW9uYWxfaW50MzJfd3JhcHBlchjKASABKAsyGy5nb29nbGUucHJvdG9idWYu",
+            "SW50MzJWYWx1ZRI8ChZvcHRpb25hbF9pbnQ2NF93cmFwcGVyGMsBIAEoCzIb",
+            "Lmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEj4KF29wdGlvbmFsX3VpbnQz",
+            "Ml93cmFwcGVyGMwBIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1",
+            "ZRI+ChdvcHRpb25hbF91aW50NjRfd3JhcHBlchjNASABKAsyHC5nb29nbGUu",
+            "cHJvdG9idWYuVUludDY0VmFsdWUSPAoWb3B0aW9uYWxfZmxvYXRfd3JhcHBl",
+            "chjOASABKAsyGy5nb29nbGUucHJvdG9idWYuRmxvYXRWYWx1ZRI+ChdvcHRp",
+            "b25hbF9kb3VibGVfd3JhcHBlchjPASABKAsyHC5nb29nbGUucHJvdG9idWYu",
+            "RG91YmxlVmFsdWUSPgoXb3B0aW9uYWxfc3RyaW5nX3dyYXBwZXIY0AEgASgL",
+            "MhwuZ29vZ2xlLnByb3RvYnVmLlN0cmluZ1ZhbHVlEjwKFm9wdGlvbmFsX2J5",
+            "dGVzX3dyYXBwZXIY0QEgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFs",
+            "dWUSOgoVcmVwZWF0ZWRfYm9vbF93cmFwcGVyGNMBIAMoCzIaLmdvb2dsZS5w",
+            "cm90b2J1Zi5Cb29sVmFsdWUSPAoWcmVwZWF0ZWRfaW50MzJfd3JhcHBlchjU",
+            "ASADKAsyGy5nb29nbGUucHJvdG9idWYuSW50MzJWYWx1ZRI8ChZyZXBlYXRl",
+            "ZF9pbnQ2NF93cmFwcGVyGNUBIAMoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2",
+            "NFZhbHVlEj4KF3JlcGVhdGVkX3VpbnQzMl93cmFwcGVyGNYBIAMoCzIcLmdv",
+            "b2dsZS5wcm90b2J1Zi5VSW50MzJWYWx1ZRI+ChdyZXBlYXRlZF91aW50NjRf",
+            "d3JhcHBlchjXASADKAsyHC5nb29nbGUucHJvdG9idWYuVUludDY0VmFsdWUS",
+            "PAoWcmVwZWF0ZWRfZmxvYXRfd3JhcHBlchjYASADKAsyGy5nb29nbGUucHJv",
+            "dG9idWYuRmxvYXRWYWx1ZRI+ChdyZXBlYXRlZF9kb3VibGVfd3JhcHBlchjZ",
+            "ASADKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSPgoXcmVwZWF0",
+            "ZWRfc3RyaW5nX3dyYXBwZXIY2gEgAygLMhwuZ29vZ2xlLnByb3RvYnVmLlN0",
+            "cmluZ1ZhbHVlEjwKFnJlcGVhdGVkX2J5dGVzX3dyYXBwZXIY2wEgAygLMhsu",
+            "Z29vZ2xlLnByb3RvYnVmLkJ5dGVzVmFsdWUSNQoRb3B0aW9uYWxfZHVyYXRp",
+            "b24YrQIgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEm9wdGlv",
+            "bmFsX3RpbWVzdGFtcBiuAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0",
+            "YW1wEjgKE29wdGlvbmFsX2ZpZWxkX21hc2sYrwIgASgLMhouZ29vZ2xlLnBy",
+            "b3RvYnVmLkZpZWxkTWFzaxIxCg9vcHRpb25hbF9zdHJ1Y3QYsAIgASgLMhcu",
+            "Z29vZ2xlLnByb3RvYnVmLlN0cnVjdBIrCgxvcHRpb25hbF9hbnkYsQIgASgL",
+            "MhQuZ29vZ2xlLnByb3RvYnVmLkFueRIvCg5vcHRpb25hbF92YWx1ZRiyAiAB",
+            "KAsyFi5nb29nbGUucHJvdG9idWYuVmFsdWUSNQoRcmVwZWF0ZWRfZHVyYXRp",
+            "b24YtwIgAygLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEjcKEnJlcGVh",
+            "dGVkX3RpbWVzdGFtcBi4AiADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0",
+            "YW1wEjcKEnJlcGVhdGVkX2ZpZWxkbWFzaxi5AiADKAsyGi5nb29nbGUucHJv",
+            "dG9idWYuRmllbGRNYXNrEjEKD3JlcGVhdGVkX3N0cnVjdBjEAiADKAsyFy5n",
+            "b29nbGUucHJvdG9idWYuU3RydWN0EisKDHJlcGVhdGVkX2FueRi7AiADKAsy",
+            "FC5nb29nbGUucHJvdG9idWYuQW55Ei8KDnJlcGVhdGVkX3ZhbHVlGLwCIAMo",
+            "CzIWLmdvb2dsZS5wcm90b2J1Zi5WYWx1ZRITCgpmaWVsZG5hbWUxGJEDIAEo",
+            "BRIUCgtmaWVsZF9uYW1lMhiSAyABKAUSFQoMX2ZpZWxkX25hbWUzGJMDIAEo",
+            "BRIWCg1maWVsZF9fbmFtZTRfGJQDIAEoBRIUCgtmaWVsZDBuYW1lNRiVAyAB",
+            "KAUSFgoNZmllbGRfMF9uYW1lNhiWAyABKAUSEwoKZmllbGROYW1lNxiXAyAB",
+            "KAUSEwoKRmllbGROYW1lOBiYAyABKAUSFAoLZmllbGRfTmFtZTkYmQMgASgF",
+            "EhUKDEZpZWxkX05hbWUxMBiaAyABKAUSFQoMRklFTERfTkFNRTExGJsDIAEo",
+            "BRIVCgxGSUVMRF9uYW1lMTIYnAMgASgFEhcKDl9fZmllbGRfbmFtZTEzGJ0D",
+            "IAEoBRIXCg5fX0ZpZWxkX25hbWUxNBieAyABKAUSFgoNZmllbGRfX25hbWUx",
+            "NRifAyABKAUSFgoNZmllbGRfX05hbWUxNhigAyABKAUSFwoOZmllbGRfbmFt",
+            "ZTE3X18YoQMgASgFEhcKDkZpZWxkX25hbWUxOF9fGKIDIAEoBRpiCg1OZXN0",
+            "ZWRNZXNzYWdlEgkKAWEYASABKAUSRgoLY29yZWN1cnNpdmUYAiABKAsyMS5w",
+            "cm90b2J1Zl90ZXN0X21lc3NhZ2VzLnByb3RvMy5UZXN0QWxsVHlwZXNQcm90",
+            "bzMaNAoSTWFwSW50MzJJbnQzMkVudHJ5EgsKA2tleRgBIAEoBRINCgV2YWx1",
+            "ZRgCIAEoBToCOAEaNAoSTWFwSW50NjRJbnQ2NEVudHJ5EgsKA2tleRgBIAEo",
+            "AxINCgV2YWx1ZRgCIAEoAzoCOAEaNgoUTWFwVWludDMyVWludDMyRW50cnkS",
+            "CwoDa2V5GAEgASgNEg0KBXZhbHVlGAIgASgNOgI4ARo2ChRNYXBVaW50NjRV",
+            "aW50NjRFbnRyeRILCgNrZXkYASABKAQSDQoFdmFsdWUYAiABKAQ6AjgBGjYK",
+            "FE1hcFNpbnQzMlNpbnQzMkVudHJ5EgsKA2tleRgBIAEoERINCgV2YWx1ZRgC",
+            "IAEoEToCOAEaNgoUTWFwU2ludDY0U2ludDY0RW50cnkSCwoDa2V5GAEgASgS",
+            "Eg0KBXZhbHVlGAIgASgSOgI4ARo4ChZNYXBGaXhlZDMyRml4ZWQzMkVudHJ5",
+            "EgsKA2tleRgBIAEoBxINCgV2YWx1ZRgCIAEoBzoCOAEaOAoWTWFwRml4ZWQ2",
+            "NEZpeGVkNjRFbnRyeRILCgNrZXkYASABKAYSDQoFdmFsdWUYAiABKAY6AjgB",
+            "GjoKGE1hcFNmaXhlZDMyU2ZpeGVkMzJFbnRyeRILCgNrZXkYASABKA8SDQoF",
+            "dmFsdWUYAiABKA86AjgBGjoKGE1hcFNmaXhlZDY0U2ZpeGVkNjRFbnRyeRIL",
+            "CgNrZXkYASABKBASDQoFdmFsdWUYAiABKBA6AjgBGjQKEk1hcEludDMyRmxv",
+            "YXRFbnRyeRILCgNrZXkYASABKAUSDQoFdmFsdWUYAiABKAI6AjgBGjUKE01h",
+            "cEludDMyRG91YmxlRW50cnkSCwoDa2V5GAEgASgFEg0KBXZhbHVlGAIgASgB",
+            "OgI4ARoyChBNYXBCb29sQm9vbEVudHJ5EgsKA2tleRgBIAEoCBINCgV2YWx1",
+            "ZRgCIAEoCDoCOAEaNgoUTWFwU3RyaW5nU3RyaW5nRW50cnkSCwoDa2V5GAEg",
+            "ASgJEg0KBXZhbHVlGAIgASgJOgI4ARo1ChNNYXBTdHJpbmdCeXRlc0VudHJ5",
+            "EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoDDoCOAEafgobTWFwU3RyaW5n",
+            "TmVzdGVkTWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRJOCgV2YWx1ZRgCIAEo",
+            "CzI/LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLlRlc3RBbGxUeXBl",
+            "c1Byb3RvMy5OZXN0ZWRNZXNzYWdlOgI4ARptChxNYXBTdHJpbmdGb3JlaWdu",
+            "TWVzc2FnZUVudHJ5EgsKA2tleRgBIAEoCRI8CgV2YWx1ZRgCIAEoCzItLnBy",
+            "b3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zLkZvcmVpZ25NZXNzYWdlOgI4",
+            "ARp4ChhNYXBTdHJpbmdOZXN0ZWRFbnVtRW50cnkSCwoDa2V5GAEgASgJEksK",
+            "BXZhbHVlGAIgASgOMjwucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMu",
+            "VGVzdEFsbFR5cGVzUHJvdG8zLk5lc3RlZEVudW06AjgBGmcKGU1hcFN0cmlu",
             "Z0ZvcmVpZ25FbnVtRW50cnkSCwoDa2V5GAEgASgJEjkKBXZhbHVlGAIgASgO",
             "MioucHJvdG9idWZfdGVzdF9tZXNzYWdlcy5wcm90bzMuRm9yZWlnbkVudW06",
             "AjgBIjkKCk5lc3RlZEVudW0SBwoDRk9PEAASBwoDQkFSEAESBwoDQkFaEAIS",
             "EAoDTkVHEP///////////wFCDQoLb25lb2ZfZmllbGQiGwoORm9yZWlnbk1l",
             "c3NhZ2USCQoBYxgBIAEoBSpACgtGb3JlaWduRW51bRIPCgtGT1JFSUdOX0ZP",
-            "TxAAEg8KC0ZPUkVJR05fQkFSEAESDwoLRk9SRUlHTl9CQVoQAkIvCihjb20u",
-            "Z29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zSAH4AQFiBnBy",
-            "b3RvMw=="));
+            "TxAAEg8KC0ZPUkVJR05fQkFSEAESDwoLRk9SRUlHTl9CQVoQAkI4Cihjb20u",
+            "Z29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8zSAH4AQGiAgZQ",
+            "cm90bzNiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.AnyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.FieldMaskReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto3.ForeignEnum), }, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypes), global::ProtobufTestMessages.Proto3.TestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "RecursiveMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "MapInt32Int32", "MapInt64Int64", "MapUint32Uint32", "MapUint64Uint64", "MapSint32Sint32", "MapSint64Sint64", "MapFixed32Fixed32", "MapFixed64Fixed64", "MapSfixed32Sfixed32", "MapSfixed64Sfixed64", "MapInt32Float", "MapInt32Double", "MapBoolBool", "MapStringString", "MapStringBytes", "MapStringNestedMessage", "MapStringForeignMessage", "MapStringNestedEnum", "MapStringForeignEnum", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofBool", "OneofUint64", "OneofFloat", "OneofDouble", "OneofEnum", "OptionalBoolWrapper", "OptionalInt32Wrapper", "OptionalInt64Wrapper", "OptionalUint32Wrapper", "OptionalUint64Wrapper", "OptionalFloatWrapper", "OptionalDoubleWrapper", "OptionalStringWrapper", "OptionalBytesWrapper", "RepeatedBoolWrapper", "RepeatedInt32Wrapper", "RepeatedInt64Wrapper", "RepeatedUint32Wrapper", "RepeatedUint64Wrapper", "RepeatedFloatWrapper", "RepeatedDoubleWrapper", "RepeatedStringWrapper", "RepeatedBytesWrapper", "OptionalDuration", "OptionalTimestamp", "OptionalFieldMask", "OptionalStruct", "OptionalAny", "OptionalValue", "RepeatedDuration", "RepeatedTimestamp", "RepeatedFieldmask", "RepeatedStruct", "RepeatedAny", "RepeatedValue", "Fieldname1", "FieldName2", "FieldName3", "FieldName4", "Field0Name5", "Field0Name6", "FieldName7", "FieldName8", "FieldName9", "FieldName10", "FIELDNAME11", "FIELDName12", "FieldName13", "FieldName14", "FieldName15", "FieldName16", "FieldName17", "FieldName18" }, new[]{ "OneofField" }, new[]{ typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) }, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage), global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser, new[]{ "A", "Corecursive" }, null, null, null),
             null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, }),
             new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto3.ForeignMessage), global::ProtobufTestMessages.Proto3.ForeignMessage.Parser, new[]{ "C" }, null, null, null)
           }));
@@ -227,10 +231,10 @@
   /// could trigger bugs that occur in any message type in this file.  We verify
   /// this stays true in a unit test.
   /// </summary>
-  public sealed partial class TestAllTypes : pb::IMessage<TestAllTypes> {
-    private static readonly pb::MessageParser<TestAllTypes> _parser = new pb::MessageParser<TestAllTypes>(() => new TestAllTypes());
+  public sealed partial class TestAllTypesProto3 : pb::IMessage<TestAllTypesProto3> {
+    private static readonly pb::MessageParser<TestAllTypesProto3> _parser = new pb::MessageParser<TestAllTypesProto3>(() => new TestAllTypesProto3());
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public static pb::MessageParser<TestAllTypes> Parser { get { return _parser; } }
+    public static pb::MessageParser<TestAllTypesProto3> Parser { get { return _parser; } }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
@@ -243,14 +247,14 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public TestAllTypes() {
+    public TestAllTypesProto3() {
       OnConstruction();
     }
 
     partial void OnConstruction();
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public TestAllTypes(TestAllTypes other) : this() {
+    public TestAllTypesProto3(TestAllTypesProto3 other) : this() {
       optionalInt32_ = other.optionalInt32_;
       optionalInt64_ = other.optionalInt64_;
       optionalUint32_ = other.optionalUint32_;
@@ -394,8 +398,8 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public TestAllTypes Clone() {
-      return new TestAllTypes(this);
+    public TestAllTypesProto3 Clone() {
+      return new TestAllTypesProto3(this);
     }
 
     /// <summary>Field number for the "optional_int32" field.</summary>
@@ -568,9 +572,9 @@
 
     /// <summary>Field number for the "optional_nested_message" field.</summary>
     public const int OptionalNestedMessageFieldNumber = 18;
-    private global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage optionalNestedMessage_;
+    private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage optionalNestedMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage OptionalNestedMessage {
+    public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OptionalNestedMessage {
       get { return optionalNestedMessage_; }
       set {
         optionalNestedMessage_ = value;
@@ -590,9 +594,9 @@
 
     /// <summary>Field number for the "optional_nested_enum" field.</summary>
     public const int OptionalNestedEnumFieldNumber = 21;
-    private global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = 0;
+    private global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum optionalNestedEnum_ = 0;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum OptionalNestedEnum {
+    public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OptionalNestedEnum {
       get { return optionalNestedEnum_; }
       set {
         optionalNestedEnum_ = value;
@@ -634,9 +638,9 @@
 
     /// <summary>Field number for the "recursive_message" field.</summary>
     public const int RecursiveMessageFieldNumber = 27;
-    private global::ProtobufTestMessages.Proto3.TestAllTypes recursiveMessage_;
+    private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 recursiveMessage_;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public global::ProtobufTestMessages.Proto3.TestAllTypes RecursiveMessage {
+    public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 RecursiveMessage {
       get { return recursiveMessage_; }
       set {
         recursiveMessage_ = value;
@@ -798,11 +802,11 @@
 
     /// <summary>Field number for the "repeated_nested_message" field.</summary>
     public const int RepeatedNestedMessageFieldNumber = 48;
-    private static readonly pb::FieldCodec<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage> _repeated_repeatedNestedMessage_codec
-        = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage.Parser);
-    private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage>();
+    private static readonly pb::FieldCodec<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> _repeated_repeatedNestedMessage_codec
+        = pb::FieldCodec.ForMessage(386, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser);
+    private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> repeatedNestedMessage_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage> RepeatedNestedMessage {
+    public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> RepeatedNestedMessage {
       get { return repeatedNestedMessage_; }
     }
 
@@ -818,11 +822,11 @@
 
     /// <summary>Field number for the "repeated_nested_enum" field.</summary>
     public const int RepeatedNestedEnumFieldNumber = 51;
-    private static readonly pb::FieldCodec<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
-        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum) x);
-    private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum>();
+    private static readonly pb::FieldCodec<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> _repeated_repeatedNestedEnum_codec
+        = pb::FieldCodec.ForEnum(410, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x);
+    private readonly pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> repeatedNestedEnum_ = new pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum> RepeatedNestedEnum {
+    public pbc::RepeatedField<global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> RepeatedNestedEnum {
       get { return repeatedNestedEnum_; }
     }
 
@@ -1011,11 +1015,11 @@
 
     /// <summary>Field number for the "map_string_nested_message" field.</summary>
     public const int MapStringNestedMessageFieldNumber = 71;
-    private static readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage>.Codec _map_mapStringNestedMessage_codec
-        = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage.Parser), 570);
-    private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage>();
+    private static readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>.Codec _map_mapStringNestedMessage_codec
+        = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForMessage(18, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage.Parser), 570);
+    private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> mapStringNestedMessage_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage> MapStringNestedMessage {
+    public pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage> MapStringNestedMessage {
       get { return mapStringNestedMessage_; }
     }
 
@@ -1031,11 +1035,11 @@
 
     /// <summary>Field number for the "map_string_nested_enum" field.</summary>
     public const int MapStringNestedEnumFieldNumber = 73;
-    private static readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum>.Codec _map_mapStringNestedEnum_codec
-        = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum) x), 586);
-    private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum>();
+    private static readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>.Codec _map_mapStringNestedEnum_codec
+        = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>.Codec(pb::FieldCodec.ForString(10), pb::FieldCodec.ForEnum(16, x => (int) x, x => (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) x), 586);
+    private readonly pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> mapStringNestedEnum_ = new pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum>();
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum> MapStringNestedEnum {
+    public pbc::MapField<string, global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum> MapStringNestedEnum {
       get { return mapStringNestedEnum_; }
     }
 
@@ -1063,8 +1067,8 @@
     /// <summary>Field number for the "oneof_nested_message" field.</summary>
     public const int OneofNestedMessageFieldNumber = 112;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage OneofNestedMessage {
-      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage) oneofField_ : null; }
+    public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage OneofNestedMessage {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage) oneofField_ : null; }
       set {
         oneofField_ = value;
         oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
@@ -1140,8 +1144,8 @@
     /// <summary>Field number for the "oneof_enum" field.</summary>
     public const int OneofEnumFieldNumber = 119;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum OneofEnum {
-      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum) oneofField_ : 0; }
+    public global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum OneofEnum {
+      get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) oneofField_ : 0; }
       set {
         oneofField_ = value;
         oneofFieldCase_ = OneofFieldOneofCase.OneofEnum;
@@ -1705,11 +1709,11 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
-      return Equals(other as TestAllTypes);
+      return Equals(other as TestAllTypesProto3);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public bool Equals(TestAllTypes other) {
+    public bool Equals(TestAllTypesProto3 other) {
       if (ReferenceEquals(other, null)) {
         return false;
       }
@@ -2530,7 +2534,7 @@
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    public void MergeFrom(TestAllTypes other) {
+    public void MergeFrom(TestAllTypesProto3 other) {
       if (other == null) {
         return;
       }
@@ -2581,7 +2585,7 @@
       }
       if (other.optionalNestedMessage_ != null) {
         if (optionalNestedMessage_ == null) {
-          optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage();
+          optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
         }
         OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
       }
@@ -2605,7 +2609,7 @@
       }
       if (other.recursiveMessage_ != null) {
         if (recursiveMessage_ == null) {
-          recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypes();
+          recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
         }
         RecursiveMessage.MergeFrom(other.RecursiveMessage);
       }
@@ -2901,7 +2905,7 @@
           }
           case 146: {
             if (optionalNestedMessage_ == null) {
-              optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage();
+              optionalNestedMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
             }
             input.ReadMessage(optionalNestedMessage_);
             break;
@@ -2914,7 +2918,7 @@
             break;
           }
           case 168: {
-            optionalNestedEnum_ = (global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedEnum) input.ReadEnum();
+            optionalNestedEnum_ = (global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedEnum) input.ReadEnum();
             break;
           }
           case 176: {
@@ -2931,7 +2935,7 @@
           }
           case 218: {
             if (recursiveMessage_ == null) {
-              recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypes();
+              recursiveMessage_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
             }
             input.ReadMessage(recursiveMessage_);
             break;
@@ -3116,7 +3120,7 @@
             break;
           }
           case 898: {
-            global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto3.TestAllTypes.Types.NestedMessage();
+            global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Types.NestedMessage();
             if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
               subBuilder.MergeFrom(OneofNestedMessage);
             }
@@ -3395,7 +3399,7 @@
     }
 
     #region Nested types
-    /// <summary>Container for nested types declared in the TestAllTypes message type.</summary>
+    /// <summary>Container for nested types declared in the TestAllTypesProto3 message type.</summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static partial class Types {
       public enum NestedEnum {
@@ -3415,7 +3419,7 @@
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public static pbr::MessageDescriptor Descriptor {
-          get { return global::ProtobufTestMessages.Proto3.TestAllTypes.Descriptor.NestedTypes[0]; }
+          get { return global::ProtobufTestMessages.Proto3.TestAllTypesProto3.Descriptor.NestedTypes[0]; }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3454,9 +3458,9 @@
 
         /// <summary>Field number for the "corecursive" field.</summary>
         public const int CorecursiveFieldNumber = 2;
-        private global::ProtobufTestMessages.Proto3.TestAllTypes corecursive_;
+        private global::ProtobufTestMessages.Proto3.TestAllTypesProto3 corecursive_;
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-        public global::ProtobufTestMessages.Proto3.TestAllTypes Corecursive {
+        public global::ProtobufTestMessages.Proto3.TestAllTypesProto3 Corecursive {
           get { return corecursive_; }
           set {
             corecursive_ = value;
@@ -3528,7 +3532,7 @@
           }
           if (other.corecursive_ != null) {
             if (corecursive_ == null) {
-              corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypes();
+              corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
             }
             Corecursive.MergeFrom(other.Corecursive);
           }
@@ -3548,7 +3552,7 @@
               }
               case 18: {
                 if (corecursive_ == null) {
-                  corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypes();
+                  corecursive_ = new global::ProtobufTestMessages.Proto3.TestAllTypesProto3();
                 }
                 input.ReadMessage(corecursive_);
                 break;
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
index 4aecc99..a3edd59 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
@@ -91,6 +91,24 @@
         }
 
         [Test]
+        public void TryUnpack_WrongType()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message);
+            Assert.False(any.TryUnpack(out TestOneof unpacked));
+            Assert.Null(unpacked);
+        }
+
+        [Test]
+        public void TryUnpack_RightType()
+        {
+            var message = SampleMessages.CreateFullTestAllTypes();
+            var any = Any.Pack(message);
+            Assert.IsTrue(any.TryUnpack(out TestAllTypes unpacked));
+            Assert.AreEqual(message, unpacked);
+        }
+
+        [Test]
         public void ToString_WithValues()
         {
             var message = SampleMessages.CreateFullTestAllTypes();
@@ -100,6 +118,16 @@
         }
 
         [Test]
+        [TestCase("proto://foo.bar", "foo.bar")]
+        [TestCase("/foo/bar/baz", "baz")]
+        [TestCase("foobar", "")]
+        public void GetTypeName(string typeUrl, string expectedTypeName)
+        {
+            var any = new Any { TypeUrl = typeUrl };
+            Assert.AreEqual(expectedTypeName, Any.GetTypeName(typeUrl));
+        }
+
+        [Test]
         public void ToString_Empty()
         {
             var any = new Any();
diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs
index 072e2e1..abd352b 100644
--- a/csharp/src/Google.Protobuf/CodedInputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedInputStream.cs
@@ -121,7 +121,7 @@
         /// <summary>

         /// Creates a new CodedInputStream reading data from the given byte array.

         /// </summary>

-        public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length)

+        public CodedInputStream(byte[] buffer) : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), 0, buffer.Length, true)

         {            

         }

 

@@ -129,7 +129,7 @@
         /// Creates a new <see cref="CodedInputStream"/> that reads from the given byte array slice.

         /// </summary>

         public CodedInputStream(byte[] buffer, int offset, int length)

-            : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)

+            : this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length, true)

         {            

             if (offset < 0 || offset > buffer.Length)

             {

@@ -158,16 +158,15 @@
         /// <c cref="CodedInputStream"/> is disposed; <c>false</c> to dispose of the given stream when the

         /// returned object is disposed.</param>

         public CodedInputStream(Stream input, bool leaveOpen)

-            : this(ProtoPreconditions.CheckNotNull(input, "input"), new byte[BufferSize], 0, 0)

+            : this(ProtoPreconditions.CheckNotNull(input, "input"), new byte[BufferSize], 0, 0, leaveOpen)

         {

-            this.leaveOpen = leaveOpen;

         }

         

         /// <summary>

         /// Creates a new CodedInputStream reading data from the given

         /// stream and buffer, using the default limits.

         /// </summary>

-        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize)

+        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, bool leaveOpen)

         {

             this.input = input;

             this.buffer = buffer;

@@ -175,6 +174,7 @@
             this.bufferSize = bufferSize;

             this.sizeLimit = DefaultSizeLimit;

             this.recursionLimit = DefaultRecursionLimit;

+            this.leaveOpen = leaveOpen;

         }

 

         /// <summary>

@@ -185,8 +185,8 @@
         /// This chains to the version with the default limits instead of vice versa to avoid

         /// having to check that the default values are valid every time.

         /// </remarks>

-        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit)

-            : this(input, buffer, bufferPos, bufferSize)

+        internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit, bool leaveOpen)

+            : this(input, buffer, bufferPos, bufferSize, leaveOpen)

         {

             if (sizeLimit <= 0)

             {

@@ -217,7 +217,8 @@
         /// and recursion limits.</returns>

         public static CodedInputStream CreateWithLimits(Stream input, int sizeLimit, int recursionLimit)

         {

-            return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit);

+            // Note: we may want an overload accepting leaveOpen

+            return new CodedInputStream(input, new byte[BufferSize], 0, 0, sizeLimit, recursionLimit, false);

         }

 

         /// <summary>

@@ -372,9 +373,9 @@
 

                 lastTag = ReadRawVarint32();

             }

-            if (lastTag == 0)

+            if (WireFormat.GetTagFieldNumber(lastTag) == 0)

             {

-                // If we actually read zero, that's not a valid tag.

+                // If we actually read a tag with a field of 0, that's not a valid tag.

                 throw InvalidProtocolBufferException.InvalidTag();

             }

             return lastTag;

diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs
index ef5651c..8dac8e3 100644
--- a/csharp/src/Google.Protobuf/Collections/MapField.cs
+++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -67,6 +67,9 @@
     /// </para>
     /// </remarks>
     public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
+#if !NET35
+        , IReadOnlyDictionary<TKey, TValue>
+#endif
     {
         // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
         private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
@@ -548,6 +551,14 @@
         }
         #endregion
 
+        #region IReadOnlyDictionary explicit interface implementation
+#if !NET35
+        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
+
+        IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
+#endif
+        #endregion
+
         private class DictionaryEnumerator : IDictionaryEnumerator
         {
             private readonly IEnumerator<KeyValuePair<TKey, TValue>> enumerator;
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index 4eebd99..4e63646 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -4,9 +4,9 @@
     <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
     <Copyright>Copyright 2015, Google Inc.</Copyright>
     <AssemblyTitle>Google Protocol Buffers</AssemblyTitle>
-    <VersionPrefix>3.3.0</VersionPrefix>
+    <VersionPrefix>3.4.0</VersionPrefix>
     <Authors>Google Inc.</Authors>
-    <TargetFrameworks>netstandard1.0;net451</TargetFrameworks>
+    <TargetFrameworks>netstandard1.0;net45</TargetFrameworks>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
@@ -16,7 +16,7 @@
     <PackageProjectUrl>https://github.com/google/protobuf</PackageProjectUrl>
     <PackageLicenseUrl>https://github.com/google/protobuf/blob/master/LICENSE</PackageLicenseUrl>
     <RepositoryType>git</RepositoryType>
-    <RepositoryUrl>https://github.com/nodatime/nodatime.git</RepositoryUrl>
+    <RepositoryUrl>https://github.com/google/protobuf.git</RepositoryUrl>
     <IncludeSymbols>true</IncludeSymbols>
     <IncludeSource>true</IncludeSource>
   </PropertyGroup>
diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
index 2960d1c..8311a2c 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
@@ -35,7 +35,7 @@
             "LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB",
             "KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv",
             "ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m",
-            "bxIOCgZzeW50YXgYDCABKAki8AQKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
+            "bxIOCgZzeW50YXgYDCABKAkiqQUKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
             "GAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
             "RGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMoCzIlLmdvb2dsZS5w",
             "cm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1CgtuZXN0ZWRfdHlwZRgD",
@@ -47,120 +47,126 @@
             "b3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2Fn",
             "ZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsyLi5nb29nbGUucHJv",
             "dG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2",
-            "ZWRfbmFtZRgKIAMoCRosCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
-            "BRILCgNlbmQYAiABKAUaKwoNUmVzZXJ2ZWRSYW5nZRINCgVzdGFydBgBIAEo",
-            "BRILCgNlbmQYAiABKAUivAUKFEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5h",
-            "bWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29v",
-            "Z2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5",
-            "cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJv",
-            "dG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkS",
-            "FQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIR",
-            "Cglqc29uX25hbWUYCiABKAkSLgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5w",
-            "cm90b2J1Zi5GaWVsZE9wdGlvbnMitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQ",
-            "ARIOCgpUWVBFX0ZMT0FUEAISDgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlO",
-            "VDY0EAQSDgoKVFlQRV9JTlQzMhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZ",
-            "UEVfRklYRUQzMhAHEg0KCVRZUEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkS",
-            "DgoKVFlQRV9HUk9VUBAKEhAKDFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllU",
-            "RVMQDBIPCgtUWVBFX1VJTlQzMhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVf",
-            "U0ZJWEVEMzIQDxIRCg1UWVBFX1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQ",
-            "ERIPCgtUWVBFX1NJTlQ2NBASIkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFM",
-            "EAESEgoOTEFCRUxfUkVRVUlSRUQQAhISCg5MQUJFTF9SRVBFQVRFRBADIlQK",
-            "FE9uZW9mRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSLgoHb3B0aW9u",
-            "cxgCIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5PbmVvZk9wdGlvbnMijAEKE0Vu",
-            "dW1EZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMo",
-            "CzIpLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8S",
-            "LQoHb3B0aW9ucxgDIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9u",
-            "cyJsChhFbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIO",
-            "CgZudW1iZXIYAiABKAUSMgoHb3B0aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90",
-            "b2J1Zi5FbnVtVmFsdWVPcHRpb25zIpABChZTZXJ2aWNlRGVzY3JpcHRvclBy",
-            "b3RvEgwKBG5hbWUYASABKAkSNgoGbWV0aG9kGAIgAygLMiYuZ29vZ2xlLnBy",
-            "b3RvYnVmLk1ldGhvZERlc2NyaXB0b3JQcm90bxIwCgdvcHRpb25zGAMgASgL",
-            "Mh8uZ29vZ2xlLnByb3RvYnVmLlNlcnZpY2VPcHRpb25zIsEBChVNZXRob2RE",
-            "ZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIg",
-            "ASgJEhMKC291dHB1dF90eXBlGAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5n",
-            "b29nbGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFt",
-            "aW5nGAUgASgIOgVmYWxzZRIfChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVm",
-            "YWxzZSK0BQoLRmlsZU9wdGlvbnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwK",
-            "FGphdmFfb3V0ZXJfY2xhc3NuYW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVf",
-            "ZmlsZXMYCiABKAg6BWZhbHNlEikKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2Fu",
-            "ZF9oYXNoGBQgASgIQgIYARIlChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsg",
-            "ASgIOgVmYWxzZRJGCgxvcHRpbWl6ZV9mb3IYCSABKA4yKS5nb29nbGUucHJv",
-            "dG9idWYuRmlsZU9wdGlvbnMuT3B0aW1pemVNb2RlOgVTUEVFRBISCgpnb19w",
-            "YWNrYWdlGAsgASgJEiIKE2NjX2dlbmVyaWNfc2VydmljZXMYECABKAg6BWZh",
-            "bHNlEiQKFWphdmFfZ2VuZXJpY19zZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoT",
-            "cHlfZ2VuZXJpY19zZXJ2aWNlcxgSIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRl",
-            "ZBgXIAEoCDoFZmFsc2USHwoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoFZmFs",
-            "c2USGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkSGAoQY3NoYXJwX25hbWVz",
-            "cGFjZRglIAEoCRIUCgxzd2lmdF9wcmVmaXgYJyABKAkSGAoQcGhwX2NsYXNz",
-            "X3ByZWZpeBgoIAEoCRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsy",
-            "JC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRp",
-            "bWl6ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JV",
-            "TlRJTUUQAyoJCOgHEICAgIACSgQIJhAnIvIBCg5NZXNzYWdlT3B0aW9ucxIm",
-            "ChdtZXNzYWdlX3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9f",
-            "c3RhbmRhcmRfZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoK",
-            "ZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMK",
-            "FHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1",
-            "Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgIEAlKBAgJEAoi",
-            "ngMKDEZpZWxkT3B0aW9ucxI6CgVjdHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90",
-            "b2J1Zi5GaWVsZE9wdGlvbnMuQ1R5cGU6BlNUUklORxIOCgZwYWNrZWQYAiAB",
-            "KAgSPwoGanN0eXBlGAYgASgOMiQuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0",
-            "aW9ucy5KU1R5cGU6CUpTX05PUk1BTBITCgRsYXp5GAUgASgIOgVmYWxzZRIZ",
-            "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxz",
-            "ZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJv",
-            "dG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQ",
-            "ABIICgRDT1JEEAESEAoMU1RSSU5HX1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpT",
-            "X05PUk1BTBAAEg0KCUpTX1NUUklORxABEg0KCUpTX05VTUJFUhACKgkI6AcQ",
-            "gICAgAJKBAgEEAUiXgoMT25lb2ZPcHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRf",
-            "b3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVk",
-            "T3B0aW9uKgkI6AcQgICAgAIikwEKC0VudW1PcHRpb25zEhMKC2FsbG93X2Fs",
-            "aWFzGAIgASgIEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEkMKFHVuaW50",
-            "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
-            "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgFEAYifQoQRW51bVZhbHVl",
-            "T3B0aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxzZRJDChR1bmludGVy",
-            "cHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRl",
-            "cnByZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZpY2VPcHRpb25zEhkK",
-            "CmRlcHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0",
+            "ZWRfbmFtZRgKIAMoCRplCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
+            "BRILCgNlbmQYAiABKAUSNwoHb3B0aW9ucxgDIAEoCzImLmdvb2dsZS5wcm90",
+            "b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVzZXJ2ZWRSYW5nZRIN",
+            "CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUiZwoVRXh0ZW5zaW9uUmFuZ2VP",
+            "cHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds",
+            "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIivAUK",
+            "FEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVy",
+            "GAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
+            "RGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5cGUYBSABKA4yKi5nb29nbGUu",
+            "cHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8uVHlwZRIRCgl0eXBlX25h",
+            "bWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkSFQoNZGVmYXVsdF92YWx1ZRgH",
+            "IAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIRCglqc29uX25hbWUYCiABKAkS",
+            "LgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv",
+            "bnMitgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIOCgpUWVBFX0ZMT0FUEAIS",
+            "DgoKVFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQSDgoKVFlQRV9JTlQz",
+            "MhAFEhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklYRUQzMhAHEg0KCVRZ",
+            "UEVfQk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoKVFlQRV9HUk9VUBAKEhAK",
+            "DFRZUEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQDBIPCgtUWVBFX1VJTlQz",
+            "MhANEg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJWEVEMzIQDxIRCg1UWVBF",
+            "X1NGSVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIPCgtUWVBFX1NJTlQ2NBAS",
+            "IkMKBUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAESEgoOTEFCRUxfUkVRVUlS",
+            "RUQQAhISCg5MQUJFTF9SRVBFQVRFRBADIlQKFE9uZW9mRGVzY3JpcHRvclBy",
+            "b3RvEgwKBG5hbWUYASABKAkSLgoHb3B0aW9ucxgCIAEoCzIdLmdvb2dsZS5w",
+            "cm90b2J1Zi5PbmVvZk9wdGlvbnMijAEKE0VudW1EZXNjcmlwdG9yUHJvdG8S",
+            "DAoEbmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIpLmdvb2dsZS5wcm90b2J1",
+            "Zi5FbnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoHb3B0aW9ucxgDIAEoCzIc",
+            "Lmdvb2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucyJsChhFbnVtVmFsdWVEZXNj",
+            "cmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAiABKAUSMgoH",
+            "b3B0aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRp",
+            "b25zIpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkS",
+            "NgoGbWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3RvYnVmLk1ldGhvZERlc2Ny",
+            "aXB0b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8uZ29vZ2xlLnByb3RvYnVm",
+            "LlNlcnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNjcmlwdG9yUHJvdG8SDAoE",
+            "bmFtZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJEhMKC291dHB1dF90eXBl",
+            "GAMgASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29nbGUucHJvdG9idWYuTWV0",
+            "aG9kT3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5nGAUgASgIOgVmYWxzZRIf",
+            "ChBzZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxzZSLwBQoLRmlsZU9wdGlv",
+            "bnMSFAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3Nu",
+            "YW1lGAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNl",
+            "EikKHWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9oYXNoGBQgASgIQgIYARIl",
+            "ChZqYXZhX3N0cmluZ19jaGVja191dGY4GBsgASgIOgVmYWxzZRJGCgxvcHRp",
+            "bWl6ZV9mb3IYCSABKA4yKS5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMu",
+            "T3B0aW1pemVNb2RlOgVTUEVFRBISCgpnb19wYWNrYWdlGAsgASgJEiIKE2Nj",
+            "X2dlbmVyaWNfc2VydmljZXMYECABKAg6BWZhbHNlEiQKFWphdmFfZ2VuZXJp",
+            "Y19zZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoTcHlfZ2VuZXJpY19zZXJ2aWNl",
+            "cxgSIAEoCDoFZmFsc2USIwoUcGhwX2dlbmVyaWNfc2VydmljZXMYEyABKAg6",
+            "BWZhbHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6BWZhbHNlEh8KEGNjX2VuYWJs",
+            "ZV9hcmVuYXMYHyABKAg6BWZhbHNlEhkKEW9iamNfY2xhc3NfcHJlZml4GCQg",
+            "ASgJEhgKEGNzaGFycF9uYW1lc3BhY2UYJSABKAkSFAoMc3dpZnRfcHJlZml4",
+            "GCcgASgJEhgKEHBocF9jbGFzc19wcmVmaXgYKCABKAkSFQoNcGhwX25hbWVz",
+            "cGFjZRgpIAEoCRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5n",
+            "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbiI6CgxPcHRpbWl6",
+            "ZU1vZGUSCQoFU1BFRUQQARINCglDT0RFX1NJWkUQAhIQCgxMSVRFX1JVTlRJ",
+            "TUUQAyoJCOgHEICAgIACSgQIJhAnIvIBCg5NZXNzYWdlT3B0aW9ucxImChdt",
+            "ZXNzYWdlX3NldF93aXJlX2Zvcm1hdBgBIAEoCDoFZmFsc2USLgofbm9fc3Rh",
+            "bmRhcmRfZGVzY3JpcHRvcl9hY2Nlc3NvchgCIAEoCDoFZmFsc2USGQoKZGVw",
+            "cmVjYXRlZBgDIAEoCDoFZmFsc2USEQoJbWFwX2VudHJ5GAcgASgIEkMKFHVu",
+            "aW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5V",
+            "bmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgIEAlKBAgJEAoingMK",
+            "DEZpZWxkT3B0aW9ucxI6CgVjdHlwZRgBIAEoDjIjLmdvb2dsZS5wcm90b2J1",
+            "Zi5GaWVsZE9wdGlvbnMuQ1R5cGU6BlNUUklORxIOCgZwYWNrZWQYAiABKAgS",
+            "PwoGanN0eXBlGAYgASgOMiQuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9u",
+            "cy5KU1R5cGU6CUpTX05PUk1BTBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpk",
+            "ZXByZWNhdGVkGAMgASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJD",
+            "ChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9i",
+            "dWYuVW5pbnRlcnByZXRlZE9wdGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABII",
+            "CgRDT1JEEAESEAoMU1RSSU5HX1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05P",
+            "Uk1BTBAAEg0KCUpTX1NUUklORxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICA",
+            "gAJKBAgEEAUiXgoMT25lb2ZPcHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0",
             "aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0",
-            "aW9uKgkI6AcQgICAgAIirQIKDU1ldGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRl",
-            "ZBghIAEoCDoFZmFsc2USXwoRaWRlbXBvdGVuY3lfbGV2ZWwYIiABKA4yLy5n",
-            "b29nbGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucy5JZGVtcG90ZW5jeUxldmVs",
-            "OhNJREVNUE9URU5DWV9VTktOT1dOEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u",
+            "aW9uKgkI6AcQgICAgAIikwEKC0VudW1PcHRpb25zEhMKC2FsbG93X2FsaWFz",
+            "GAIgASgIEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEkMKFHVuaW50ZXJw",
+            "cmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVy",
+            "cHJldGVkT3B0aW9uKgkI6AcQgICAgAJKBAgFEAYifQoQRW51bVZhbHVlT3B0",
+            "aW9ucxIZCgpkZXByZWNhdGVkGAEgASgIOgVmYWxzZRJDChR1bmludGVycHJl",
+            "dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy",
+            "ZXRlZE9wdGlvbioJCOgHEICAgIACInsKDlNlcnZpY2VPcHRpb25zEhkKCmRl",
+            "cHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u",
             "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u",
-            "IlAKEElkZW1wb3RlbmN5TGV2ZWwSFwoTSURFTVBPVEVOQ1lfVU5LTk9XThAA",
-            "EhMKD05PX1NJREVfRUZGRUNUUxABEg4KCklERU1QT1RFTlQQAioJCOgHEICA",
-            "gIACIp4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiADKAsyLS5n",
-            "b29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1lUGFydBIY",
-            "ChBpZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2ludF92YWx1",
-            "ZRgEIAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoMZG91Ymxl",
-            "X3ZhbHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdh",
-            "dGVfdmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJ",
-            "EhQKDGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNlQ29kZUluZm8SOgoI",
-            "bG9jYXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYuU291cmNlQ29kZUlu",
-            "Zm8uTG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgYASADKAVCAhABEhAK",
-            "BHNwYW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVudHMYAyABKAkSGQoR",
-            "dHJhaWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGluZ19kZXRhY2hlZF9j",
-            "b21tZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUluZm8SQQoKYW5ub3Rh",
-            "dGlvbhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5m",
-            "by5Bbm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0aBgBIAMoBUICEAES",
-            "EwoLc291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyABKAUSCwoDZW5kGAQg",
-            "ASgFQowBChNjb20uZ29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9z",
-            "SAFaPmdpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3Byb3RvYy1nZW4tZ28v",
-            "ZGVzY3JpcHRvcjtkZXNjcmlwdG9yogIDR1BCqgIaR29vZ2xlLlByb3RvYnVm",
-            "LlJlZmxlY3Rpb24="));
+            "KgkI6AcQgICAgAIirQIKDU1ldGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBgh",
+            "IAEoCDoFZmFsc2USXwoRaWRlbXBvdGVuY3lfbGV2ZWwYIiABKA4yLy5nb29n",
+            "bGUucHJvdG9idWYuTWV0aG9kT3B0aW9ucy5JZGVtcG90ZW5jeUxldmVsOhNJ",
+            "REVNUE9URU5DWV9VTktOT1dOEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcH",
+            "IAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIlAK",
+            "EElkZW1wb3RlbmN5TGV2ZWwSFwoTSURFTVBPVEVOQ1lfVU5LTk9XThAAEhMK",
+            "D05PX1NJREVfRUZGRUNUUxABEg4KCklERU1QT1RFTlQQAioJCOgHEICAgIAC",
+            "Ip4CChNVbmludGVycHJldGVkT3B0aW9uEjsKBG5hbWUYAiADKAsyLS5nb29n",
+            "bGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbi5OYW1lUGFydBIYChBp",
+            "ZGVudGlmaWVyX3ZhbHVlGAMgASgJEhoKEnBvc2l0aXZlX2ludF92YWx1ZRgE",
+            "IAEoBBIaChJuZWdhdGl2ZV9pbnRfdmFsdWUYBSABKAMSFAoMZG91YmxlX3Zh",
+            "bHVlGAYgASgBEhQKDHN0cmluZ192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdhdGVf",
+            "dmFsdWUYCCABKAkaMwoITmFtZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJEhQK",
+            "DGlzX2V4dGVuc2lvbhgCIAIoCCLVAQoOU291cmNlQ29kZUluZm8SOgoIbG9j",
+            "YXRpb24YASADKAsyKC5nb29nbGUucHJvdG9idWYuU291cmNlQ29kZUluZm8u",
+            "TG9jYXRpb24ahgEKCExvY2F0aW9uEhAKBHBhdGgYASADKAVCAhABEhAKBHNw",
+            "YW4YAiADKAVCAhABEhgKEGxlYWRpbmdfY29tbWVudHMYAyABKAkSGQoRdHJh",
+            "aWxpbmdfY29tbWVudHMYBCABKAkSIQoZbGVhZGluZ19kZXRhY2hlZF9jb21t",
+            "ZW50cxgGIAMoCSKnAQoRR2VuZXJhdGVkQ29kZUluZm8SQQoKYW5ub3RhdGlv",
+            "bhgBIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5B",
+            "bm5vdGF0aW9uGk8KCkFubm90YXRpb24SEAoEcGF0aBgBIAMoBUICEAESEwoL",
+            "c291cmNlX2ZpbGUYAiABKAkSDQoFYmVnaW4YAyABKAUSCwoDZW5kGAQgASgF",
+            "QowBChNjb20uZ29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9yUHJvdG9zSAFa",
+            "PmdpdGh1Yi5jb20vZ29sYW5nL3Byb3RvYnVmL3Byb3RvYy1nZW4tZ28vZGVz",
+            "Y3JpcHRvcjtkZXNjcmlwdG9yogIDR1BCqgIaR29vZ2xlLlByb3RvYnVmLlJl",
+            "ZmxlY3Rpb24="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto), global::Google.Protobuf.Reflection.FieldDescriptorProto.Parser, new[]{ "Name", "Number", "Label", "Type", "TypeName", "Extendee", "DefaultValue", "OneofIndex", "JsonName", "Options" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type), typeof(global::Google.Protobuf.Reflection.FieldDescriptorProto.Types.Label) }, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofDescriptorProto), global::Google.Protobuf.Reflection.OneofDescriptorProto.Parser, new[]{ "Name", "Options" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumDescriptorProto), global::Google.Protobuf.Reflection.EnumDescriptorProto.Parser, new[]{ "Name", "Value", "Options" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.EnumValueDescriptorProto), global::Google.Protobuf.Reflection.EnumValueDescriptorProto.Parser, new[]{ "Name", "Number", "Options" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ServiceDescriptorProto), global::Google.Protobuf.Reflection.ServiceDescriptorProto.Parser, new[]{ "Name", "Method", "Options" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodDescriptorProto), global::Google.Protobuf.Reflection.MethodDescriptorProto.Parser, new[]{ "Name", "InputType", "OutputType", "Options", "ClientStreaming", "ServerStreaming" }, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "SwiftPrefix", "PhpClassPrefix", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileOptions), global::Google.Protobuf.Reflection.FileOptions.Parser, new[]{ "JavaPackage", "JavaOuterClassname", "JavaMultipleFiles", "JavaGenerateEqualsAndHash", "JavaStringCheckUtf8", "OptimizeFor", "GoPackage", "CcGenericServices", "JavaGenericServices", "PyGenericServices", "PhpGenericServices", "Deprecated", "CcEnableArenas", "ObjcClassPrefix", "CsharpNamespace", "SwiftPrefix", "PhpClassPrefix", "PhpNamespace", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FileOptions.Types.OptimizeMode) }, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MessageOptions), global::Google.Protobuf.Reflection.MessageOptions.Parser, new[]{ "MessageSetWireFormat", "NoStandardDescriptorAccessor", "Deprecated", "MapEntry", "UninterpretedOption" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FieldOptions), global::Google.Protobuf.Reflection.FieldOptions.Parser, new[]{ "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.CType), typeof(global::Google.Protobuf.Reflection.FieldOptions.Types.JSType) }, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.OneofOptions), global::Google.Protobuf.Reflection.OneofOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null),
@@ -1051,6 +1057,7 @@
         public ExtensionRange(ExtensionRange other) : this() {
           start_ = other.start_;
           end_ = other.end_;
+          Options = other.options_ != null ? other.Options.Clone() : null;
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1080,6 +1087,17 @@
           }
         }
 
+        /// <summary>Field number for the "options" field.</summary>
+        public const int OptionsFieldNumber = 3;
+        private global::Google.Protobuf.Reflection.ExtensionRangeOptions options_;
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        public global::Google.Protobuf.Reflection.ExtensionRangeOptions Options {
+          get { return options_; }
+          set {
+            options_ = value;
+          }
+        }
+
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         public override bool Equals(object other) {
           return Equals(other as ExtensionRange);
@@ -1095,6 +1113,7 @@
           }
           if (Start != other.Start) return false;
           if (End != other.End) return false;
+          if (!object.Equals(Options, other.Options)) return false;
           return true;
         }
 
@@ -1103,6 +1122,7 @@
           int hash = 1;
           if (Start != 0) hash ^= Start.GetHashCode();
           if (End != 0) hash ^= End.GetHashCode();
+          if (options_ != null) hash ^= Options.GetHashCode();
           return hash;
         }
 
@@ -1121,6 +1141,10 @@
             output.WriteRawTag(16);
             output.WriteInt32(End);
           }
+          if (options_ != null) {
+            output.WriteRawTag(26);
+            output.WriteMessage(Options);
+          }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1132,6 +1156,9 @@
           if (End != 0) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
+          if (options_ != null) {
+            size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
+          }
           return size;
         }
 
@@ -1146,6 +1173,12 @@
           if (other.End != 0) {
             End = other.End;
           }
+          if (other.options_ != null) {
+            if (options_ == null) {
+              options_ = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
+            }
+            Options.MergeFrom(other.Options);
+          }
         }
 
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1164,6 +1197,13 @@
                 End = input.ReadInt32();
                 break;
               }
+              case 26: {
+                if (options_ == null) {
+                  options_ = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
+                }
+                input.ReadMessage(options_);
+                break;
+              }
             }
           }
         }
@@ -1331,6 +1371,118 @@
 
   }
 
+  internal sealed partial class ExtensionRangeOptions : pb::IMessage<ExtensionRangeOptions> {
+    private static readonly pb::MessageParser<ExtensionRangeOptions> _parser = new pb::MessageParser<ExtensionRangeOptions>(() => new ExtensionRangeOptions());
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static pb::MessageParser<ExtensionRangeOptions> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[3]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public ExtensionRangeOptions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public ExtensionRangeOptions(ExtensionRangeOptions other) : this() {
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public ExtensionRangeOptions Clone() {
+      return new ExtensionRangeOptions(this);
+    }
+
+    /// <summary>Field number for the "uninterpreted_option" field.</summary>
+    public const int UninterpretedOptionFieldNumber = 999;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
+        = pb::FieldCodec.ForMessage(7994, global::Google.Protobuf.Reflection.UninterpretedOption.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> uninterpretedOption_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption>();
+    /// <summary>
+    /// The parser stores options it doesn't recognize here. See above.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.UninterpretedOption> UninterpretedOption {
+      get { return uninterpretedOption_; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override bool Equals(object other) {
+      return Equals(other as ExtensionRangeOptions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool Equals(ExtensionRangeOptions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
+      return true;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override int GetHashCode() {
+      int hash = 1;
+      hash ^= uninterpretedOption_.GetHashCode();
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void WriteTo(pb::CodedOutputStream output) {
+      uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public int CalculateSize() {
+      int size = 0;
+      size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void MergeFrom(ExtensionRangeOptions other) {
+      if (other == null) {
+        return;
+      }
+      uninterpretedOption_.Add(other.uninterpretedOption_);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void MergeFrom(pb::CodedInputStream input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            input.SkipLastField();
+            break;
+          case 7994: {
+            uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
+            break;
+          }
+        }
+      }
+    }
+
+  }
+
   /// <summary>
   /// Describes a field within a message.
   /// </summary>
@@ -1341,7 +1493,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[3]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[4]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1818,7 +1970,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[4]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[5]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1972,7 +2124,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[5]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[6]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2146,7 +2298,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[6]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[7]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2328,7 +2480,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[7]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[8]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2502,7 +2654,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[8]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[9]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2775,7 +2927,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[9]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[10]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2804,12 +2956,14 @@
       ccGenericServices_ = other.ccGenericServices_;
       javaGenericServices_ = other.javaGenericServices_;
       pyGenericServices_ = other.pyGenericServices_;
+      phpGenericServices_ = other.phpGenericServices_;
       deprecated_ = other.deprecated_;
       ccEnableArenas_ = other.ccEnableArenas_;
       objcClassPrefix_ = other.objcClassPrefix_;
       csharpNamespace_ = other.csharpNamespace_;
       swiftPrefix_ = other.swiftPrefix_;
       phpClassPrefix_ = other.phpClassPrefix_;
+      phpNamespace_ = other.phpNamespace_;
       uninterpretedOption_ = other.uninterpretedOption_.Clone();
     }
 
@@ -2980,6 +3134,17 @@
       }
     }
 
+    /// <summary>Field number for the "php_generic_services" field.</summary>
+    public const int PhpGenericServicesFieldNumber = 19;
+    private bool phpGenericServices_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool PhpGenericServices {
+      get { return phpGenericServices_; }
+      set {
+        phpGenericServices_ = value;
+      }
+    }
+
     /// <summary>Field number for the "deprecated" field.</summary>
     public const int DeprecatedFieldNumber = 23;
     private bool deprecated_;
@@ -3073,6 +3238,22 @@
       }
     }
 
+    /// <summary>Field number for the "php_namespace" field.</summary>
+    public const int PhpNamespaceFieldNumber = 41;
+    private string phpNamespace_ = "";
+    /// <summary>
+    /// Use this option to change the namespace of php generated classes. Default
+    /// is empty. When this option is empty, the package name will be used for
+    /// determining the namespace.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public string PhpNamespace {
+      get { return phpNamespace_; }
+      set {
+        phpNamespace_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+
     /// <summary>Field number for the "uninterpreted_option" field.</summary>
     public const int UninterpretedOptionFieldNumber = 999;
     private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.UninterpretedOption> _repeated_uninterpretedOption_codec
@@ -3109,12 +3290,14 @@
       if (CcGenericServices != other.CcGenericServices) return false;
       if (JavaGenericServices != other.JavaGenericServices) return false;
       if (PyGenericServices != other.PyGenericServices) return false;
+      if (PhpGenericServices != other.PhpGenericServices) return false;
       if (Deprecated != other.Deprecated) return false;
       if (CcEnableArenas != other.CcEnableArenas) return false;
       if (ObjcClassPrefix != other.ObjcClassPrefix) return false;
       if (CsharpNamespace != other.CsharpNamespace) return false;
       if (SwiftPrefix != other.SwiftPrefix) return false;
       if (PhpClassPrefix != other.PhpClassPrefix) return false;
+      if (PhpNamespace != other.PhpNamespace) return false;
       if(!uninterpretedOption_.Equals(other.uninterpretedOption_)) return false;
       return true;
     }
@@ -3132,12 +3315,14 @@
       if (CcGenericServices != false) hash ^= CcGenericServices.GetHashCode();
       if (JavaGenericServices != false) hash ^= JavaGenericServices.GetHashCode();
       if (PyGenericServices != false) hash ^= PyGenericServices.GetHashCode();
+      if (PhpGenericServices != false) hash ^= PhpGenericServices.GetHashCode();
       if (Deprecated != false) hash ^= Deprecated.GetHashCode();
       if (CcEnableArenas != false) hash ^= CcEnableArenas.GetHashCode();
       if (ObjcClassPrefix.Length != 0) hash ^= ObjcClassPrefix.GetHashCode();
       if (CsharpNamespace.Length != 0) hash ^= CsharpNamespace.GetHashCode();
       if (SwiftPrefix.Length != 0) hash ^= SwiftPrefix.GetHashCode();
       if (PhpClassPrefix.Length != 0) hash ^= PhpClassPrefix.GetHashCode();
+      if (PhpNamespace.Length != 0) hash ^= PhpNamespace.GetHashCode();
       hash ^= uninterpretedOption_.GetHashCode();
       return hash;
     }
@@ -3181,6 +3366,10 @@
         output.WriteRawTag(144, 1);
         output.WriteBool(PyGenericServices);
       }
+      if (PhpGenericServices != false) {
+        output.WriteRawTag(152, 1);
+        output.WriteBool(PhpGenericServices);
+      }
       if (JavaGenerateEqualsAndHash != false) {
         output.WriteRawTag(160, 1);
         output.WriteBool(JavaGenerateEqualsAndHash);
@@ -3213,6 +3402,10 @@
         output.WriteRawTag(194, 2);
         output.WriteString(PhpClassPrefix);
       }
+      if (PhpNamespace.Length != 0) {
+        output.WriteRawTag(202, 2);
+        output.WriteString(PhpNamespace);
+      }
       uninterpretedOption_.WriteTo(output, _repeated_uninterpretedOption_codec);
     }
 
@@ -3249,6 +3442,9 @@
       if (PyGenericServices != false) {
         size += 2 + 1;
       }
+      if (PhpGenericServices != false) {
+        size += 2 + 1;
+      }
       if (Deprecated != false) {
         size += 2 + 1;
       }
@@ -3267,6 +3463,9 @@
       if (PhpClassPrefix.Length != 0) {
         size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpClassPrefix);
       }
+      if (PhpNamespace.Length != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeStringSize(PhpNamespace);
+      }
       size += uninterpretedOption_.CalculateSize(_repeated_uninterpretedOption_codec);
       return size;
     }
@@ -3306,6 +3505,9 @@
       if (other.PyGenericServices != false) {
         PyGenericServices = other.PyGenericServices;
       }
+      if (other.PhpGenericServices != false) {
+        PhpGenericServices = other.PhpGenericServices;
+      }
       if (other.Deprecated != false) {
         Deprecated = other.Deprecated;
       }
@@ -3324,6 +3526,9 @@
       if (other.PhpClassPrefix.Length != 0) {
         PhpClassPrefix = other.PhpClassPrefix;
       }
+      if (other.PhpNamespace.Length != 0) {
+        PhpNamespace = other.PhpNamespace;
+      }
       uninterpretedOption_.Add(other.uninterpretedOption_);
     }
 
@@ -3367,6 +3572,10 @@
             PyGenericServices = input.ReadBool();
             break;
           }
+          case 152: {
+            PhpGenericServices = input.ReadBool();
+            break;
+          }
           case 160: {
             JavaGenerateEqualsAndHash = input.ReadBool();
             break;
@@ -3399,6 +3608,10 @@
             PhpClassPrefix = input.ReadString();
             break;
           }
+          case 330: {
+            PhpNamespace = input.ReadString();
+            break;
+          }
           case 7994: {
             uninterpretedOption_.AddEntriesFrom(input, _repeated_uninterpretedOption_codec);
             break;
@@ -3441,7 +3654,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[10]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[11]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3721,7 +3934,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[11]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[12]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3795,13 +4008,15 @@
     /// <summary>
     /// The jstype option determines the JavaScript type used for values of the
     /// field.  The option is permitted only for 64 bit integral and fixed types
-    /// (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
-    /// represented as JavaScript strings.  This avoids loss of precision that can
-    /// happen when a large value is converted to a floating point JavaScript
-    /// numbers.  Specifying JS_NUMBER for the jstype causes the generated
-    /// JavaScript code to use the JavaScript "number" type instead of strings.
-    /// This option is an enum to permit additional types to be added,
-    /// e.g. goog.math.Integer.
+    /// (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+    /// is represented as JavaScript string, which avoids loss of precision that
+    /// can happen when a large value is converted to a floating point JavaScript.
+    /// Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+    /// use the JavaScript "number" type.  The behavior of the default option
+    /// JS_NORMAL is implementation dependent.
+    ///
+    /// This option is an enum to permit additional types to be added, e.g.
+    /// goog.math.Integer.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public global::Google.Protobuf.Reflection.FieldOptions.Types.JSType Jstype {
@@ -4096,7 +4311,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[12]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[13]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4210,7 +4425,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[13]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[14]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4390,7 +4605,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[14]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[15]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4538,7 +4753,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[15]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[16]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4686,7 +4901,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[16]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[17]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4894,7 +5109,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[17]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[18]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -5338,7 +5553,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[18]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[19]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -5792,7 +6007,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pbr::MessageDescriptor Descriptor {
-      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[19]; }
+      get { return global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor.MessageTypes[20]; }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
index b90c9a2..5b39b80 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
@@ -73,6 +73,16 @@
   ///       any.Unpack(foo)
   ///       ...
   ///
+  ///  Example 4: Pack and unpack a message in Go
+  ///
+  ///      foo := &amp;pb.Foo{...}
+  ///      any, err := ptypes.MarshalAny(foo)
+  ///      ...
+  ///      foo := &amp;pb.Foo{}
+  ///      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+  ///        ...
+  ///      }
+  ///
   /// The pack methods provided by protobuf library will by default use
   /// 'type.googleapis.com/full.type.name' as the type URL and the unpack
   /// methods only use the fully qualified type name after the last '/'
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
index f4fac73..fca689d 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
@@ -44,17 +44,25 @@
             prefix.EndsWith("/") ? prefix + descriptor.FullName : prefix + "/" + descriptor.FullName;
 
         /// <summary>
-        /// Retrieves the type name for a type URL. This is always just the last part of the URL,
-        /// after the trailing slash. No validation of anything before the trailing slash is performed.
-        /// If the type URL does not include a slash, an empty string is returned rather than an exception
-        /// being thrown; this won't match any types, and the calling code is probably in a better position
-        /// to give a meaningful error.
-        /// There is no handling of fragments or queries  at the moment.
+        /// Retrieves the type name for a type URL, matching the <see cref="DescriptorBase.FullName"/>
+        /// of the packed message type.
         /// </summary>
+        /// <remarks>
+        /// <para>
+        /// This is always just the last part of the URL, after the final slash. No validation of 
+        /// anything before the trailing slash is performed. If the type URL does not include a slash,
+        /// an empty string is returned rather than an exception being thrown; this won't match any types,
+        /// and the calling code is probably in a better position to give a meaningful error.
+        /// </para>
+        /// <para>
+        /// There is no handling of fragments or queries  at the moment.
+        /// </para>
+        /// </remarks>
         /// <param name="typeUrl">The URL to extract the type name from</param>
         /// <returns>The type name</returns>
-        internal static string GetTypeName(string typeUrl)
+        public static string GetTypeName(string typeUrl)
         {
+            ProtoPreconditions.CheckNotNull(typeUrl, nameof(typeUrl));
             int lastSlash = typeUrl.LastIndexOf('/');
             return lastSlash == -1 ? "" : typeUrl.Substring(lastSlash + 1);
         }
@@ -81,6 +89,27 @@
         }
 
         /// <summary>
+        /// Attempts to unpack the content of this Any message into the target message type,
+        /// if it matches the type URL within this Any message.
+        /// </summary>
+        /// <typeparam name="T">The type of message to attempt to unpack the content into.</typeparam>
+        /// <returns><c>true</c> if the message was successfully unpacked; <c>false</c> if the type name didn't match</returns>
+        public bool TryUnpack<T>(out T result) where T : IMessage, new()
+        {
+            // Note: deliberately avoid writing anything to result until the end, in case it's being
+            // monitored by other threads. (That would be a bug in the calling code, but let's not make it worse.)
+            T target = new T();
+            if (GetTypeName(TypeUrl) != target.Descriptor.FullName)
+            {
+                result = default(T); // Can't use null as there's no class constraint, but this always *will* be null in real usage.
+                return false;
+            }
+            target.MergeFrom(Value);
+            result = target;
+            return true;
+        }
+
+        /// <summary>
         /// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com".
         /// </summary>
         /// <param name="message">The message to pack.</param>
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
index aeeb8e7..6705e09 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
@@ -52,7 +52,15 @@
   }
   #region Messages
   /// <summary>
-  /// Api is a light-weight descriptor for a protocol buffer service.
+  /// Api is a light-weight descriptor for an API Interface.
+  ///
+  /// Interfaces are also described as "protocol buffer services" in some contexts,
+  /// such as by the "service" keyword in a .proto file, but they are different
+  /// from API Services, which represent a concrete implementation of an interface
+  /// as opposed to simply a description of methods and bindings. They are also
+  /// sometimes simply referred to as "APIs" in other contexts, such as the name of
+  /// this message itself. See https://cloud.google.com/apis/design/glossary for
+  /// detailed terminology.
   /// </summary>
   public sealed partial class Api : pb::IMessage<Api> {
     private static readonly pb::MessageParser<Api> _parser = new pb::MessageParser<Api>(() => new Api());
@@ -96,8 +104,8 @@
     public const int NameFieldNumber = 1;
     private string name_ = "";
     /// <summary>
-    /// The fully qualified name of this api, including package name
-    /// followed by the api's simple name.
+    /// The fully qualified name of this interface, including package name
+    /// followed by the interface's simple name.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
@@ -113,7 +121,7 @@
         = pb::FieldCodec.ForMessage(18, global::Google.Protobuf.WellKnownTypes.Method.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method> methods_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method>();
     /// <summary>
-    /// The methods of this api, in unspecified order.
+    /// The methods of this interface, in unspecified order.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Method> Methods {
@@ -126,7 +134,7 @@
         = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.Option.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> options_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option>();
     /// <summary>
-    /// Any metadata attached to the API.
+    /// Any metadata attached to the interface.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Option> Options {
@@ -137,13 +145,12 @@
     public const int VersionFieldNumber = 4;
     private string version_ = "";
     /// <summary>
-    /// A version string for this api. If specified, must have the form
-    /// `major-version.minor-version`, as in `1.10`. If the minor version
-    /// is omitted, it defaults to zero. If the entire version field is
-    /// empty, the major version is derived from the package name, as
-    /// outlined below. If the field is not empty, the version in the
-    /// package name will be verified to be consistent with what is
-    /// provided here.
+    /// A version string for this interface. If specified, must have the form
+    /// `major-version.minor-version`, as in `1.10`. If the minor version is
+    /// omitted, it defaults to zero. If the entire version field is empty, the
+    /// major version is derived from the package name, as outlined below. If the
+    /// field is not empty, the version in the package name will be verified to be
+    /// consistent with what is provided here.
     ///
     /// The versioning schema uses [semantic
     /// versioning](http://semver.org) where the major version number
@@ -153,10 +160,10 @@
     /// chosen based on the product plan.
     ///
     /// The major version is also reflected in the package name of the
-    /// API, which must end in `v&lt;major-version>`, as in
+    /// interface, which must end in `v&lt;major-version>`, as in
     /// `google.feature.v1`. For major versions 0 and 1, the suffix can
     /// be omitted. Zero major versions must only be used for
-    /// experimental, none-GA apis.
+    /// experimental, non-GA interfaces.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Version {
@@ -187,7 +194,7 @@
         = pb::FieldCodec.ForMessage(50, global::Google.Protobuf.WellKnownTypes.Mixin.Parser);
     private readonly pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> mixins_ = new pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin>();
     /// <summary>
-    /// Included APIs. See [Mixin][].
+    /// Included interfaces. See [Mixin][].
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public pbc::RepeatedField<global::Google.Protobuf.WellKnownTypes.Mixin> Mixins {
@@ -364,7 +371,7 @@
   }
 
   /// <summary>
-  /// Method represents a method of an api.
+  /// Method represents a method of an API interface.
   /// </summary>
   public sealed partial class Method : pb::IMessage<Method> {
     private static readonly pb::MessageParser<Method> _parser = new pb::MessageParser<Method>(() => new Method());
@@ -665,9 +672,9 @@
   }
 
   /// <summary>
-  /// Declares an API to be included in this API. The including API must
-  /// redeclare all the methods from the included API, but documentation
-  /// and options are inherited as follows:
+  /// Declares an API Interface to be included in this interface. The including
+  /// interface must redeclare all the methods from the included interface, but
+  /// documentation and options are inherited as follows:
   ///
   /// - If after comment and whitespace stripping, the documentation
   ///   string of the redeclared method is empty, it will be inherited
@@ -679,7 +686,8 @@
   ///
   /// - If an http annotation is inherited, the path pattern will be
   ///   modified as follows. Any version prefix will be replaced by the
-  ///   version of the including API plus the [root][] path if specified.
+  ///   version of the including interface plus the [root][] path if
+  ///   specified.
   ///
   /// Example of a simple mixin:
   ///
@@ -780,7 +788,7 @@
     public const int NameFieldNumber = 1;
     private string name_ = "";
     /// <summary>
-    /// The fully qualified name of the API which is included.
+    /// The fully qualified name of the interface which is included.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string Name {
diff --git a/docs/third_party.md b/docs/third_party.md
index 3def003..5d2695d 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -32,6 +32,7 @@
 * Delphi: http://sourceforge.net/projects/protobuf-delphi/
 * Delphi: http://fundementals.sourceforge.net/dl.html
 * Elixir: https://github.com/jeremyong/exprotoc
+* Elixir: https://github.com/tony612/protobuf-elixir
 * Elm: https://github.com/tiziano88/elm-protobuf
 * Erlang: http://github.com/ngerakines/erlang_protobuffs/tree/master
 * Erlang: http://piqi.org/
@@ -116,6 +117,8 @@
 * https://github.com/thesamet/rpcz (C++/Python, based on ZeroMQ)
 * https://github.com/w359405949/libmaid (C++, Python)
 * https://github.com/madwyn/libpbrpc (C++)
+* https://github.com/SeriousMa/grpc-protobuf-validation (Java)
+* https://github.com/tony612/grpc-elixir (Elixir)
 
 ## Other Utilities
 
@@ -140,7 +143,7 @@
     * http://igor-petruk.github.com/protobuf-maven-plugin/
     * http://code.google.com/p/maven-protoc-plugin/
     * https://github.com/os72/protoc-jar-maven-plugin
-* [Documentation generator plugin (Markdown/HTML/DocBook/...)](https://github.com/estan/protoc-gen-doc)
+* [Documentation generator plugin (Markdown/HTML/DocBook/...)](https://github.com/pseudomuto/protoc-gen-doc)
 * [DocBook generator for .proto files](http://code.google.com/p/protoc-gen-docbook/)
 * [Protobuf for nginx module](https://github.com/dbcode/protobuf-nginx/)
 * [RSpec matchers and Cucumber step defs for testing Protocol Buffers](https://github.com/connamara/protobuf_spec)
@@ -155,3 +158,4 @@
 * [Linter for .proto files](https://github.com/ckaznocha/protoc-gen-lint)
 * [Protocol Buffers Dynamic Schema - create protobuf schemas programmatically (Java)] (https://github.com/os72/protobuf-dynamic)
 * [Make protoc plugins in NodeJS](https://github.com/konsumer/node-protoc-plugin)
+* [ProfaneDB - A Protocol Buffers database](https://profanedb.gitlab.io)
diff --git a/examples/BUILD b/examples/BUILD
new file mode 100644
index 0000000..d5d5d9a
--- /dev/null
+++ b/examples/BUILD
@@ -0,0 +1,101 @@
+# This BUILD file shows how to use protobuf with bazel. Before you can use
+# proto_library/<lang>_proto_library rules in a BUILD file, you need to
+# include protobuf repo as remote repositories in your WORKSPACE file. See
+# the WORKSPACE file in the same directory with this BUILD file for an
+# example.
+
+# For each .proto file, a proto_library target should be defined. This target
+# is not bound to any particular language. Instead, it defines the dependency
+# graph of the .proto files (i.e., proto imports) and serves as the provider
+# of .proto source files to the protocol compiler.
+#
+# Remote repository "com_google_protobuf" must be defined to use this rule.
+proto_library(
+    name = "addressbook_proto",
+    srcs = ["addressbook.proto"],
+    deps = ["@com_google_protobuf//:timestamp_proto"],
+)
+
+# The cc_proto_library rule generates C++ code for a proto_library rule. It
+# must have exactly one proto_library dependency. If you want to use multiple
+# proto_library targets, create a separate cc_proto_library target for each
+# of them.
+#
+# Remote repository "com_google_protobuf_cc" must be defined to use this rule.
+cc_proto_library(
+    name = "addressbook_cc_proto",
+    deps = [":addressbook_proto"],
+)
+
+# cc_library/cc_binary targets can depend on cc_proto_library targets.
+cc_binary(
+    name = "add_person_cpp",
+    srcs = ["add_person.cc"],
+    deps = [":addressbook_cc_proto"],
+)
+
+cc_binary(
+    name = "list_people_cpp",
+    srcs = ["list_people.cc"],
+    deps = [":addressbook_cc_proto"],
+)
+
+# Similar to cc_proto_library but for Java.
+#
+# Remote repository "com_google_protobuf_java" must be defined to use this rule.
+java_proto_library(
+    name = "addressbook_java_proto",
+    deps = [":addressbook_proto"],
+)
+
+java_binary(
+    name = "add_person_java",
+    srcs = ["AddPerson.java"],
+    main_class = "AddPerson",
+    deps = [":addressbook_java_proto"],
+)
+
+java_binary(
+    name = "list_people_java",
+    srcs = ["ListPeople.java"],
+    main_class = "ListPeople",
+    deps = [":addressbook_java_proto"],
+)
+
+# Java lite.
+#
+# Remote repository "com_google_protobuf_javalite" must be defined to use this
+# rule.
+java_lite_proto_library(
+    name = "addressbook_java_lite_proto",
+    deps = [":addressbook_proto"],
+)
+
+# Java lite API is a subset of the regular Java API so if you only uses this
+# subset in your code, you can actually compile your code against both (i.e.,
+# share code between server build and Android build).
+#
+# The lite version has a smaller code size, and you can see that by comparing
+# the resulted .jar file:
+#
+#   $ bazel build :add_person_java_deploy.jar :add_person_java_lite_deploy.jar
+#   $ ls -l bazel-bin/*_deploy.jar
+#   -r-xr-xr-x 1 xiaofeng eng 1230797 Sep  8 12:24 bazel-bin/add_person_java_deploy.jar
+#   -r-xr-xr-x 1 xiaofeng eng  236166 Sep  8 12:24 bazel-bin/add_person_java_lite_deploy.jar
+#
+# In the above example, the lite .jar file is 6 times smaller. With proper
+# proguard inlining/stripping, the difference can be much more larger than
+# that.
+java_binary(
+    name = "add_person_java_lite",
+    srcs = ["AddPerson.java"],
+    main_class = "AddPerson",
+    deps = [":addressbook_java_lite_proto"],
+)
+
+java_binary(
+    name = "list_people_java_lite",
+    srcs = ["ListPeople.java"],
+    main_class = "ListPeople",
+    deps = [":addressbook_java_lite_proto"],
+)
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 2cd2acc..3e8e654 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -32,22 +32,6 @@
   if(protobuf_MODULE_COMPATIBLE) #Legacy Support
     protobuf_generate_cpp(${example}_PROTO_SRCS ${example}_PROTO_HDRS ${${example}_PROTOS})
     list(APPEND ${example}_SRCS ${${example}_PROTO_SRCS} ${${example}_PROTO_HDRS})
-  else()
-
-    foreach(proto_file ${${example}_PROTOS})
-      get_filename_component(proto_file_abs ${proto_file} ABSOLUTE)
-      get_filename_component(basename ${proto_file} NAME_WE)
-      set(generated_files ${basename}.pb.cc ${basename}.pb.h)
-      list(APPEND ${example}_SRCS ${generated_files})
-
-      add_custom_command(
-        OUTPUT ${generated_files}
-        COMMAND protobuf::protoc
-        ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} -I ${CMAKE_CURRENT_SOURCE_DIR} ${proto_file_abs}
-        COMMENT "Generating ${generated_files} from ${proto_file}"
-        VERBATIM
-      )
-    endforeach()
   endif()
 
   #Executable setup
@@ -58,6 +42,7 @@
     target_link_libraries(${executable_name} ${PROTOBUF_LIBRARIES})
   else()
     target_link_libraries(${executable_name} protobuf::libprotobuf)
+    protobuf_generate(TARGET ${executable_name})
   endif()
 
 endforeach()
diff --git a/examples/ListPeople.java b/examples/ListPeople.java
index 7892430..580f7ac 100644
--- a/examples/ListPeople.java
+++ b/examples/ListPeople.java
@@ -27,6 +27,9 @@
           case WORK:
             System.out.print("  Work phone #: ");
             break;
+          default:
+            System.out.println(" Unknown phone #: ");
+            break;
         }
         System.out.println(phoneNumber.getNumber());
       }
diff --git a/examples/Makefile b/examples/Makefile
index 51f1342..3b61790 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -51,7 +51,7 @@
 	go test list_people.go list_people_test.go
 
 javac_middleman: AddPerson.java ListPeople.java protoc_middleman
-	javac AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
+	javac -cp $$CLASSPATH AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
 	@touch javac_middleman
 
 add_person_java: javac_middleman
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..20f285c
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,124 @@
+# Protocol Buffers - Code Example
+
+This directory contains example code that uses Protocol Buffers to manage an
+address book. Two programs are provided for each supported language. The
+add_person example adds a new person to an address book, prompting the user to
+input the person's information. The list_people example lists people already in
+the address book. The examples use the exact same format in all three languages,
+so you can, for example, use add_person_java to create an address book and then
+use list_people_python to read it.
+
+These examples are part of the Protocol Buffers tutorial, located at:
+  https://developers.google.com/protocol-buffers/docs/tutorials
+
+## Build the example using bazel
+
+The example requires bazel 0.5.4 or newer to build. You can download/install
+the latest version of bazel from bazel's release page:
+
+    https://github.com/bazelbuild/bazel/releases
+
+Once you have bazel installed, simply run the following command in this examples
+directory to build the code:
+
+    $ bazel build :all
+
+Then you can run the built binary:
+
+    $ bazel-bin/add_person_cpp addressbook.data
+
+To use protobuf in your own bazel project, please follow instructions in the
+[BUILD](BUILD) file and [WORKSPACE](WORKSPACE) file.
+
+## Build the example using make
+
+You must install the protobuf package before you can build it using make. The
+minimum requirement is to install protocol compiler (i.e., the protoc binary)
+and the protobuf runtime for the language you want to build.
+
+You can simply run "make" to build the example for all languages (except for
+Go). However, since different language has different installation requirement,
+it will likely fail. It's better to follow individual instrutions below to
+build only the language you are interested in.
+
+### C++
+
+You can follow instructions in [../src/README.md](../src/README.md) to install
+protoc and protobuf C++ runtime from source.
+
+Then run "make cpp" in this examples directory to build the C++ example. It
+will create two executables: add_person_cpp and list_people_cpp. These programs
+simply take an address book file as their parameter. The add_person_cpp
+programs will create the file if it doesn't already exist.
+
+To run the examples:
+
+    $ ./add_person_cpp addressbook.data
+    $ ./list_people_cpp addressbook.data
+
+Note that on some platforms you may have to edit the Makefile and remove
+"-lpthread" from the linker commands (perhaps replacing it with something else).
+We didn't do this automatically because we wanted to keep the example simple.
+
+### Python
+
+Follow instructions in [../README.md](../README.md) to install protoc and then
+follow [../python/README.md](../python/README.md) to install protobuf python
+runtime from source. You can also install python runtime using pip:
+
+    $ pip install protobuf
+
+Make sure the runtime version is the same as protoc binary, or it may not work.
+
+After you have install both protoc and python runtime, run "make python" to
+build two executables (shell scripts actually): add_person_python and
+list_people_python. They work the same way as the C++ executables.
+
+### Java
+
+Follow instructions in [../README.md](../README.md) to install protoc and then
+download protobuf Java runtime .jar file from maven:
+
+    https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java
+
+Then run the following:
+
+    $ export CLASSPATH=/path/to/protobuf-java-[version].jar
+    $ make java
+
+This will create the add_person_java/list_people_java executables (shell
+scripts) and can be used to create/display an address book data file.
+
+### Go
+
+The Go example requires a plugin to the protocol buffer compiler, so it is not
+build with all the other examples.  See:
+
+    https://github.com/golang/protobuf
+
+for more information about Go protocol buffer support.
+
+First, install the Protocol Buffers compiler (protoc).
+
+Then, install the Go Protocol Buffers plugin ($GOPATH/bin must be in your $PATH
+for protoc to find it):
+
+    go get github.com/golang/protobuf/protoc-gen-go
+
+Build the Go samples in this directory with "make go".  This creates the
+following executable files in the current directory:
+
+    add_person_go      list_people_go
+
+To run the example:
+
+    ./add_person_go addressbook.data
+
+to add a person to the protocol buffer encoded file addressbook.data.  The file
+is created if it does not exist.  To view the data, run:
+
+    ./list_people_go addressbook.data
+
+Observe that the C++, Python, and Java examples in this directory run in a
+similar way and can view/modify files created by the Go example and vice
+versa.
diff --git a/examples/README.txt b/examples/README.txt
deleted file mode 100644
index b33f841..0000000
--- a/examples/README.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-This directory contains example code that uses Protocol Buffers to manage an
-address book.  Two programs are provided, each with three different
-implementations, one written in each of C++, Java, and Python.  The add_person
-example adds a new person to an address book, prompting the user to input
-the person's information.  The list_people example lists people already in the
-address book.  The examples use the exact same format in all three languages,
-so you can, for example, use add_person_java to create an address book and then
-use list_people_python to read it.
-
-You must install the protobuf package before you can build these.
-
-To build all the examples (on a unix-like system), simply run "make".  This
-creates the following executable files in the current directory:
-  add_person_cpp     list_people_cpp
-  add_person_java    list_people_java
-  add_person_python  list_people_python
-
-If you only want to compile examples in one language, use "make cpp"*,
-"make java", or "make python".
-
-All of these programs simply take an address book file as their parameter.
-The add_person programs will create the file if it doesn't already exist.
-
-These examples are part of the Protocol Buffers tutorial, located at:
-  https://developers.google.com/protocol-buffers/docs/tutorials
-
-* Note that on some platforms you may have to edit the Makefile and remove
-"-lpthread" from the linker commands (perhaps replacing it with something else).
-We didn't do this automatically because we wanted to keep the example simple.
-
-## Go ##
-
-The Go example requires a plugin to the protocol buffer compiler, so it is not
-build with all the other examples.  See:
-  https://github.com/golang/protobuf
-for more information about Go protocol buffer support.
-
-First, install the Protocol Buffers compiler (protoc).
-Then, install the Go Protocol Buffers plugin
-($GOPATH/bin must be in your $PATH for protoc to find it):
-  go get github.com/golang/protobuf/protoc-gen-go
-
-Build the Go samples in this directory with "make go".  This creates the
-following executable files in the current directory:
-  add_person_go      list_people_go
-To run the example:
-  ./add_person_go addressbook.data
-to add a person to the protocol buffer encoded file addressbook.data.  The file
-is created if it does not exist.  To view the data, run:
-  ./list_people_go addressbook.data
-
-Observe that the C++, Python, and Java examples in this directory run in a
-similar way and can view/modify files created by the Go example and vice
-versa.
diff --git a/examples/WORKSPACE b/examples/WORKSPACE
new file mode 100644
index 0000000..bb00310
--- /dev/null
+++ b/examples/WORKSPACE
@@ -0,0 +1,33 @@
+# This com_google_protobuf repository is required for proto_library rule.
+# It provides the protocol compiler binary (i.e., protoc).
+http_archive(
+    name = "com_google_protobuf",
+    strip_prefix = "protobuf-master",
+    urls = ["https://github.com/google/protobuf/archive/master.zip"],
+)
+
+# This com_google_protobuf_cc repository is required for cc_proto_library
+# rule. It provides protobuf C++ runtime. Note that it actually is the same
+# repo as com_google_protobuf but has to be given a different name as
+# required by bazel.
+http_archive(
+    name = "com_google_protobuf_cc",
+    strip_prefix = "protobuf-master",
+    urls = ["https://github.com/google/protobuf/archive/master.zip"],
+)
+
+# Similar to com_google_protobuf_cc but for Java (i.e., java_proto_library).
+http_archive(
+    name = "com_google_protobuf_java",
+    strip_prefix = "protobuf-master",
+    urls = ["https://github.com/google/protobuf/archive/master.zip"],
+)
+
+# Similar to com_google_protobuf_cc but for Java lite. If you are building
+# for Android, the lite version should be prefered because it has a much
+# smaller code size.
+http_archive(
+    name = "com_google_protobuf_javalite",
+    strip_prefix = "protobuf-javalite",
+    urls = ["https://github.com/google/protobuf/archive/javalite.zip"],
+)
diff --git a/examples/add_person.cc b/examples/add_person.cc
index 9bec4b3..856e90b 100644
--- a/examples/add_person.cc
+++ b/examples/add_person.cc
@@ -1,11 +1,17 @@
 // See README.txt for information and build instructions.
 
-#include <iostream>
+#include <ctime>
 #include <fstream>
+#include <google/protobuf/util/time_util.h>
+#include <iostream>
 #include <string>
+
 #include "addressbook.pb.h"
+
 using namespace std;
 
+using google::protobuf::util::TimeUtil;
+
 // This function fills in a Person message based on user input.
 void PromptForAddress(tutorial::Person* person) {
   cout << "Enter person ID number: ";
@@ -48,6 +54,7 @@
       cout << "Unknown phone type.  Using default." << endl;
     }
   }
+  *person->mutable_last_updated() = TimeUtil::SecondsToTimestamp(time(NULL));
 }
 
 // Main function:  Reads the entire address book from a file,
diff --git a/examples/add_person.py b/examples/add_person.py
index 0b69857..aa0fbca 100755
--- a/examples/add_person.py
+++ b/examples/add_person.py
@@ -5,6 +5,12 @@
 import addressbook_pb2
 import sys
 
+try:
+  raw_input          # Python 2
+except NameError:
+  raw_input = input  # Python 3
+
+
 # This function fills in a Person message based on user input.
 def PromptForAddress(person):
   person.id = int(raw_input("Enter person ID number: "))
@@ -30,13 +36,14 @@
     elif type == "work":
       phone_number.type = addressbook_pb2.Person.WORK
     else:
-      print "Unknown phone type; leaving as default value."
+      print("Unknown phone type; leaving as default value.")
+
 
 # Main procedure:  Reads the entire address book from a file,
 #   adds one person based on user input, then writes it back out to the same
 #   file.
 if len(sys.argv) != 2:
-  print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
+  print("Usage:", sys.argv[0], "ADDRESS_BOOK_FILE")
   sys.exit(-1)
 
 address_book = addressbook_pb2.AddressBook()
@@ -46,7 +53,7 @@
   with open(sys.argv[1], "rb") as f:
     address_book.ParseFromString(f.read())
 except IOError:
-  print sys.argv[1] + ": File not found.  Creating a new file."
+  print(sys.argv[1] + ": File not found.  Creating a new file.")
 
 # Add an address.
 PromptForAddress(address_book.people.add())
diff --git a/examples/addressbook.proto b/examples/addressbook.proto
index 23cc2f9..b4b33b4 100644
--- a/examples/addressbook.proto
+++ b/examples/addressbook.proto
@@ -9,6 +9,8 @@
 // [START declaration]
 syntax = "proto3";
 package tutorial;
+
+import "google/protobuf/timestamp.proto";
 // [END declaration]
 
 // [START java_declaration]
@@ -38,6 +40,8 @@
   }
 
   repeated PhoneNumber phones = 4;
+
+  google.protobuf.Timestamp last_updated = 5;
 }
 
 // Our address book file is just one of these.
diff --git a/examples/list_people.cc b/examples/list_people.cc
index 68e5666..b309c59 100644
--- a/examples/list_people.cc
+++ b/examples/list_people.cc
@@ -1,11 +1,16 @@
 // See README.txt for information and build instructions.
 
-#include <iostream>
 #include <fstream>
+#include <google/protobuf/util/time_util.h>
+#include <iostream>
 #include <string>
+
 #include "addressbook.pb.h"
+
 using namespace std;
 
+using google::protobuf::util::TimeUtil;
+
 // Iterates though all people in the AddressBook and prints info about them.
 void ListPeople(const tutorial::AddressBook& address_book) {
   for (int i = 0; i < address_book.people_size(); i++) {
@@ -30,9 +35,15 @@
         case tutorial::Person::WORK:
           cout << "  Work phone #: ";
           break;
+        default:
+          cout << "  Unknown phone #: ";
+          break;
       }
       cout << phone_number.number() << endl;
     }
+    if (person.has_last_updated()) {
+      cout << "  Updated: " << TimeUtil::ToString(person.last_updated()) << endl;
+    }
   }
 }
 
diff --git a/examples/list_people.py b/examples/list_people.py
index f131872..d2c294c 100755
--- a/examples/list_people.py
+++ b/examples/list_people.py
@@ -2,30 +2,33 @@
 
 # See README.txt for information and build instructions.
 
+from __future__ import print_function
 import addressbook_pb2
 import sys
 
+
 # Iterates though all people in the AddressBook and prints info about them.
 def ListPeople(address_book):
   for person in address_book.people:
-    print "Person ID:", person.id
-    print "  Name:", person.name
+    print("Person ID:", person.id)
+    print("  Name:", person.name)
     if person.email != "":
-      print "  E-mail address:", person.email
+      print("  E-mail address:", person.email)
 
     for phone_number in person.phones:
       if phone_number.type == addressbook_pb2.Person.MOBILE:
-        print "  Mobile phone #:",
+        print("  Mobile phone #:", end=" ")
       elif phone_number.type == addressbook_pb2.Person.HOME:
-        print "  Home phone #:",
+        print("  Home phone #:", end=" ")
       elif phone_number.type == addressbook_pb2.Person.WORK:
-        print "  Work phone #:",
-      print phone_number.number
+        print("  Work phone #:", end=" ")
+      print(phone_number.number)
+
 
 # Main procedure:  Reads the entire address book from a file and prints all
 #   the information inside.
 if len(sys.argv) != 2:
-  print "Usage:", sys.argv[0], "ADDRESS_BOOK_FILE"
+  print("Usage:", sys.argv[0], "ADDRESS_BOOK_FILE")
   sys.exit(-1)
 
 address_book = addressbook_pb2.AddressBook()
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index 229bec4..8a5ed48 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -42,12 +42,23 @@
   google/protobuf/wrappers.proto)
 
 declare -a COMPILER_PROTO_FILES=(\
-  google/protobuf/compiler/plugin.proto \
-  google/protobuf/compiler/profile.proto \
-)
+  google/protobuf/compiler/plugin.proto)
 
 CORE_PROTO_IS_CORRECT=0
 PROCESS_ROUND=1
+BOOTSTRAP_PROTOC=""
+while [ $# -gt 0 ]; do
+  case $1 in
+    --bootstrap_protoc)
+      BOOTSTRAP_PROTOC=$2
+      shift
+      ;;
+    *)
+      break
+      ;;
+  esac
+  shift
+done
 TMP=$(mktemp -d)
 echo "Updating descriptor protos..."
 while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
@@ -55,14 +66,20 @@
   echo "Round $PROCESS_ROUND"
   CORE_PROTO_IS_CORRECT=1
 
-  make $@ protoc
-  if test $? -ne 0; then
-    echo "Failed to build protoc."
-    exit 1
+  if [ "$BOOTSTRAP_PROTOC" != "" ]; then
+    PROTOC=$BOOTSTRAP_PROTOC
+    BOOTSTRAP_PROTOC=""
+  else
+    make $@ protoc
+    if test $? -ne 0; then
+      echo "Failed to build protoc."
+      exit 1
+    fi
+    PROTOC="./protoc"
   fi
 
-  ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
-  ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP ${COMPILER_PROTO_FILES[@]}
+  $PROTOC --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
+  $PROTOC --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:$TMP ${COMPILER_PROTO_FILES[@]}
 
   for PROTO_FILE in ${RUNTIME_PROTO_FILES[@]} ${COMPILER_PROTO_FILES[@]}; do
     BASE_NAME=${PROTO_FILE%.*}
diff --git a/java/core/generate-test-sources-build.xml b/java/core/generate-test-sources-build.xml
index ab415db..6895174 100644
--- a/java/core/generate-test-sources-build.xml
+++ b/java/core/generate-test-sources-build.xml
@@ -5,6 +5,7 @@
         <arg value="--proto_path=${protobuf.source.dir}"/>
         <arg value="--proto_path=${test.proto.dir}"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_public.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_mset.proto"/>
@@ -40,4 +41,4 @@
         <arg value="${test.proto.dir}/com/google/protobuf/map_test.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/map_initialization_order_test.proto"/>
     </exec>
-</project>
\ No newline at end of file
+</project>
diff --git a/java/core/pom.xml b/java/core/pom.xml
index 9c4e1b9..4608fce 100644
--- a/java/core/pom.xml
+++ b/java/core/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.3.0</version>
+    <version>3.4.0</version>
   </parent>
 
   <artifactId>protobuf-java</artifactId>
@@ -34,11 +34,6 @@
       <artifactId>easymockclassextension</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency>
-      <groupId>com.google.truth</groupId>
-      <artifactId>truth</artifactId>
-      <scope>test</scope>
-    </dependency>
   </dependencies>
 
   <build>
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
index b5043eb..065fa1a 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -32,6 +32,7 @@
 
 import com.google.protobuf.Descriptors.EnumValueDescriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
+import com.google.protobuf.Descriptors.FileDescriptor.Syntax;
 import com.google.protobuf.Descriptors.OneofDescriptor;
 import com.google.protobuf.Internal.EnumLite;
 import java.io.IOException;
@@ -162,7 +163,7 @@
     }
     return hash;
   }
-  
+
   private static ByteString toByteString(Object value) {
     if (value instanceof byte[]) {
       return ByteString.copyFrom((byte[]) value);
@@ -170,7 +171,7 @@
       return (ByteString) value;
     }
   }
- 
+
   /**
    * Compares two bytes fields. The parameters must be either a byte array or a
    * ByteString object. They can be of different type though.
@@ -181,7 +182,7 @@
     }
     return toByteString(a).equals(toByteString(b));
   }
-  
+
   /**
    * Converts a list of MapEntry messages into a Map used for equals() and
    * hashCode().
@@ -212,7 +213,7 @@
     }
     return result;
   }
-  
+
   /**
    * Compares two map fields. The parameters must be a list of MapEntry
    * messages.
@@ -223,13 +224,13 @@
     Map mb = convertMapEntryListToMap((List) b);
     return MapFieldLite.equals(ma, mb);
   }
-  
+
   /**
    * Compares two set of fields.
    * This method is used to implement {@link AbstractMessage#equals(Object)}
    * and {@link AbstractMutableMessage#equals(Object)}. It takes special care
    * of bytes fields because immutable messages and mutable messages use
-   * different Java type to reprensent a bytes field and this method should be
+   * different Java type to represent a bytes field and this method should be
    * able to compare immutable messages, mutable messages and also an immutable
    * message to a mutable message.
    */
@@ -275,7 +276,7 @@
     }
     return true;
   }
-  
+
   /**
    * Calculates the hash code of a map field. {@code value} must be a list of
    * MapEntry messages.
@@ -371,7 +372,7 @@
     public String getInitializationErrorString() {
       return MessageReflection.delimitWithCommas(findInitializationErrors());
     }
-    
+
     @Override
     protected BuilderType internalMergeFrom(AbstractMessageLite other) {
       return mergeFrom((Message) other);
@@ -432,8 +433,12 @@
         final CodedInputStream input,
         final ExtensionRegistryLite extensionRegistry)
         throws IOException {
+      boolean discardUnknown =
+          getDescriptorForType().getFile().getSyntax() == Syntax.PROTO3
+              ? input.shouldDiscardUnknownFieldsProto3()
+              : input.shouldDiscardUnknownFields();
       final UnknownFieldSet.Builder unknownFields =
-        UnknownFieldSet.newBuilder(getUnknownFields());
+          discardUnknown ? null : UnknownFieldSet.newBuilder(getUnknownFields());
       while (true) {
         final int tag = input.readTag();
         if (tag == 0) {
@@ -451,7 +456,9 @@
           break;
         }
       }
-      setUnknownFields(unknownFields.build());
+      if (unknownFields != null) {
+        setUnknownFields(unknownFields.build());
+      }
       return (BuilderType) this;
     }
 
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 99787fc..24830c0 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -36,7 +36,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.List;
 
 /**
  * A partial implementation of the {@link MessageLite} interface which
@@ -118,8 +120,13 @@
     }
   }
 
-  protected static <T> void addAll(final Iterable<T> values,
-      final Collection<? super T> list) {
+  // For binary compatibility
+  @Deprecated
+  protected static <T> void addAll(final Iterable<T> values, final Collection<? super T> list) {
+    Builder.addAll(values, (List) list);
+  }
+
+  protected static <T> void addAll(final Iterable<T> values, final List<? super T> list) {
     Builder.addAll(values, list);
   }
 
@@ -334,6 +341,25 @@
           + " threw an IOException (should never happen).";
     }
 
+    // We check nulls as we iterate to avoid iterating over values twice.
+    private static <T> void addAllCheckingNulls(Iterable<T> values, List<? super T> list) {
+      if (list instanceof ArrayList && values instanceof Collection) {
+        ((ArrayList<T>) list).ensureCapacity(list.size() + ((Collection<T>) values).size());
+      }
+      int begin = list.size();
+      for (T value : values) {
+        if (value == null) {
+          // encountered a null value so we must undo our modifications prior to throwing
+          String message = "Element at index " + (list.size() - begin) + " is null.";
+          for (int i = list.size() - 1; i >= begin; i--) {
+            list.remove(i);
+          }
+          throw new NullPointerException(message);
+        }
+        list.add(value);
+      }
+    }
+
     /**
      * Construct an UninitializedMessageException reporting missing fields in
      * the given message.
@@ -343,16 +369,20 @@
       return new UninitializedMessageException(message);
     }
 
+    // For binary compatibility.
+    @Deprecated
+    protected static <T> void addAll(final Iterable<T> values, final Collection<? super T> list) {
+      addAll(values, (List<T>) list);
+    }
+
     /**
-     * Adds the {@code values} to the {@code list}.  This is a helper method
-     * used by generated code.  Users should ignore it.
+     * Adds the {@code values} to the {@code list}. This is a helper method used by generated code.
+     * Users should ignore it.
      *
-     * @throws NullPointerException if {@code values} or any of the elements of
-     * {@code values} is null. When that happens, some elements of
-     * {@code values} may have already been added to the result {@code list}.
+     * @throws NullPointerException if {@code values} or any of the elements of {@code values} is
+     *     null.
      */
-    protected static <T> void addAll(final Iterable<T> values,
-                                     final Collection<? super T> list) {
+    protected static <T> void addAll(final Iterable<T> values, final List<? super T> list) {
       checkNotNull(values);
       if (values instanceof LazyStringList) {
         // For StringOrByteStringLists, check the underlying elements to avoid
@@ -360,25 +390,31 @@
         // TODO(dweis): Could we just prohibit nulls in all protobuf lists and get rid of this? Is
         // if even possible to hit this condition as all protobuf methods check for null first,
         // right?
-        checkForNullValues(((LazyStringList) values).getUnderlyingElements());
-        list.addAll((Collection<T>) values);
-      } else if (values instanceof Collection) {
-        if (!(values instanceof PrimitiveNonBoxingCollection)) {
-          checkForNullValues(values);
+        List<?> lazyValues = ((LazyStringList) values).getUnderlyingElements();
+        LazyStringList lazyList = (LazyStringList) list;
+        int begin = list.size();
+        for (Object value : lazyValues) {
+          if (value == null) {
+            // encountered a null value so we must undo our modifications prior to throwing
+            String message = "Element at index " + (lazyList.size() - begin) + " is null.";
+            for (int i = lazyList.size() - 1; i >= begin; i--) {
+              lazyList.remove(i);
+            }
+            throw new NullPointerException(message);
+          }
+          if (value instanceof ByteString) {
+            lazyList.add((ByteString) value);
+          } else {
+            lazyList.add((String) value);
+          }
         }
-        list.addAll((Collection<T>) values);
       } else {
-        for (final T value : values) {
-          checkNotNull(value);
-          list.add(value);
+        if (values instanceof PrimitiveNonBoxingCollection) {
+          list.addAll((Collection<T>) values);
+        } else {
+          addAllCheckingNulls(values, list);
         }
       }
     }
-
-    private static void checkForNullValues(final Iterable<?> values) {
-      for (final Object value : values) {
-        checkNotNull(value);
-      }
-    }
   }
 }
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index 3dfbcb0..d6a941b 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -34,8 +34,8 @@
 import static com.google.protobuf.Internal.EMPTY_BYTE_BUFFER;
 import static com.google.protobuf.Internal.UTF_8;
 import static com.google.protobuf.Internal.checkNotNull;
-import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
-import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
+import static com.google.protobuf.WireFormat.FIXED32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED64_SIZE;
 import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
 
 import java.io.ByteArrayOutputStream;
@@ -372,6 +372,64 @@
     return oldLimit;
   }
 
+
+  private boolean explicitDiscardUnknownFields = false;
+
+  /** TODO(liujisi): flip the default.*/
+  private static volatile boolean proto3DiscardUnknownFieldsDefault = true;
+
+  static void setProto3DiscardUnknownsByDefaultForTest() {
+    proto3DiscardUnknownFieldsDefault = true;
+  }
+
+  static void setProto3KeepUnknownsByDefaultForTest() {
+    proto3DiscardUnknownFieldsDefault = false;
+  }
+
+  static boolean getProto3DiscardUnknownFieldsDefault() {
+    return proto3DiscardUnknownFieldsDefault;
+  }
+
+  /**
+   * Sets this {@code CodedInputStream} to discard unknown fields. Only applies to full runtime
+   * messages; lite messages will always preserve unknowns.
+   *
+   * <p>Note calling this function alone will have NO immediate effect on the underlying input data.
+   * The unknown fields will be discarded during parsing. This affects both Proto2 and Proto3 full
+   * runtime.
+   */
+  final void discardUnknownFields() {
+    explicitDiscardUnknownFields = true;
+  }
+
+  /**
+   * Reverts the unknown fields preservation behavior for Proto2 and Proto3 full runtime to their
+   * default.
+   */
+  final void unsetDiscardUnknownFields() {
+    explicitDiscardUnknownFields = false;
+  }
+
+  /**
+   * Whether unknown fields in this input stream should be discarded during parsing into full
+   * runtime messages.
+   */
+  final boolean shouldDiscardUnknownFields() {
+    return explicitDiscardUnknownFields;
+  }
+
+  /**
+   * Whether unknown fields in this input stream should be discarded during parsing for proto3 full
+   * runtime messages.
+   *
+   * <p>This function was temporarily introduced before proto3 unknown fields behavior is changed.
+   * TODO(liujisi): remove this and related code in GeneratedMessage after proto3 unknown
+   * fields migration is done.
+   */
+  final boolean shouldDiscardUnknownFieldsProto3() {
+    return explicitDiscardUnknownFields ? true : proto3DiscardUnknownFieldsDefault;
+  }
+
   /**
    * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). Only valid for {@link
    * InputStream}-backed streams.
@@ -572,7 +630,7 @@
           skipRawVarint();
           return true;
         case WireFormat.WIRETYPE_FIXED64:
-          skipRawBytes(FIXED_64_SIZE);
+          skipRawBytes(FIXED64_SIZE);
           return true;
         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
           skipRawBytes(readRawVarint32());
@@ -585,7 +643,7 @@
         case WireFormat.WIRETYPE_END_GROUP:
           return false;
         case WireFormat.WIRETYPE_FIXED32:
-          skipRawBytes(FIXED_32_SIZE);
+          skipRawBytes(FIXED32_SIZE);
           return true;
         default:
           throw InvalidProtocolBufferException.invalidWireType();
@@ -1064,12 +1122,12 @@
     public int readRawLittleEndian32() throws IOException {
       int tempPos = pos;
 
-      if (limit - tempPos < FIXED_32_SIZE) {
+      if (limit - tempPos < FIXED32_SIZE) {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
 
       final byte[] buffer = this.buffer;
-      pos = tempPos + FIXED_32_SIZE;
+      pos = tempPos + FIXED32_SIZE;
       return (((buffer[tempPos] & 0xff))
           | ((buffer[tempPos + 1] & 0xff) << 8)
           | ((buffer[tempPos + 2] & 0xff) << 16)
@@ -1080,12 +1138,12 @@
     public long readRawLittleEndian64() throws IOException {
       int tempPos = pos;
 
-      if (limit - tempPos < FIXED_64_SIZE) {
+      if (limit - tempPos < FIXED64_SIZE) {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
 
       final byte[] buffer = this.buffer;
-      pos = tempPos + FIXED_64_SIZE;
+      pos = tempPos + FIXED64_SIZE;
       return (((buffer[tempPos] & 0xffL))
           | ((buffer[tempPos + 1] & 0xffL) << 8)
           | ((buffer[tempPos + 2] & 0xffL) << 16)
@@ -1290,7 +1348,7 @@
           skipRawVarint();
           return true;
         case WireFormat.WIRETYPE_FIXED64:
-          skipRawBytes(FIXED_64_SIZE);
+          skipRawBytes(FIXED64_SIZE);
           return true;
         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
           skipRawBytes(readRawVarint32());
@@ -1303,7 +1361,7 @@
         case WireFormat.WIRETYPE_END_GROUP:
           return false;
         case WireFormat.WIRETYPE_FIXED32:
-          skipRawBytes(FIXED_32_SIZE);
+          skipRawBytes(FIXED32_SIZE);
           return true;
         default:
           throw InvalidProtocolBufferException.invalidWireType();
@@ -1429,7 +1487,9 @@
       final int size = readRawVarint32();
       if (size > 0 && size <= remaining()) {
         // TODO(nathanmittler): Is there a way to avoid this copy?
-        byte[] bytes = copyToArray(pos, pos + size);
+        // The same as readBytes' logic
+        byte[] bytes = new byte[size];
+        UnsafeUtil.copyMemory(pos, bytes, 0, size);
         String result = new String(bytes, UTF_8);
         pos += size;
         return result;
@@ -1449,7 +1509,9 @@
       final int size = readRawVarint32();
       if (size >= 0 && size <= remaining()) {
         // TODO(nathanmittler): Is there a way to avoid this copy?
-        byte[] bytes = copyToArray(pos, pos + size);
+        // The same as readBytes' logic
+        byte[] bytes = new byte[size];
+        UnsafeUtil.copyMemory(pos, bytes, 0, size);
         // TODO(martinrb): We could save a pass by validating while decoding.
         if (!Utf8.isValidUtf8(bytes)) {
           throw InvalidProtocolBufferException.invalidUtf8();
@@ -1545,14 +1607,17 @@
     public ByteString readBytes() throws IOException {
       final int size = readRawVarint32();
       if (size > 0 && size <= remaining()) {
-        ByteBuffer result;
         if (immutable && enableAliasing) {
-          result = slice(pos, pos + size);
+          final ByteBuffer result = slice(pos, pos + size);
+          pos += size;
+          return ByteString.wrap(result);
         } else {
-          result = copy(pos, pos + size);
+          // Use UnsafeUtil to copy the memory to bytes instead of using ByteBuffer ways.
+          byte[] bytes = new byte[size];
+          UnsafeUtil.copyMemory(pos, bytes, 0, size);
+          pos += size;
+          return ByteString.wrap(bytes);
         }
-        pos += size;
-        return ByteString.wrap(result);
       }
 
       if (size == 0) {
@@ -1573,18 +1638,21 @@
     public ByteBuffer readByteBuffer() throws IOException {
       final int size = readRawVarint32();
       if (size > 0 && size <= remaining()) {
-        ByteBuffer result;
         // "Immutable" implies that buffer is backing a ByteString.
         // Disallow slicing in this case to prevent the caller from modifying the contents
         // of the ByteString.
         if (!immutable && enableAliasing) {
-          result = slice(pos, pos + size);
+          final ByteBuffer result = slice(pos, pos + size);
+          pos += size;
+          return result;
         } else {
-          result = copy(pos, pos + size);
+          // The same as readBytes' logic
+          byte[] bytes = new byte[size];
+          UnsafeUtil.copyMemory(pos, bytes, 0, size);
+          pos += size;
+          return ByteBuffer.wrap(bytes);
         }
-        pos += size;
         // TODO(nathanmittler): Investigate making the ByteBuffer be made read-only
-        return result;
       }
 
       if (size == 0) {
@@ -1785,11 +1853,11 @@
     public int readRawLittleEndian32() throws IOException {
       long tempPos = pos;
 
-      if (limit - tempPos < FIXED_32_SIZE) {
+      if (limit - tempPos < FIXED32_SIZE) {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
 
-      pos = tempPos + FIXED_32_SIZE;
+      pos = tempPos + FIXED32_SIZE;
       return (((UnsafeUtil.getByte(tempPos) & 0xff))
           | ((UnsafeUtil.getByte(tempPos + 1) & 0xff) << 8)
           | ((UnsafeUtil.getByte(tempPos + 2) & 0xff) << 16)
@@ -1800,11 +1868,11 @@
     public long readRawLittleEndian64() throws IOException {
       long tempPos = pos;
 
-      if (limit - tempPos < FIXED_64_SIZE) {
+      if (limit - tempPos < FIXED64_SIZE) {
         throw InvalidProtocolBufferException.truncatedMessage();
       }
 
-      pos = tempPos + FIXED_64_SIZE;
+      pos = tempPos + FIXED64_SIZE;
       return (((UnsafeUtil.getByte(tempPos) & 0xffL))
           | ((UnsafeUtil.getByte(tempPos + 1) & 0xffL) << 8)
           | ((UnsafeUtil.getByte(tempPos + 2) & 0xffL) << 16)
@@ -1943,27 +2011,6 @@
         buffer.limit(prevLimit);
       }
     }
-
-    private ByteBuffer copy(long begin, long end) throws IOException {
-      return ByteBuffer.wrap(copyToArray(begin, end));
-    }
-
-    private byte[] copyToArray(long begin, long end) throws IOException {
-      int prevPos = buffer.position();
-      int prevLimit = buffer.limit();
-      try {
-        buffer.position(bufferPos(begin));
-        buffer.limit(bufferPos(end));
-        byte[] bytes = new byte[(int) (end - begin)];
-        buffer.get(bytes);
-        return bytes;
-      } catch (IllegalArgumentException e) {
-        throw InvalidProtocolBufferException.truncatedMessage();
-      } finally {
-        buffer.position(prevPos);
-        buffer.limit(prevLimit);
-      }
-    }
   }
 
   /**
@@ -2034,7 +2081,7 @@
           skipRawVarint();
           return true;
         case WireFormat.WIRETYPE_FIXED64:
-          skipRawBytes(FIXED_64_SIZE);
+          skipRawBytes(FIXED64_SIZE);
           return true;
         case WireFormat.WIRETYPE_LENGTH_DELIMITED:
           skipRawBytes(readRawVarint32());
@@ -2047,7 +2094,7 @@
         case WireFormat.WIRETYPE_END_GROUP:
           return false;
         case WireFormat.WIRETYPE_FIXED32:
-          skipRawBytes(FIXED_32_SIZE);
+          skipRawBytes(FIXED32_SIZE);
           return true;
         default:
           throw InvalidProtocolBufferException.invalidWireType();
@@ -2332,8 +2379,7 @@
       if (size == 0) {
         return ByteString.EMPTY;
       }
-      // Slow path:  Build a byte array first then copy it.
-      return ByteString.wrap(readRawBytesSlowPath(size));
+      return readBytesSlowPath(size);
     }
 
     @Override
@@ -2558,13 +2604,13 @@
     public int readRawLittleEndian32() throws IOException {
       int tempPos = pos;
 
-      if (bufferSize - tempPos < FIXED_32_SIZE) {
-        refillBuffer(FIXED_32_SIZE);
+      if (bufferSize - tempPos < FIXED32_SIZE) {
+        refillBuffer(FIXED32_SIZE);
         tempPos = pos;
       }
 
       final byte[] buffer = this.buffer;
-      pos = tempPos + FIXED_32_SIZE;
+      pos = tempPos + FIXED32_SIZE;
       return (((buffer[tempPos] & 0xff))
           | ((buffer[tempPos + 1] & 0xff) << 8)
           | ((buffer[tempPos + 2] & 0xff) << 16)
@@ -2575,13 +2621,13 @@
     public long readRawLittleEndian64() throws IOException {
       int tempPos = pos;
 
-      if (bufferSize - tempPos < FIXED_64_SIZE) {
-        refillBuffer(FIXED_64_SIZE);
+      if (bufferSize - tempPos < FIXED64_SIZE) {
+        refillBuffer(FIXED64_SIZE);
         tempPos = pos;
       }
 
       final byte[] buffer = this.buffer;
-      pos = tempPos + FIXED_64_SIZE;
+      pos = tempPos + FIXED64_SIZE;
       return (((buffer[tempPos] & 0xffL))
           | ((buffer[tempPos + 1] & 0xffL) << 8)
           | ((buffer[tempPos + 2] & 0xffL) << 16)
@@ -2675,7 +2721,13 @@
      */
     private void refillBuffer(int n) throws IOException {
       if (!tryRefillBuffer(n)) {
-        throw InvalidProtocolBufferException.truncatedMessage();
+        // We have to distinguish the exception between sizeLimitExceeded and truncatedMessage. So
+        // we just throw an sizeLimitExceeded exception here if it exceeds the sizeLimit
+        if (n > sizeLimit - totalBytesRetired - pos) {
+          throw InvalidProtocolBufferException.sizeLimitExceeded();
+        } else {
+          throw InvalidProtocolBufferException.truncatedMessage();
+        }
       }
     }
 
@@ -2684,8 +2736,8 @@
      * buffer. Caller must ensure that the requested space is not yet available, and that the
      * requested space is less than BUFFER_SIZE.
      *
-     * @return {@code true} if the bytes could be made available; {@code false} if the end of the
-     *     stream or the current limit was reached.
+     * @return {@code true} If the bytes could be made available; {@code false} 1. Current at the
+     *     end of the stream 2. The current limit was reached 3. The total size limit was reached
      */
     private boolean tryRefillBuffer(int n) throws IOException {
       if (pos + n <= bufferSize) {
@@ -2693,6 +2745,14 @@
             "refillBuffer() called when " + n + " bytes were already available in buffer");
       }
 
+      // Check whether the size of total message needs to read is bigger than the size limit.
+      // We shouldn't throw an exception here as isAtEnd() function needs to get this function's
+      // return as the result.
+      if (n > sizeLimit - totalBytesRetired - pos) {
+        return false;
+      }
+
+      // Shouldn't throw the exception here either.
       if (totalBytesRetired + pos + n > currentLimit) {
         // Oops, we hit a limit.
         return false;
@@ -2712,7 +2772,16 @@
         pos = 0;
       }
 
-      int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize);
+      // Here we should refill the buffer as many bytes as possible.
+      int bytesRead =
+          input.read(
+              buffer,
+              bufferSize,
+              Math.min(
+                  //  the size of allocated but unused bytes in the buffer
+                  buffer.length - bufferSize,
+                  //  do not exceed the total bytes limit
+                  sizeLimit - totalBytesRetired - bufferSize));
       if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) {
         throw new IllegalStateException(
             "InputStream#read(byte[]) returned invalid result: "
@@ -2721,10 +2790,6 @@
       }
       if (bytesRead > 0) {
         bufferSize += bytesRead;
-        // Integer-overflow-conscious check against sizeLimit
-        if (totalBytesRetired + n - sizeLimit > 0) {
-          throw InvalidProtocolBufferException.sizeLimitExceeded();
-        }
         recomputeBufferSizeAfterLimit();
         return (bufferSize >= n) ? true : tryRefillBuffer(n);
       }
@@ -2756,6 +2821,49 @@
      * (bufferSize - pos) && size > 0)
      */
     private byte[] readRawBytesSlowPath(final int size) throws IOException {
+      // Attempt to read the data in one byte array when it's safe to do.
+      byte[] result = readRawBytesSlowPathOneChunk(size);
+      if (result != null) {
+        return result;
+      }
+
+      final int originalBufferPos = pos;
+      final int bufferedBytes = bufferSize - pos;
+
+      // Mark the current buffer consumed.
+      totalBytesRetired += bufferSize;
+      pos = 0;
+      bufferSize = 0;
+
+      // Determine the number of bytes we need to read from the input stream.
+      int sizeLeft = size - bufferedBytes;
+
+      // The size is very large. For security reasons we read them in small
+      // chunks.
+      List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
+
+      // OK, got everything.  Now concatenate it all into one buffer.
+      final byte[] bytes = new byte[size];
+
+      // Start by copying the leftover bytes from this.buffer.
+      System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
+
+      // And now all the chunks.
+      int tempPos = bufferedBytes;
+      for (final byte[] chunk : chunks) {
+        System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
+        tempPos += chunk.length;
+      }
+
+      // Done.
+      return bytes;
+    }
+
+    /**
+     * Attempts to read the data in one byte array when it's safe to do. Returns null if the size to
+     * read is too large and needs to be allocated in smaller chunks for security reasons.
+     */
+    private byte[] readRawBytesSlowPathOneChunk(final int size) throws IOException {
       if (size == 0) {
         return Internal.EMPTY_BYTE_ARRAY;
       }
@@ -2776,14 +2884,7 @@
         throw InvalidProtocolBufferException.truncatedMessage();
       }
 
-      final int originalBufferPos = pos;
       final int bufferedBytes = bufferSize - pos;
-
-      // Mark the current buffer consumed.
-      totalBytesRetired += bufferSize;
-      pos = 0;
-      bufferSize = 0;
-
       // Determine the number of bytes we need to read from the input stream.
       int sizeLeft = size - bufferedBytes;
       // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
@@ -2793,7 +2894,10 @@
         final byte[] bytes = new byte[size];
 
         // Copy all of the buffered bytes to the result buffer.
-        System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
+        System.arraycopy(buffer, pos, bytes, 0, bufferedBytes);
+        totalBytesRetired += bufferSize;
+        pos = 0;
+        bufferSize = 0;
 
         // Fill the remaining bytes from the input stream.
         int tempPos = bufferedBytes;
@@ -2809,6 +2913,11 @@
         return bytes;
       }
 
+      return null;
+    }
+
+    /** Reads the remaining data in small chunks from the input stream. */
+    private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException {
       // The size is very large.  For security reasons, we can't allocate the
       // entire byte array yet.  The size comes directly from the input, so a
       // maliciously-crafted message could provide a bogus very large size in
@@ -2834,21 +2943,41 @@
         chunks.add(chunk);
       }
 
-      // OK, got everything.  Now concatenate it all into one buffer.
-      final byte[] bytes = new byte[size];
+      return chunks;
+    }
 
-      // Start by copying the leftover bytes from this.buffer.
-      System.arraycopy(buffer, originalBufferPos, bytes, 0, bufferedBytes);
-
-      // And now all the chunks.
-      int tempPos = bufferedBytes;
-      for (final byte[] chunk : chunks) {
-        System.arraycopy(chunk, 0, bytes, tempPos, chunk.length);
-        tempPos += chunk.length;
+    /**
+     * Like readBytes, but caller must have already checked the fast path: (size <= (bufferSize -
+     * pos) && size > 0 || size == 0)
+     */
+    private ByteString readBytesSlowPath(final int size) throws IOException {
+      final byte[] result = readRawBytesSlowPathOneChunk(size);
+      if (result != null) {
+        return ByteString.wrap(result);
       }
 
-      // Done.
-      return bytes;
+      final int originalBufferPos = pos;
+      final int bufferedBytes = bufferSize - pos;
+
+      // Mark the current buffer consumed.
+      totalBytesRetired += bufferSize;
+      pos = 0;
+      bufferSize = 0;
+
+      // Determine the number of bytes we need to read from the input stream.
+      int sizeLeft = size - bufferedBytes;
+
+      // The size is very large. For security reasons we read them in small
+      // chunks.
+      List<byte[]> chunks = readRawBytesSlowPathRemainingChunks(sizeLeft);
+
+      // Wrap the byte arrays into a single ByteString.
+      List<ByteString> byteStrings = new ArrayList<ByteString>(1 + chunks.size());
+      byteStrings.add(ByteString.copyFrom(buffer, originalBufferPos, bufferedBytes));
+      for (byte[] chunk : chunks) {
+        byteStrings.add(ByteString.wrap(chunk));
+      }
+      return ByteString.copyFrom(byteStrings);
     }
 
     @Override
diff --git a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
index da0e9b1..093a5f6 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
@@ -30,8 +30,8 @@
 
 package com.google.protobuf;
 
-import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
-import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
+import static com.google.protobuf.WireFormat.FIXED32_SIZE;
+import static com.google.protobuf.WireFormat.FIXED64_SIZE;
 import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
 import static java.lang.Math.max;
 
@@ -59,13 +59,12 @@
 public abstract class CodedOutputStream extends ByteOutput {
   private static final Logger logger = Logger.getLogger(CodedOutputStream.class.getName());
   private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsafeArrayOperations();
-  private static final long ARRAY_BASE_OFFSET = UnsafeUtil.getArrayBaseOffset();
 
   /**
    * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
    */
   @Deprecated
-  public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
+  public static final int LITTLE_ENDIAN_32_SIZE = FIXED32_SIZE;
 
   /**
    * The buffer size used in {@link #newInstance(OutputStream)}.
@@ -755,7 +754,7 @@
    * {@code fixed32} field.
    */
   public static int computeFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
-    return FIXED_32_SIZE;
+    return FIXED32_SIZE;
   }
 
   /**
@@ -763,7 +762,7 @@
    * {@code sfixed32} field.
    */
   public static int computeSFixed32SizeNoTag(@SuppressWarnings("unused") final int unused) {
-    return FIXED_32_SIZE;
+    return FIXED32_SIZE;
   }
 
   /**
@@ -813,7 +812,7 @@
    * {@code fixed64} field.
    */
   public static int computeFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
-    return FIXED_64_SIZE;
+    return FIXED64_SIZE;
   }
 
   /**
@@ -821,7 +820,7 @@
    * {@code sfixed64} field.
    */
   public static int computeSFixed64SizeNoTag(@SuppressWarnings("unused") final long unused) {
-    return FIXED_64_SIZE;
+    return FIXED64_SIZE;
   }
 
   /**
@@ -829,7 +828,7 @@
    * {@code float} field, including tag.
    */
   public static int computeFloatSizeNoTag(@SuppressWarnings("unused") final float unused) {
-    return FIXED_32_SIZE;
+    return FIXED32_SIZE;
   }
 
   /**
@@ -837,7 +836,7 @@
    * {@code double} field, including tag.
    */
   public static int computeDoubleSizeNoTag(@SuppressWarnings("unused") final double unused) {
-    return FIXED_64_SIZE;
+    return FIXED64_SIZE;
   }
 
   /**
@@ -1321,15 +1320,12 @@
     @Override
     public final void writeUInt32NoTag(int value) throws IOException {
       if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
-        long pos = ARRAY_BASE_OFFSET + position;
         while (true) {
           if ((value & ~0x7F) == 0) {
-            UnsafeUtil.putByte(buffer, pos++, (byte) value);
-            position++;
+            UnsafeUtil.putByte(buffer, position++, (byte) value);
             return;
           } else {
-            UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
-            position++;
+            UnsafeUtil.putByte(buffer, position++, (byte) ((value & 0x7F) | 0x80));
             value >>>= 7;
           }
         }
@@ -1367,15 +1363,12 @@
     @Override
     public final void writeUInt64NoTag(long value) throws IOException {
       if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
-        long pos = ARRAY_BASE_OFFSET + position;
         while (true) {
           if ((value & ~0x7FL) == 0) {
-            UnsafeUtil.putByte(buffer, pos++, (byte) value);
-            position++;
+            UnsafeUtil.putByte(buffer, position++, (byte) value);
             return;
           } else {
-            UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
-            position++;
+            UnsafeUtil.putByte(buffer, position++, (byte) (((int) value & 0x7F) | 0x80));
             value >>>= 7;
           }
         }
@@ -1854,7 +1847,7 @@
     }
 
     static boolean isSupported() {
-      return UnsafeUtil.hasUnsafeByteBufferOperations() && UnsafeUtil.hasUnsafeCopyMemory();
+      return UnsafeUtil.hasUnsafeByteBufferOperations();
     }
 
     @Override
@@ -2030,7 +2023,7 @@
     @Override
     public void writeFixed32NoTag(int value) throws IOException {
       buffer.putInt(bufferPos(position), value);
-      position += FIXED_32_SIZE;
+      position += FIXED32_SIZE;
     }
 
     @Override
@@ -2064,7 +2057,7 @@
     @Override
     public void writeFixed64NoTag(long value) throws IOException {
       buffer.putLong(bufferPos(position), value);
-      position += FIXED_64_SIZE;
+      position += FIXED64_SIZE;
     }
 
     @Override
@@ -2081,8 +2074,7 @@
             String.format("Pos: %d, limit: %d, len: %d", position, limit, length));
       }
 
-      UnsafeUtil.copyMemory(
-          value, UnsafeUtil.getArrayBaseOffset() + offset, null, position, length);
+      UnsafeUtil.copyMemory(value, offset, position, length);
       position += length;
     }
 
@@ -2249,19 +2241,17 @@
      */
     final void bufferUInt32NoTag(int value) {
       if (HAS_UNSAFE_ARRAY_OPERATIONS) {
-        final long originalPos = ARRAY_BASE_OFFSET + position;
-        long pos = originalPos;
+        final long originalPos = position;
         while (true) {
           if ((value & ~0x7F) == 0) {
-            UnsafeUtil.putByte(buffer, pos++, (byte) value);
+            UnsafeUtil.putByte(buffer, position++, (byte) value);
             break;
           } else {
-            UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
+            UnsafeUtil.putByte(buffer, position++, (byte) ((value & 0x7F) | 0x80));
             value >>>= 7;
           }
         }
-        int delta = (int) (pos - originalPos);
-        position += delta;
+        int delta = (int) (position - originalPos);
         totalBytesWritten += delta;
       } else {
         while (true) {
@@ -2284,19 +2274,17 @@
      */
     final void bufferUInt64NoTag(long value) {
       if (HAS_UNSAFE_ARRAY_OPERATIONS) {
-        final long originalPos = ARRAY_BASE_OFFSET + position;
-        long pos = originalPos;
+        final long originalPos = position;
         while (true) {
           if ((value & ~0x7FL) == 0) {
-            UnsafeUtil.putByte(buffer, pos++, (byte) value);
+            UnsafeUtil.putByte(buffer, position++, (byte) value);
             break;
           } else {
-            UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80));
+            UnsafeUtil.putByte(buffer, position++, (byte) (((int) value & 0x7F) | 0x80));
             value >>>= 7;
           }
         }
-        int delta = (int) (pos - originalPos);
-        position += delta;
+        int delta = (int) (position - originalPos);
         totalBytesWritten += delta;
       } else {
         while (true) {
@@ -2322,7 +2310,7 @@
       buffer[position++] = (byte) ((value >> 8) & 0xFF);
       buffer[position++] = (byte) ((value >> 16) & 0xFF);
       buffer[position++] = (byte) ((value >> 24) & 0xFF);
-      totalBytesWritten += FIXED_32_SIZE;
+      totalBytesWritten += FIXED32_SIZE;
     }
 
     /**
@@ -2338,7 +2326,7 @@
       buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
       buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
       buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
-      totalBytesWritten += FIXED_64_SIZE;
+      totalBytesWritten += FIXED64_SIZE;
     }
   }
 
@@ -2379,7 +2367,7 @@
 
     @Override
     public void writeFixed32(final int fieldNumber, final int value) throws IOException {
-      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED32_SIZE);
       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
       bufferFixed32NoTag(value);
     }
@@ -2393,7 +2381,7 @@
 
     @Override
     public void writeFixed64(final int fieldNumber, final long value) throws IOException {
-      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED64_SIZE);
       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
       bufferFixed64NoTag(value);
     }
@@ -2519,7 +2507,7 @@
 
     @Override
     public void writeFixed32NoTag(final int value) throws IOException {
-      flushIfNotAvailable(FIXED_32_SIZE);
+      flushIfNotAvailable(FIXED32_SIZE);
       bufferFixed32NoTag(value);
     }
 
@@ -2531,7 +2519,7 @@
 
     @Override
     public void writeFixed64NoTag(final long value) throws IOException {
-      flushIfNotAvailable(FIXED_64_SIZE);
+      flushIfNotAvailable(FIXED64_SIZE);
       bufferFixed64NoTag(value);
     }
 
@@ -2682,7 +2670,7 @@
 
     @Override
     public void writeFixed32(final int fieldNumber, final int value) throws IOException {
-      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_32_SIZE);
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED32_SIZE);
       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
       bufferFixed32NoTag(value);
     }
@@ -2696,7 +2684,7 @@
 
     @Override
     public void writeFixed64(final int fieldNumber, final long value) throws IOException {
-      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED_64_SIZE);
+      flushIfNotAvailable(MAX_VARINT_SIZE + FIXED64_SIZE);
       bufferTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
       bufferFixed64NoTag(value);
     }
@@ -2822,7 +2810,7 @@
 
     @Override
     public void writeFixed32NoTag(final int value) throws IOException {
-      flushIfNotAvailable(FIXED_32_SIZE);
+      flushIfNotAvailable(FIXED32_SIZE);
       bufferFixed32NoTag(value);
     }
 
@@ -2834,7 +2822,7 @@
 
     @Override
     public void writeFixed64NoTag(final long value) throws IOException {
-      flushIfNotAvailable(FIXED_64_SIZE);
+      flushIfNotAvailable(FIXED64_SIZE);
       bufferFixed64NoTag(value);
     }
 
diff --git a/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java b/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java
new file mode 100644
index 0000000..7ae9434
--- /dev/null
+++ b/java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java
@@ -0,0 +1,71 @@
+// 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.
+
+package com.google.protobuf;
+
+/**
+ * Parsers to discard unknown fields during parsing.
+ */
+public final class DiscardUnknownFieldsParser {
+
+  /**
+   * Warps a given {@link Parser} into a new {@link Parser} that discards unknown fields during
+   * parsing.
+   *
+   * <p>Usage example:
+   * <pre>{@code
+     * private final static Parser<Foo> FOO_PARSER = DiscardUnknownFieldsParser.wrap(Foo.parser());
+     * Foo parseFooDiscardUnknown(ByteBuffer input) throws IOException {
+     *   return FOO_PARSER.parseFrom(input);
+     * }
+   * }</pre>
+   *
+   * <p>Like all other implementations of {@code Parser}, this parser is stateless and thread-safe.
+   *
+   * @param parser The delegated parser that parses messages.
+   * @return a {@link Parser} that will discard unknown fields during parsing.
+   */
+  public static final <T extends Message> Parser<T> wrap(final Parser<T> parser) {
+    return new AbstractParser<T>() {
+      @Override
+      public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
+          throws InvalidProtocolBufferException {
+        try {
+          input.discardUnknownFields();
+          return parser.parsePartialFrom(input, extensionRegistry);
+        } finally {
+          input.unsetDiscardUnknownFields();
+        }
+      }
+    };
+  }
+
+  private DiscardUnknownFieldsParser() {}
+}
diff --git a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
index 2631db7..ba53202 100644
--- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -590,9 +590,8 @@
 
     @Override
     public Builder setUnknownFields(UnknownFieldSet unknownFields) {
-      if (getDescriptorForType().getFile().getSyntax()
-          == Descriptors.FileDescriptor.Syntax.PROTO3) {
-        // Proto3 discards unknown fields.
+      if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
+          && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
         return this;
       }
       this.unknownFields = unknownFields;
@@ -601,9 +600,8 @@
 
     @Override
     public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
-      if (getDescriptorForType().getFile().getSyntax()
-          == Descriptors.FileDescriptor.Syntax.PROTO3) {
-        // Proto3 discards unknown fields.
+      if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
+          && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
         return this;
       }
       this.unknownFields =
diff --git a/java/core/src/main/java/com/google/protobuf/Extension.java b/java/core/src/main/java/com/google/protobuf/Extension.java
index 08ec5b4..5df12e6 100644
--- a/java/core/src/main/java/com/google/protobuf/Extension.java
+++ b/java/core/src/main/java/com/google/protobuf/Extension.java
@@ -58,10 +58,7 @@
     PROTO1,
   }
 
-  protected ExtensionType getExtensionType() {
-    // TODO(liujisi): make this abstract after we fix proto1.
-    return ExtensionType.IMMUTABLE;
-  }
+  protected abstract ExtensionType getExtensionType();
 
   /**
    * Type of a message extension.
@@ -70,7 +67,7 @@
     PROTO1,
     PROTO2,
   }
-  
+
   /**
    * If the extension is a message extension (i.e., getLiteType() == MESSAGE),
    * returns the type of the message, otherwise undefined.
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
index 23174e2..89f7ab9 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
@@ -34,7 +34,7 @@
 
 /**
  * A factory object to create instances of {@link ExtensionRegistryLite}.
- * 
+ *
  * <p>
  * This factory detects (via reflection) if the full (non-Lite) protocol buffer libraries
  * are available, and if so, the instances returned are actually {@link ExtensionRegistry}.
@@ -82,6 +82,7 @@
     return EMPTY_REGISTRY_LITE;
   }
 
+
   static boolean isFullRegistry(ExtensionRegistryLite registry) {
     return EXTENSION_REGISTRY_CLASS != null
         && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass());
@@ -90,6 +91,6 @@
   private static final ExtensionRegistryLite invokeSubclassFactory(String methodName)
       throws Exception {
     return (ExtensionRegistryLite) EXTENSION_REGISTRY_CLASS
-        .getMethod(methodName).invoke(null);
+        .getDeclaredMethod(methodName).invoke(null);
   }
 }
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index cf3486e..7116ae1 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -107,11 +107,12 @@
   @SuppressWarnings("unchecked") // Guaranteed by runtime
   @Override
   public int hashCode() {
-    if (memoizedHashCode == 0) {
-      HashCodeVisitor visitor = new HashCodeVisitor();
-      visit(visitor, (MessageType) this);
-      memoizedHashCode = visitor.hashCode;
+    if (memoizedHashCode != 0) {
+      return memoizedHashCode;
     }
+    HashCodeVisitor visitor = new HashCodeVisitor();
+    visit(visitor, (MessageType) this);
+    memoizedHashCode = visitor.hashCode;
     return memoizedHashCode;
   }
 
@@ -331,7 +332,7 @@
       if (isBuilt) {
         MessageType newInstance =
             (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_MUTABLE_INSTANCE);
-        newInstance.visit(MergeFromVisitor.INSTANCE, instance);
+        mergeFromInstance(newInstance, instance);
         instance = newInstance;
         isBuilt = false;
       }
@@ -386,10 +387,14 @@
     /** All subclasses implement this. */
     public BuilderType mergeFrom(MessageType message) {
       copyOnWrite();
-      instance.visit(MergeFromVisitor.INSTANCE, message);
+      mergeFromInstance(instance, message);
       return (BuilderType) this;
     }
 
+    private void mergeFromInstance(MessageType dest, MessageType src) {
+      dest.visit(MergeFromVisitor.INSTANCE, src);
+    }
+
     @Override
     public MessageType getDefaultInstanceForType() {
       return defaultInstance;
@@ -1713,7 +1718,6 @@
     Object visitOneofLong(boolean minePresent, Object mine, Object other);
     Object visitOneofString(boolean minePresent, Object mine, Object other);
     Object visitOneofByteString(boolean minePresent, Object mine, Object other);
-    Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other);
     Object visitOneofMessage(boolean minePresent, Object mine, Object other);
     void visitOneofNotSet(boolean minePresent);
 
@@ -1721,7 +1725,6 @@
      * Message fields use null sentinals.
      */
     <T extends MessageLite> T visitMessage(T mine, T other);
-    LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other);
 
     <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other);
     BooleanList visitBooleanList(BooleanList mine, BooleanList other);
@@ -1865,14 +1868,6 @@
     }
 
     @Override
-    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
-      if (minePresent && mine.equals(other)) {
-        return mine;
-      }
-      throw NOT_EQUALS;
-    }
-
-    @Override
     public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
       if (minePresent && ((GeneratedMessageLite<?, ?>) mine).equals(this, (MessageLite) other)) {
         return mine;
@@ -1903,21 +1898,6 @@
     }
 
     @Override
-    public LazyFieldLite visitLazyMessage(
-        LazyFieldLite mine, LazyFieldLite other) {
-      if (mine == null && other == null) {
-        return null;
-      }
-      if (mine == null || other == null) {
-        throw NOT_EQUALS;
-      }
-      if (mine.equals(other)) {
-        return mine;
-      }
-      throw NOT_EQUALS;
-    }
-
-    @Override
     public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
       if (!mine.equals(other)) {
         throw NOT_EQUALS;
@@ -2094,12 +2074,6 @@
     }
 
     @Override
-    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
-      hashCode = (53 * hashCode) + mine.hashCode();
-      return mine;
-    }
-
-    @Override
     public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
       return visitMessage((MessageLite) mine, (MessageLite) other);
     }
@@ -2128,18 +2102,6 @@
     }
 
     @Override
-    public LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other) {
-      final int protoHash;
-      if (mine != null) {
-        protoHash = mine.hashCode();
-      } else {
-        protoHash = 37;
-      }
-      hashCode = (53 * hashCode) + protoHash;
-      return mine;
-    }
-
-    @Override
     public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
       hashCode = (53 * hashCode) + mine.hashCode();
       return mine;
@@ -2282,13 +2244,6 @@
     }
 
     @Override
-    public Object visitOneofLazyMessage(boolean minePresent, Object mine, Object other) {
-      LazyFieldLite lazy = minePresent ? (LazyFieldLite) mine : new LazyFieldLite();
-      lazy.merge((LazyFieldLite) other);
-      return lazy;
-    }
-
-    @Override
     public Object visitOneofMessage(boolean minePresent, Object mine, Object other) {
       if (minePresent) {
         return visitMessage((MessageLite) mine, (MessageLite) other);
@@ -2312,17 +2267,6 @@
     }
 
     @Override
-    public LazyFieldLite visitLazyMessage(LazyFieldLite mine, LazyFieldLite other) {
-      if (other != null) {
-        if (mine == null) {
-          mine = new LazyFieldLite();
-        }
-        mine.merge(other);
-      }
-      return mine;
-    }
-
-    @Override
     public <T> ProtobufList<T> visitList(ProtobufList<T> mine, ProtobufList<T> other) {
       int size = mine.size();
       int otherSize = other.size();
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
index b949cd1..592869a 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -30,6 +30,8 @@
 
 package com.google.protobuf;
 
+import static com.google.protobuf.Internal.checkNotNull;
+
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.EnumDescriptor;
 import com.google.protobuf.Descriptors.EnumValueDescriptor;
@@ -47,7 +49,6 @@
 // to be able to use GeneratedMessage.GeneratedExtension. The GeneratedExtension definition in
 // this file is also excluded from opensource to avoid conflict.
 import com.google.protobuf.GeneratedMessage.GeneratedExtension;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectStreamException;
@@ -277,13 +278,30 @@
 
   /**
    * Called by subclasses to parse an unknown field.
+   *
    * @return {@code true} unless the tag is an end-group tag.
    */
   protected boolean parseUnknownField(
       CodedInputStream input,
       UnknownFieldSet.Builder unknownFields,
       ExtensionRegistryLite extensionRegistry,
-      int tag) throws IOException {
+      int tag)
+      throws IOException {
+    if (input.shouldDiscardUnknownFields()) {
+      return input.skipField(tag);
+    }
+    return unknownFields.mergeFieldFrom(tag, input);
+  }
+
+  protected boolean parseUnknownFieldProto3(
+      CodedInputStream input,
+      UnknownFieldSet.Builder unknownFields,
+      ExtensionRegistryLite extensionRegistry,
+      int tag)
+      throws IOException {
+    if (input.shouldDiscardUnknownFieldsProto3()) {
+      return input.skipField(tag);
+    }
     return unknownFields.mergeFieldFrom(tag, input);
   }
 
@@ -619,15 +637,22 @@
       return (BuilderType) this;
     }
 
+    protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
+      if (CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
+        return (BuilderType) this;
+      }
+      this.unknownFields = unknownFields;
+      onChanged();
+      return (BuilderType) this;
+    }
+
     @Override
     public BuilderType mergeUnknownFields(
         final UnknownFieldSet unknownFields) {
-      this.unknownFields =
+      return setUnknownFields(
         UnknownFieldSet.newBuilder(this.unknownFields)
                        .mergeFrom(unknownFields)
-                       .build();
-      onChanged();
-      return (BuilderType) this;
+                       .build());
     }
 
     @Override
@@ -666,18 +691,6 @@
     }
 
     /**
-     * Called by subclasses to parse an unknown field.
-     * @return {@code true} unless the tag is an end-group tag.
-     */
-    protected boolean parseUnknownField(
-        final CodedInputStream input,
-        final UnknownFieldSet.Builder unknownFields,
-        final ExtensionRegistryLite extensionRegistry,
-        final int tag) throws IOException {
-      return unknownFields.mergeFieldFrom(tag, input);
-    }
-
-    /**
      * Implementation of {@link BuilderParent} for giving to our children. This
      * small inner class makes it so we don't publicly expose the BuilderParent
      * methods.
@@ -987,8 +1000,23 @@
         ExtensionRegistryLite extensionRegistry,
         int tag) throws IOException {
       return MessageReflection.mergeFieldFrom(
-          input, unknownFields, extensionRegistry, getDescriptorForType(),
-          new MessageReflection.ExtensionAdapter(extensions), tag);
+          input, input.shouldDiscardUnknownFields() ? null : unknownFields, extensionRegistry,
+          getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag);
+    }
+
+    @Override
+    protected boolean parseUnknownFieldProto3(
+        CodedInputStream input,
+        UnknownFieldSet.Builder unknownFields,
+        ExtensionRegistryLite extensionRegistry,
+        int tag) throws IOException {
+      return MessageReflection.mergeFieldFrom(
+          input,
+          input.shouldDiscardUnknownFieldsProto3() ? null : unknownFields,
+          extensionRegistry,
+          getDescriptorForType(),
+          new MessageReflection.ExtensionAdapter(extensions),
+          tag);
     }
 
 
@@ -1458,21 +1486,6 @@
       return super.isInitialized() && extensionsAreInitialized();
     }
 
-    /**
-     * Called by subclasses to parse an unknown field or an extension.
-     * @return {@code true} unless the tag is an end-group tag.
-     */
-    @Override
-    protected boolean parseUnknownField(
-        final CodedInputStream input,
-        final UnknownFieldSet.Builder unknownFields,
-        final ExtensionRegistryLite extensionRegistry,
-        final int tag) throws IOException {
-      return MessageReflection.mergeFieldFrom(
-          input, unknownFields, extensionRegistry, getDescriptorForType(),
-          new MessageReflection.BuilderAdapter(this), tag);
-    }
-
     // ---------------------------------------------------------------
     // Reflection
 
@@ -2277,7 +2290,7 @@
       public Object getRepeatedRaw(Builder builder, int index) {
         return getRepeated(builder, index);
       }
-      
+
       @Override
       public void setRepeated(Builder builder, int index, Object value) {
         getMutableMapField(builder).getMutableList().set(index, coerceType((Message) value));
@@ -2678,7 +2691,7 @@
 
     return (Extension<MessageType, T>) extension;
   }
-  
+
   protected static int computeStringSize(final int fieldNumber, final Object value) {
     if (value instanceof String) {
       return CodedOutputStream.computeStringSize(fieldNumber, (String) value);
@@ -2686,7 +2699,7 @@
       return CodedOutputStream.computeBytesSize(fieldNumber, (ByteString) value);
     }
   }
-  
+
   protected static int computeStringSizeNoTag(final Object value) {
     if (value instanceof String) {
       return CodedOutputStream.computeStringSizeNoTag((String) value);
@@ -2694,7 +2707,7 @@
       return CodedOutputStream.computeBytesSizeNoTag((ByteString) value);
     }
   }
-  
+
   protected static void writeString(
       CodedOutputStream output, final int fieldNumber, final Object value) throws IOException {
     if (value instanceof String) {
@@ -2703,7 +2716,7 @@
       output.writeBytes(fieldNumber, (ByteString) value);
     }
   }
-  
+
   protected static void writeStringNoTag(
       CodedOutputStream output, final Object value) throws IOException {
     if (value instanceof String) {
diff --git a/java/core/src/main/java/com/google/protobuf/Internal.java b/java/core/src/main/java/com/google/protobuf/Internal.java
index 36bdece..848cad0 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -414,9 +414,8 @@
     }
   }
 
-  /**
-   * An empty byte array constant used in generated code.
-   */
+
+  /** An empty byte array constant used in generated code. */
   public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
 
   /**
diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index 55e33d2..510c6aa 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -50,6 +50,10 @@
     super(e.getMessage(), e);
   }
 
+  public InvalidProtocolBufferException(final String description, IOException e) {
+    super(description, e);
+  }
+
   /**
    * Attaches an unfinished message to the exception to support best-effort
    * parsing in {@code Parser} interface.
diff --git a/java/core/src/main/java/com/google/protobuf/MessageReflection.java b/java/core/src/main/java/com/google/protobuf/MessageReflection.java
index 3d73efb..69ad7dd 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageReflection.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageReflection.java
@@ -31,7 +31,6 @@
 package com.google.protobuf;
 
 import com.google.protobuf.Descriptors.FieldDescriptor;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -714,12 +713,14 @@
   }
 
   /**
-   * Parses a single field into MergeTarget. The target can be Message.Builder,
-   * FieldSet or MutableMessage.
+   * Parses a single field into MergeTarget. The target can be Message.Builder, FieldSet or
+   * MutableMessage.
    *
-   * Package-private because it is used by GeneratedMessage.ExtendableMessage.
+   * <p>Package-private because it is used by GeneratedMessage.ExtendableMessage.
    *
    * @param tag The tag, which should have already been read.
+   * @param unknownFields If not null, unknown fields will be merged to this {@link
+   *     UnknownFieldSet}, otherwise unknown fields will be discarded.
    * @return {@code true} unless the tag is an end-group tag.
    */
   static boolean mergeFieldFrom(
@@ -728,7 +729,8 @@
       ExtensionRegistryLite extensionRegistry,
       Descriptors.Descriptor type,
       MergeTarget target,
-      int tag) throws IOException {
+      int tag)
+      throws IOException {
     if (type.getOptions().getMessageSetWireFormat() &&
         tag == WireFormat.MESSAGE_SET_ITEM_TAG) {
       mergeMessageSetExtensionFromCodedStream(
@@ -792,7 +794,11 @@
     }
 
     if (unknown) {  // Unknown field or wrong wire type.  Skip.
-      return unknownFields.mergeFieldFrom(tag, input);
+      if (unknownFields != null) {
+        return unknownFields.mergeFieldFrom(tag, input);
+      } else {
+        return input.skipField(tag);
+      }
     }
 
     if (packed) {
@@ -844,7 +850,9 @@
             // If the number isn't recognized as a valid value for this enum,
             // drop it.
             if (value == null) {
-              unknownFields.mergeVarintField(fieldNumber, rawValue);
+              if (unknownFields != null) {
+                unknownFields.mergeVarintField(fieldNumber, rawValue);
+              }
               return true;
             }
           }
@@ -947,7 +955,7 @@
         mergeMessageSetExtensionFromBytes(
             rawBytes, extension, extensionRegistry, target);
       } else { // We don't know how to parse this. Ignore it.
-        if (rawBytes != null) {
+        if (rawBytes != null && unknownFields != null) {
           unknownFields.mergeField(typeId, UnknownFieldSet.Field.newBuilder()
               .addLengthDelimited(rawBytes).build());
         }
diff --git a/java/core/src/main/java/com/google/protobuf/TextFormat.java b/java/core/src/main/java/com/google/protobuf/TextFormat.java
index 53dead8..64094d0 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -34,7 +34,6 @@
 import com.google.protobuf.Descriptors.EnumDescriptor;
 import com.google.protobuf.Descriptors.EnumValueDescriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
-
 import java.io.IOException;
 import java.math.BigInteger;
 import java.nio.CharBuffer;
@@ -56,14 +55,7 @@
 public final class TextFormat {
   private TextFormat() {}
 
-  private static final Logger logger =
-      Logger.getLogger(TextFormat.class.getName());
-
-  private static final Printer DEFAULT_PRINTER = new Printer();
-  private static final Printer SINGLE_LINE_PRINTER =
-      (new Printer()).setSingleLineMode(true);
-  private static final Printer UNICODE_PRINTER =
-      (new Printer()).setEscapeNonAscii(false);
+  private static final Logger logger = Logger.getLogger(TextFormat.class.getName());
 
   /**
    * Outputs a textual representation of the Protocol Message supplied into
@@ -73,14 +65,14 @@
   public static void print(
       final MessageOrBuilder message, final Appendable output)
       throws IOException {
-    DEFAULT_PRINTER.print(message, new TextGenerator(output));
+    Printer.DEFAULT.print(message, multiLineOutput(output));
   }
 
   /** Outputs a textual representation of {@code fields} to {@code output}. */
   public static void print(final UnknownFieldSet fields,
                            final Appendable output)
                            throws IOException {
-    DEFAULT_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+    Printer.DEFAULT.printUnknownFields(fields, multiLineOutput(output));
   }
 
   /**
@@ -90,7 +82,7 @@
   public static void printUnicode(
       final MessageOrBuilder message, final Appendable output)
       throws IOException {
-    UNICODE_PRINTER.print(message, new TextGenerator(output));
+    Printer.UNICODE.print(message, multiLineOutput(output));
   }
 
   /**
@@ -100,7 +92,7 @@
   public static void printUnicode(final UnknownFieldSet fields,
                                   final Appendable output)
                                   throws IOException {
-    UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(output));
+    Printer.UNICODE.printUnknownFields(fields, multiLineOutput(output));
   }
 
   /**
@@ -109,10 +101,9 @@
    */
   public static String shortDebugString(final MessageOrBuilder message) {
     try {
-      final StringBuilder sb = new StringBuilder();
-      SINGLE_LINE_PRINTER.print(message, new TextGenerator(sb));
-      // Single line mode currently might have an extra space at the end.
-      return sb.toString().trim();
+      final StringBuilder text = new StringBuilder();
+      Printer.DEFAULT.print(message, singleLineOutput(text));
+      return text.toString();
     } catch (IOException e) {
       throw new IllegalStateException(e);
     }
@@ -125,11 +116,11 @@
   public static String shortDebugString(final FieldDescriptor field,
                                         final Object value) {
     try {
-      final StringBuilder sb = new StringBuilder();
-      SINGLE_LINE_PRINTER.printField(field, value, new TextGenerator(sb));
-      return sb.toString().trim();
+      final StringBuilder text = new StringBuilder();
+      Printer.DEFAULT.printField(field, value, singleLineOutput(text));
+      return text.toString();
     } catch (IOException e) {
-        throw new IllegalStateException(e);
+      throw new IllegalStateException(e);
     }
   }
 
@@ -139,10 +130,9 @@
    */
   public static String shortDebugString(final UnknownFieldSet fields) {
     try {
-      final StringBuilder sb = new StringBuilder();
-      SINGLE_LINE_PRINTER.printUnknownFields(fields, new TextGenerator(sb));
-      // Single line mode currently might have an extra space at the end.
-      return sb.toString().trim();
+      final StringBuilder text = new StringBuilder();
+      Printer.DEFAULT.printUnknownFields(fields, singleLineOutput(text));
+      return text.toString();
     } catch (IOException e) {
       throw new IllegalStateException(e);
     }
@@ -183,7 +173,7 @@
   public static String printToUnicodeString(final MessageOrBuilder message) {
     try {
       final StringBuilder text = new StringBuilder();
-      UNICODE_PRINTER.print(message, new TextGenerator(text));
+      Printer.UNICODE.print(message, multiLineOutput(text));
       return text.toString();
     } catch (IOException e) {
       throw new IllegalStateException(e);
@@ -197,7 +187,7 @@
   public static String printToUnicodeString(final UnknownFieldSet fields) {
     try {
       final StringBuilder text = new StringBuilder();
-      UNICODE_PRINTER.printUnknownFields(fields, new TextGenerator(text));
+      Printer.UNICODE.printUnknownFields(fields, multiLineOutput(text));
       return text.toString();
     } catch (IOException e) {
       throw new IllegalStateException(e);
@@ -208,7 +198,7 @@
                                 final Object value,
                                 final Appendable output)
                                 throws IOException {
-    DEFAULT_PRINTER.printField(field, value, new TextGenerator(output));
+    Printer.DEFAULT.printField(field, value, multiLineOutput(output));
   }
 
   public static String printFieldToString(final FieldDescriptor field,
@@ -223,6 +213,23 @@
   }
 
   /**
+   * Outputs a unicode textual representation of the value of given field value.
+   *
+   * <p>Same as {@code printFieldValue()}, except that non-ASCII characters in string type fields
+   * are not escaped in backslash+octals.
+   *
+   * @param field the descriptor of the field
+   * @param value the value of the field
+   * @param output the output to which to append the formatted value
+   * @throws ClassCastException if the value is not appropriate for the given field descriptor
+   * @throws IOException if there is an exception writing to the output
+   */
+  public static void printUnicodeFieldValue(
+      final FieldDescriptor field, final Object value, final Appendable output) throws IOException {
+    Printer.UNICODE.printFieldValue(field, value, multiLineOutput(output));
+  }
+
+  /**
    * Outputs a textual representation of the value of given field value.
    *
    * @param field the descriptor of the field
@@ -236,7 +243,7 @@
                                      final Object value,
                                      final Appendable output)
                                      throws IOException {
-    DEFAULT_PRINTER.printFieldValue(field, value, new TextGenerator(output));
+    Printer.DEFAULT.printFieldValue(field, value, multiLineOutput(output));
   }
 
   /**
@@ -253,7 +260,7 @@
                                             final Object value,
                                             final Appendable output)
                                             throws IOException {
-    printUnknownFieldValue(tag, value, new TextGenerator(output));
+    printUnknownFieldValue(tag, value, multiLineOutput(output));
   }
 
   private static void printUnknownFieldValue(final int tag,
@@ -277,7 +284,7 @@
         generator.print("\"");
         break;
       case WireFormat.WIRETYPE_START_GROUP:
-        DEFAULT_PRINTER.printUnknownFields((UnknownFieldSet) value, generator);
+        Printer.DEFAULT.printUnknownFields((UnknownFieldSet) value, generator);
         break;
       default:
         throw new IllegalArgumentException("Bad tag: " + tag);
@@ -286,24 +293,16 @@
 
   /** Helper class for converting protobufs to text. */
   private static final class Printer {
-    /** Whether to omit newlines from the output. */
-    boolean singleLineMode = false;
+    // Printer instance which escapes non-ASCII characters.
+    static final Printer DEFAULT = new Printer(true);
+    // Printer instance which emits Unicode (it still escapes newlines and quotes in strings).
+    static final Printer UNICODE = new Printer(false);
 
     /** Whether to escape non ASCII characters with backslash and octal. */
-    boolean escapeNonAscii = true;
+    private final boolean escapeNonAscii;
 
-    private Printer() {}
-
-    /** Setter of singleLineMode */
-    private Printer setSingleLineMode(boolean singleLineMode) {
-      this.singleLineMode = singleLineMode;
-      return this;
-    }
-
-    /** Setter of escapeNonAscii */
-    private Printer setEscapeNonAscii(boolean escapeNonAscii) {
+    private Printer(boolean escapeNonAscii) {
       this.escapeNonAscii = escapeNonAscii;
-      return this;
     }
 
     private void print(
@@ -355,12 +354,9 @@
       }
 
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        if (singleLineMode) {
-          generator.print(" { ");
-        } else {
-          generator.print(" {\n");
-          generator.indent();
-        }
+        generator.print(" {");
+        generator.eol();
+        generator.indent();
       } else {
         generator.print(": ");
       }
@@ -368,19 +364,10 @@
       printFieldValue(field, value, generator);
 
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        if (singleLineMode) {
-          generator.print("} ");
-        } else {
-          generator.outdent();
-          generator.print("}\n");
-        }
-      } else {
-        if (singleLineMode) {
-          generator.print(" ");
-        } else {
-          generator.print("\n");
-        }
+        generator.outdent();
+        generator.print("}");
       }
+      generator.eol();
     }
 
     private void printFieldValue(final FieldDescriptor field,
@@ -469,19 +456,13 @@
             field.getLengthDelimitedList(), generator);
         for (final UnknownFieldSet value : field.getGroupList()) {
           generator.print(entry.getKey().toString());
-          if (singleLineMode) {
-            generator.print(" { ");
-          } else {
-            generator.print(" {\n");
-            generator.indent();
-          }
+          generator.print(" {");
+          generator.eol();
+          generator.indent();
           printUnknownFields(value, generator);
-          if (singleLineMode) {
-            generator.print("} ");
-          } else {
-            generator.outdent();
-            generator.print("}\n");
-          }
+          generator.outdent();
+          generator.print("}");
+          generator.eol();
         }
       }
     }
@@ -495,7 +476,7 @@
         generator.print(String.valueOf(number));
         generator.print(": ");
         printUnknownFieldValue(wireType, value, generator);
-        generator.print(singleLineMode ? " " : "\n");
+        generator.eol();
       }
     }
   }
@@ -521,16 +502,29 @@
     }
   }
 
-  /**
+  private static TextGenerator multiLineOutput(Appendable output) {
+    return new TextGenerator(output, false);
+  }
+
+  private static TextGenerator singleLineOutput(Appendable output) {
+    return new TextGenerator(output, true);
+  }
+
+ /**
    * An inner class for writing text to the output stream.
    */
   private static final class TextGenerator {
     private final Appendable output;
     private final StringBuilder indent = new StringBuilder();
-    private boolean atStartOfLine = true;
+    private final boolean singleLineMode;
+    // While technically we are "at the start of a line" at the very beginning of the output, all
+    // we would do in response to this is emit the (zero length) indentation, so it has no effect.
+    // Setting it false here does however suppress an unwanted leading space in single-line mode.
+    private boolean atStartOfLine = false;
 
-    private TextGenerator(final Appendable output) {
+    private TextGenerator(final Appendable output, boolean singleLineMode) {
       this.output = output;
+      this.singleLineMode = singleLineMode;
     }
 
     /**
@@ -552,35 +546,31 @@
         throw new IllegalArgumentException(
             " Outdent() without matching Indent().");
       }
-      indent.delete(length - 2, length);
+      indent.setLength(length - 2);
     }
 
     /**
-     * Print text to the output stream.
+     * Print text to the output stream. Bare newlines are never expected to be passed to this
+     * method; to indicate the end of a line, call "eol()".
      */
     public void print(final CharSequence text) throws IOException {
-      final int size = text.length();
-      int pos = 0;
-
-      for (int i = 0; i < size; i++) {
-        if (text.charAt(i) == '\n') {
-          write(text.subSequence(pos, i + 1));
-          pos = i + 1;
-          atStartOfLine = true;
-        }
-      }
-      write(text.subSequence(pos, size));
-    }
-
-    private void write(final CharSequence data) throws IOException {
-      if (data.length() == 0) {
-        return;
-      }
       if (atStartOfLine) {
         atStartOfLine = false;
-        output.append(indent);
+        output.append(singleLineMode ? " " : indent);
       }
-      output.append(data);
+      output.append(text);
+    }
+
+    /**
+     * Signifies reaching the "end of the current line" in the output. In single-line mode, this
+     * does not result in a newline being emitted, but ensures that a separating space is written
+     * before the next output.
+     */
+    public void eol() throws IOException {
+      if (!singleLineMode) {
+        output.append("\n");
+      }
+      atStartOfLine = true;
     }
   }
 
@@ -1469,9 +1459,15 @@
             extensionRegistry, name.toString());
 
         if (extension == null) {
-          unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" +
-              (tokenizer.getPreviousColumn() + 1) + ":\t" +
-              type.getFullName() + ".[" + name + "]");
+          unknownFields.add(
+              (tokenizer.getPreviousLine() + 1)
+                  + ":"
+                  + (tokenizer.getPreviousColumn() + 1)
+                  + ":\t"
+                  + type.getFullName()
+                  + ".["
+                  + name
+                  + "]");
         } else {
           if (extension.descriptor.getContainingType() != type) {
             throw tokenizer.parseExceptionPreviousToken(
@@ -1506,9 +1502,14 @@
         }
 
         if (field == null) {
-          unknownFields.add((tokenizer.getPreviousLine() + 1) + ":" +
-              (tokenizer.getPreviousColumn() + 1) + ":\t" +
-              type.getFullName() + "." + name);
+          unknownFields.add(
+              (tokenizer.getPreviousLine() + 1)
+                  + ":"
+                  + (tokenizer.getPreviousColumn() + 1)
+                  + ":\t"
+                  + type.getFullName()
+                  + "."
+                  + name);
         }
       }
 
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
index d938113..37d6463 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -715,7 +715,7 @@
    * @see UnknownFieldSet
    */
   public static final class Field {
-    Field() {}
+    private Field() {}
 
     /** Construct a new {@link Builder}. */
     public static Builder newBuilder() {
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
index ca80d94..acc03a7 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -47,8 +47,29 @@
   private static final boolean HAS_UNSAFE_BYTEBUFFER_OPERATIONS =
       supportsUnsafeByteBufferOperations();
   private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArrayOperations();
-  private static final boolean HAS_UNSAFE_COPY_MEMORY = supportsUnsafeCopyMemory();
-  private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
+
+  private static final long BYTE_ARRAY_BASE_OFFSET = arrayBaseOffset(byte[].class);
+  // Micro-optimization: we can assume a scale of 1 and skip the multiply
+  // private static final long BYTE_ARRAY_INDEX_SCALE = 1;
+
+  private static final long BOOLEAN_ARRAY_BASE_OFFSET = arrayBaseOffset(boolean[].class);
+  private static final long BOOLEAN_ARRAY_INDEX_SCALE = arrayIndexScale(boolean[].class);
+
+  private static final long INT_ARRAY_BASE_OFFSET = arrayBaseOffset(int[].class);
+  private static final long INT_ARRAY_INDEX_SCALE = arrayIndexScale(int[].class);
+
+  private static final long LONG_ARRAY_BASE_OFFSET = arrayBaseOffset(long[].class);
+  private static final long LONG_ARRAY_INDEX_SCALE = arrayIndexScale(long[].class);
+
+  private static final long FLOAT_ARRAY_BASE_OFFSET = arrayBaseOffset(float[].class);
+  private static final long FLOAT_ARRAY_INDEX_SCALE = arrayIndexScale(float[].class);
+
+  private static final long DOUBLE_ARRAY_BASE_OFFSET = arrayBaseOffset(double[].class);
+  private static final long DOUBLE_ARRAY_INDEX_SCALE = arrayIndexScale(double[].class);
+
+  private static final long OBJECT_ARRAY_BASE_OFFSET = arrayBaseOffset(Object[].class);
+  private static final long OBJECT_ARRAY_INDEX_SCALE = arrayIndexScale(Object[].class);
+
   private static final long BUFFER_ADDRESS_OFFSET = fieldOffset(bufferAddressField());
 
   private UnsafeUtil() {}
@@ -57,10 +78,6 @@
     return HAS_UNSAFE_ARRAY_OPERATIONS;
   }
 
-  static boolean hasUnsafeCopyMemory() {
-    return HAS_UNSAFE_COPY_MEMORY;
-  }
-
   static boolean hasUnsafeByteBufferOperations() {
     return HAS_UNSAFE_BYTEBUFFER_OPERATIONS;
   }
@@ -69,8 +86,12 @@
     return MEMORY_ACCESSOR.objectFieldOffset(field);
   }
 
-  static long getArrayBaseOffset() {
-    return ARRAY_BASE_OFFSET;
+  private static int arrayBaseOffset(Class<?> clazz) {
+    return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayBaseOffset(clazz) : -1;
+  }
+
+  private static int arrayIndexScale(Class<?> clazz) {
+    return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayIndexScale(clazz) : -1;
   }
 
   static byte getByte(Object target, long offset) {
@@ -129,9 +150,82 @@
     MEMORY_ACCESSOR.putObject(target, offset, value);
   }
 
-  static void copyMemory(
-      Object src, long srcOffset, Object target, long targetOffset, long length) {
-    MEMORY_ACCESSOR.copyMemory(src, srcOffset, target, targetOffset, length);
+  static byte getByte(byte[] target, long index) {
+    return MEMORY_ACCESSOR.getByte(target, BYTE_ARRAY_BASE_OFFSET + index);
+  }
+
+  static void putByte(byte[] target, long index, byte value) {
+    MEMORY_ACCESSOR.putByte(target, BYTE_ARRAY_BASE_OFFSET + index, value);
+  }
+
+  static int getInt(int[] target, long index) {
+    return MEMORY_ACCESSOR.getInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE));
+  }
+
+  static void putInt(int[] target, long index, int value) {
+    MEMORY_ACCESSOR.putInt(target, INT_ARRAY_BASE_OFFSET + (index * INT_ARRAY_INDEX_SCALE), value);
+  }
+
+  static long getLong(long[] target, long index) {
+    return MEMORY_ACCESSOR.getLong(
+        target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE));
+  }
+
+  static void putLong(long[] target, long index, long value) {
+    MEMORY_ACCESSOR.putLong(
+        target, LONG_ARRAY_BASE_OFFSET + (index * LONG_ARRAY_INDEX_SCALE), value);
+  }
+
+  static boolean getBoolean(boolean[] target, long index) {
+    return MEMORY_ACCESSOR.getBoolean(
+        target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE));
+  }
+
+  static void putBoolean(boolean[] target, long index, boolean value) {
+    MEMORY_ACCESSOR.putBoolean(
+        target, BOOLEAN_ARRAY_BASE_OFFSET + (index * BOOLEAN_ARRAY_INDEX_SCALE), value);
+  }
+
+  static float getFloat(float[] target, long index) {
+    return MEMORY_ACCESSOR.getFloat(
+        target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE));
+  }
+
+  static void putFloat(float[] target, long index, float value) {
+    MEMORY_ACCESSOR.putFloat(
+        target, FLOAT_ARRAY_BASE_OFFSET + (index * FLOAT_ARRAY_INDEX_SCALE), value);
+  }
+
+  static double getDouble(double[] target, long index) {
+    return MEMORY_ACCESSOR.getDouble(
+        target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE));
+  }
+
+  static void putDouble(double[] target, long index, double value) {
+    MEMORY_ACCESSOR.putDouble(
+        target, DOUBLE_ARRAY_BASE_OFFSET + (index * DOUBLE_ARRAY_INDEX_SCALE), value);
+  }
+
+  static Object getObject(Object[] target, long index) {
+    return MEMORY_ACCESSOR.getObject(
+        target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE));
+  }
+
+  static void putObject(Object[] target, long index, Object value) {
+    MEMORY_ACCESSOR.putObject(
+        target, OBJECT_ARRAY_BASE_OFFSET + (index * OBJECT_ARRAY_INDEX_SCALE), value);
+  }
+
+  static void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+    MEMORY_ACCESSOR.copyMemory(src, srcIndex, targetOffset, length);
+  }
+
+  static void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+    MEMORY_ACCESSOR.copyMemory(srcOffset, target, targetIndex, length);
+  }
+
+  static void copyMemory(byte[] src, long srcIndex, byte[] target, long targetIndex, long length) {
+    System.arraycopy(src, (int) srcIndex, target, (int) targetIndex, (int) length); 
   }
 
   static byte getByte(long address) {
@@ -221,6 +315,7 @@
       Class<?> clazz = UNSAFE.getClass();
       clazz.getMethod("objectFieldOffset", Field.class);
       clazz.getMethod("arrayBaseOffset", Class.class);
+      clazz.getMethod("arrayIndexScale", Class.class);
       clazz.getMethod("getInt", Object.class, long.class);
       clazz.getMethod("putInt", Object.class, long.class, int.class);
       clazz.getMethod("getLong", Object.class, long.class);
@@ -245,27 +340,6 @@
     return false;
   }
 
-  /**
-   * Indicates whether or not unsafe copyMemory(object, long, object, long, long) operations are
-   * supported on this platform.
-   */
-  private static boolean supportsUnsafeCopyMemory() {
-    if (UNSAFE == null) {
-      return false;
-    }
-    try {
-      Class<?> clazz = UNSAFE.getClass();
-      clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
-
-      return true;
-    } catch (Throwable e) {
-      logger.log(
-          Level.WARNING,
-          "copyMemory is missing from platform - proto runtime falling back to safer methods.");
-    }
-    return false;
-  }
-
   private static boolean supportsUnsafeByteBufferOperations() {
     if (UNSAFE == null) {
       return false;
@@ -283,6 +357,7 @@
       clazz.getMethod("getLong", long.class);
       clazz.getMethod("putLong", long.class, long.class);
       clazz.getMethod("copyMemory", long.class, long.class, long.class);
+      clazz.getMethod("copyMemory", Object.class, long.class, Object.class, long.class, long.class);
       return true;
     } catch (Throwable e) {
       logger.log(
@@ -308,13 +383,6 @@
   }
 
   /**
-   * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsafe} is not available.
-   */
-  private static int byteArrayBaseOffset() {
-    return HAS_UNSAFE_ARRAY_OPERATIONS ? MEMORY_ACCESSOR.arrayBaseOffset(byte[].class) : -1;
-  }
-
-  /**
    * Returns the offset of the provided field, or {@code -1} if {@code sun.misc.Unsafe} is not
    * available.
    */
@@ -394,6 +462,10 @@
       return unsafe.arrayBaseOffset(clazz);
     }
 
+    public final int arrayIndexScale(Class<?> clazz) {
+      return unsafe.arrayIndexScale(clazz);
+    }
+
     public abstract byte getByte(long address);
 
     public abstract void putByte(long address, byte value);
@@ -408,10 +480,11 @@
 
     public abstract void copyMemory(long srcAddress, long targetAddress, long length);
 
-    public abstract void copyMemory(
-        Object src, long srcOffset, Object target, long targetOffset, long length);
-
     public abstract Object getStaticObject(Field field);
+    
+    public abstract void copyMemory(long srcOffset, byte[] target, long targetIndex, long length);
+    
+    public abstract void copyMemory(byte[] src, long srcIndex, long targetOffset, long length);
   }
 
   private static final class JvmMemoryAccessor extends MemoryAccessor {
@@ -491,15 +564,19 @@
     }
 
     @Override
-    public void copyMemory(
-        Object src, long srcOffset, Object target, long targetOffset, long length) {
-      unsafe.copyMemory(src, srcOffset, target, targetOffset, length);
-    }
-
-    @Override
     public void copyMemory(long srcAddress, long targetAddress, long length) {
       unsafe.copyMemory(srcAddress, targetAddress, length);
     }
+    
+    @Override 
+    public void copyMemory(long srcOffset, byte[] target, long targetIndex, long length) {
+      unsafe.copyMemory(null, srcOffset, target, BYTE_ARRAY_BASE_OFFSET + targetIndex, length);
+    }
+    
+    @Override
+    public void copyMemory(byte[] src, long srcIndex, long targetOffset, long length) {
+      unsafe.copyMemory(src, BYTE_ARRAY_BASE_OFFSET + srcIndex, null, targetOffset, length);
+    }
 
     @Override
     public Object getStaticObject(Field field) {
diff --git a/java/core/src/main/java/com/google/protobuf/Utf8.java b/java/core/src/main/java/com/google/protobuf/Utf8.java
index be7b746..1b13614 100644
--- a/java/core/src/main/java/com/google/protobuf/Utf8.java
+++ b/java/core/src/main/java/com/google/protobuf/Utf8.java
@@ -31,7 +31,6 @@
 package com.google.protobuf;
 
 import static com.google.protobuf.UnsafeUtil.addressOffset;
-import static com.google.protobuf.UnsafeUtil.getArrayBaseOffset;
 import static com.google.protobuf.UnsafeUtil.hasUnsafeArrayOperations;
 import static com.google.protobuf.UnsafeUtil.hasUnsafeByteBufferOperations;
 import static java.lang.Character.MAX_SURROGATE;
@@ -1001,8 +1000,8 @@
         throw new ArrayIndexOutOfBoundsException(
             String.format("Array length=%d, index=%d, limit=%d", bytes.length, index, limit));
       }
-      long offset = getArrayBaseOffset() + index;
-      final long offsetLimit = getArrayBaseOffset() + limit;
+      long offset = index;
+      final long offsetLimit = limit;
       if (state != COMPLETE) {
         // The previous decoding operation was incomplete (or malformed).
         // We look for a well-formed sequence consisting of bytes from
@@ -1187,7 +1186,7 @@
 
     @Override
     int encodeUtf8(final CharSequence in, final byte[] out, final int offset, final int length) {
-      long outIx = getArrayBaseOffset() + offset;
+      long outIx = offset;
       final long outLimit = outIx + length;
       final int inLimit = in.length();
       if (inLimit > length || out.length - length < offset) {
@@ -1204,7 +1203,7 @@
       }
       if (inIx == inLimit) {
         // We're done, it was ASCII encoded.
-        return (int) (outIx - getArrayBaseOffset());
+        return (int) outIx;
       }
 
       for (char c; inIx < inLimit; ++inIx) {
@@ -1243,7 +1242,7 @@
       }
 
       // All bytes have been encoded.
-      return (int) (outIx - getArrayBaseOffset());
+      return (int) outIx;
     }
 
     @Override
@@ -1321,31 +1320,17 @@
      */
     private static int unsafeEstimateConsecutiveAscii(
         byte[] bytes, long offset, final int maxChars) {
-      int remaining = maxChars;
-      if (remaining < UNSAFE_COUNT_ASCII_THRESHOLD) {
+      if (maxChars < UNSAFE_COUNT_ASCII_THRESHOLD) {
         // Don't bother with small strings.
         return 0;
       }
 
-      // Read bytes until 8-byte aligned so that we can read longs in the loop below.
-      // Byte arrays are already either 8 or 16-byte aligned, so we just need to make sure that
-      // the index (relative to the start of the array) is also 8-byte aligned. We do this by
-      // ANDing the index with 7 to determine the number of bytes that need to be read before
-      // we're 8-byte aligned.
-      final int unaligned = 8 - ((int) offset & 7);
-      for (int j = unaligned; j > 0; j--) {
+      for (int i = 0; i < maxChars; i++) {
         if (UnsafeUtil.getByte(bytes, offset++) < 0) {
-          return unaligned - j;
+          return i;
         }
       }
-
-      // This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
-      // To speed things up further, we're reading longs instead of bytes so we use a mask to
-      // determine if any byte in the current long is non-ASCII.
-      remaining -= unaligned;
-      for (; remaining >= 8 && (UnsafeUtil.getLong(bytes, offset) & ASCII_MASK_LONG) == 0;
-          offset += 8, remaining -= 8) {}
-      return maxChars - remaining;
+      return maxChars;
     }
 
     /**
@@ -1362,7 +1347,7 @@
       // Read bytes until 8-byte aligned so that we can read longs in the loop below.
       // We do this by ANDing the address with 7 to determine the number of bytes that need to
       // be read before we're 8-byte aligned.
-      final int unaligned = (int) address & 7;
+      final int unaligned = 8 - ((int) address & 7);
       for (int j = unaligned; j > 0; j--) {
         if (UnsafeUtil.getByte(address++) < 0) {
           return unaligned - j;
diff --git a/java/core/src/main/java/com/google/protobuf/WireFormat.java b/java/core/src/main/java/com/google/protobuf/WireFormat.java
index 0b0cdb7..8b837ee 100644
--- a/java/core/src/main/java/com/google/protobuf/WireFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/WireFormat.java
@@ -47,8 +47,10 @@
   // Do not allow instantiation.
   private WireFormat() {}
 
-  static final int FIXED_32_SIZE = 4;
-  static final int FIXED_64_SIZE = 8;
+  static final int FIXED32_SIZE = 4;
+  static final int FIXED64_SIZE = 8;
+  static final int MAX_VARINT32_SIZE = 5;
+  static final int MAX_VARINT64_SIZE = 10;
   static final int MAX_VARINT_SIZE = 10;
 
   public static final int WIRETYPE_VARINT           = 0;
diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index e440c7d..da2c067 100644
--- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -41,6 +41,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import junit.framework.TestCase;
 
 /**
@@ -613,6 +614,82 @@
       checkSizeLimitExceeded(expected);
     }
   }
+  
+  public void testRefillBufferWithCorrectSize() throws Exception {
+    // NOTE: refillBuffer only applies to the stream-backed CIS.
+    byte[] bytes = "123456789".getBytes("UTF-8");
+    ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.writeRawByte(4);
+    output.flush();
+
+    // Input is two string with length 9 and one raw byte.
+    byte[] rawInput = rawOutput.toByteArray(); 
+    for (int inputStreamBufferLength = 8; 
+        inputStreamBufferLength <= rawInput.length + 1; inputStreamBufferLength++) {
+      CodedInputStream input = CodedInputStream.newInstance(
+              new ByteArrayInputStream(rawInput), inputStreamBufferLength);
+      input.setSizeLimit(rawInput.length - 1);
+      input.readString();
+      input.readString(); 
+      try {
+        input.readRawByte(); // Hits limit.
+        fail("Should have thrown an exception!");
+      } catch (InvalidProtocolBufferException expected) {
+        checkSizeLimitExceeded(expected);
+      }
+    }
+  }
+
+  public void testIsAtEnd() throws Exception {
+    CodedInputStream input = CodedInputStream.newInstance(
+        new ByteArrayInputStream(new byte[5]));
+    try {   
+      for (int i = 0; i < 5; i++) {
+        assertEquals(false, input.isAtEnd());
+        input.readRawByte();
+      }
+      assertEquals(true, input.isAtEnd());
+    } catch (Exception e) {
+      fail("Catch exception in the testIsAtEnd");
+    }
+  }
+
+  public void testCurrentLimitExceeded() throws Exception {
+    byte[] bytes = "123456789".getBytes("UTF-8");
+    ByteArrayOutputStream rawOutput = new ByteArrayOutputStream();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput, bytes.length);
+
+    int tag = WireFormat.makeTag(1, WireFormat.WIRETYPE_LENGTH_DELIMITED);
+    output.writeRawVarint32(tag);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.flush();
+
+    byte[] rawInput = rawOutput.toByteArray();
+    CodedInputStream input = CodedInputStream.newInstance(
+              new ByteArrayInputStream(rawInput));
+    // The length of the whole rawInput
+    input.setSizeLimit(11);
+    // Some number that is smaller than the rawInput's length
+    // but larger than 2 
+    input.pushLimit(5);
+    try {
+      input.readString();
+      fail("Should have thrown an exception");
+    } catch (InvalidProtocolBufferException expected) {
+      assertEquals(expected.getMessage(), 
+          InvalidProtocolBufferException.truncatedMessage().getMessage());
+    }
+  }
 
   public void testSizeLimitMultipleMessages() throws Exception {
     // NOTE: Size limit only applies to the stream-backed CIS.
@@ -807,6 +884,52 @@
     }
   }
 
+  public void testReadLargeByteStringFromInputStream() throws Exception {
+    byte[] bytes = new byte[1024 * 1024];
+    for (int i = 0; i < bytes.length; i++) {
+      bytes[i] = (byte) (i & 0xFF);
+    }
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.flush();
+    byte[] data = rawOutput.toByteString().toByteArray();
+
+    CodedInputStream input = CodedInputStream.newInstance(
+        new ByteArrayInputStream(data) {
+          @Override
+          public synchronized int available() {
+            return 0;
+          }
+        });
+    ByteString result = input.readBytes();
+    assertEquals(ByteString.copyFrom(bytes), result);
+  }
+
+  public void testReadLargeByteArrayFromInputStream() throws Exception {
+    byte[] bytes = new byte[1024 * 1024];
+    for (int i = 0; i < bytes.length; i++) {
+      bytes[i] = (byte) (i & 0xFF);
+    }
+    ByteString.Output rawOutput = ByteString.newOutput();
+    CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
+    output.writeRawVarint32(bytes.length);
+    output.writeRawBytes(bytes);
+    output.flush();
+    byte[] data = rawOutput.toByteString().toByteArray();
+
+    CodedInputStream input = CodedInputStream.newInstance(
+        new ByteArrayInputStream(data) {
+          @Override
+          public synchronized int available() {
+            return 0;
+          }
+        });
+    byte[] result = input.readByteArray();
+    assertTrue(Arrays.equals(bytes, result));
+  }
+
   public void testReadByteBuffer() throws Exception {
     ByteString.Output rawOutput = ByteString.newOutput();
     CodedOutputStream output = CodedOutputStream.newInstance(rawOutput);
diff --git a/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java b/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java
new file mode 100644
index 0000000..0f09a51
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java
@@ -0,0 +1,157 @@
+// 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.
+
+package com.google.protobuf;
+
+import static org.junit.Assert.assertEquals;
+
+import protobuf_unittest.UnittestProto;
+import proto3_unittest.UnittestProto3;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for discard or preserve unknown fields. */
+@RunWith(JUnit4.class)
+public class DiscardUnknownFieldsTest {
+  @Test
+  public void testProto2() throws Exception {
+    testProto2Message(
+          UnittestProto.TestEmptyMessage.getDefaultInstance());
+    testProto2Message(
+          UnittestProto.TestEmptyMessageWithExtensions.getDefaultInstance());
+    testProto2Message(
+          DynamicMessage.getDefaultInstance(UnittestProto.TestEmptyMessage.getDescriptor()));
+    testProto2Message(
+          DynamicMessage.getDefaultInstance(
+              UnittestProto.TestEmptyMessageWithExtensions.getDescriptor()));
+  }
+
+  @Test
+  public void testProto3() throws Exception {
+    testProto3Message(UnittestProto3.TestEmptyMessage.getDefaultInstance());
+    testProto3Message(
+        DynamicMessage.getDefaultInstance(UnittestProto3.TestEmptyMessage.getDescriptor()));
+  }
+
+  private static void testProto2Message(Message message) throws Exception {
+    assertUnknownFieldsDefaultPreserved(message);
+    assertUnknownFieldsExplicitlyDiscarded(message);
+    assertReuseCodedInputStreamPreserve(message);
+    assertUnknownFieldsInUnknownFieldSetArePreserve(message);
+  }
+
+  private static void testProto3Message(Message message) throws Exception {
+    CodedInputStream.setProto3KeepUnknownsByDefaultForTest();
+    assertUnknownFieldsDefaultPreserved(message);
+    assertUnknownFieldsExplicitlyDiscarded(message);
+    assertReuseCodedInputStreamPreserve(message);
+    assertUnknownFieldsInUnknownFieldSetArePreserve(message);
+    CodedInputStream.setProto3DiscardUnknownsByDefaultForTest();
+    assertUnknownFieldsDefaultDiscarded(message);
+    assertUnknownFieldsExplicitlyDiscarded(message);
+    assertUnknownFieldsInUnknownFieldSetAreDiscarded(message);
+  }
+
+  private static void assertReuseCodedInputStreamPreserve(Message message) throws Exception {
+    final int messageSize = payload.size();
+    byte[] copied = new byte[messageSize * 2];
+    payload.copyTo(copied, 0);
+    payload.copyTo(copied, messageSize);
+    CodedInputStream input = CodedInputStream.newInstance(copied);
+    {
+      // Use DiscardUnknownFieldsParser to parse the first payload.
+      int oldLimit = input.pushLimit(messageSize);
+      Message parsed = DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(input);
+      assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
+      input.popLimit(oldLimit);
+    }
+    {
+      // Use the normal parser to parse the remaining payload should have unknown fields preserved.
+      Message parsed = message.getParserForType().parseFrom(input);
+      assertEquals(message.getClass().getName(), payload, parsed.toByteString());
+    }
+  }
+
+  /**
+   * {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link
+   * Message.Builder#mergeUnknownFields(UnknownFieldSet)} should preserve the unknown fields.
+   */
+  private static void assertUnknownFieldsInUnknownFieldSetArePreserve(Message message)
+      throws Exception {
+    UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build();
+    Message built = message.newBuilderForType().setUnknownFields(unknownFields).build();
+    assertEquals(message.getClass().getName(), payload, built.toByteString());
+
+  }
+  /**
+   * {@link Message.Builder#setUnknownFields(UnknownFieldSet)} and {@link
+   * Message.Builder#mergeUnknownFields(UnknownFieldSet)} should discard the unknown fields.
+   */
+  private static void assertUnknownFieldsInUnknownFieldSetAreDiscarded(Message message)
+      throws Exception {
+    UnknownFieldSet unknownFields = UnknownFieldSet.newBuilder().mergeFrom(payload).build();
+    Message built = message.newBuilderForType().setUnknownFields(unknownFields).build();
+    assertEquals(message.getClass().getName(), 0, built.getSerializedSize());
+  }
+
+  private static void assertUnknownFieldsDefaultPreserved(MessageLite message) throws Exception {
+    {
+      MessageLite parsed = message.getParserForType().parseFrom(payload);
+      assertEquals(message.getClass().getName(), payload, parsed.toByteString());
+    }
+
+    {
+      MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
+      assertEquals(message.getClass().getName(), payload, parsed.toByteString());
+    }
+  }
+
+  private static void assertUnknownFieldsDefaultDiscarded(MessageLite message) throws Exception {
+    {
+      MessageLite parsed = message.getParserForType().parseFrom(payload);
+      assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
+    }
+
+    {
+      MessageLite parsed = message.newBuilderForType().mergeFrom(payload).build();
+      assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
+    }
+  }
+
+  private static void assertUnknownFieldsExplicitlyDiscarded(Message message) throws Exception {
+    Message parsed =
+        DiscardUnknownFieldsParser.wrap(message.getParserForType()).parseFrom(payload);
+    assertEquals(message.getClass().getName(), 0, parsed.getSerializedSize());
+  }
+
+  private static final ByteString payload =
+      TestUtilLite.getAllLiteSetBuilder().build().toByteString();
+}
diff --git a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
index 4a42c89..ff686a0 100644
--- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -108,7 +108,7 @@
     assertFalse(TestAllTypes.newBuilder().build().hasOptionalNestedMessage());
     assertFalse(TestAllTypes.newBuilder().hasOptionalNestedMessage());
 
-    // oneof fields don't have hasFoo() methods (even for message types).
+    // oneof fields don't have hasFoo() methods for non-message types.
     assertHasMethodRemoved(
         UnittestProto.TestAllTypes.class,
         TestAllTypes.class,
@@ -121,10 +121,8 @@
         UnittestProto.TestAllTypes.class,
         TestAllTypes.class,
         "OneofBytes");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.class,
-        TestAllTypes.class,
-        "OneofNestedMessage");
+    assertFalse(TestAllTypes.newBuilder().build().hasOneofNestedMessage());
+    assertFalse(TestAllTypes.newBuilder().hasOneofNestedMessage());
 
     assertHasMethodRemoved(
         UnittestProto.TestAllTypes.Builder.class,
@@ -138,10 +136,6 @@
         UnittestProto.TestAllTypes.Builder.class,
         TestAllTypes.Builder.class,
         "OneofBytes");
-    assertHasMethodRemoved(
-        UnittestProto.TestAllTypes.Builder.class,
-        TestAllTypes.Builder.class,
-        "OneofNestedMessage");
   }
 
   public void testOneofEquals() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 3eece26..a4311d1 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -923,15 +923,9 @@
   }
 
   public void testEnumValues() {
-     assertEquals(
-         TestAllTypes.NestedEnum.BAR.getNumber(),
-         TestAllTypes.NestedEnum.BAR_VALUE);
-    assertEquals(
-        TestAllTypes.NestedEnum.BAZ.getNumber(),
-        TestAllTypes.NestedEnum.BAZ_VALUE);
-    assertEquals(
-        TestAllTypes.NestedEnum.FOO.getNumber(),
-        TestAllTypes.NestedEnum.FOO_VALUE);
+    assertEquals(TestAllTypes.NestedEnum.BAR_VALUE, TestAllTypes.NestedEnum.BAR.getNumber());
+    assertEquals(TestAllTypes.NestedEnum.BAZ_VALUE, TestAllTypes.NestedEnum.BAZ.getNumber());
+    assertEquals(TestAllTypes.NestedEnum.FOO_VALUE, TestAllTypes.NestedEnum.FOO.getNumber());
   }
 
   public void testNonNestedExtensionInitialization() {
@@ -1319,51 +1313,51 @@
       assertFalse(builder.clearFooInt().hasFooInt());
       TestOneof2 message2 = builder.build();
       assertFalse(message2.hasFooInt());
-      assertEquals(message2.getFooInt(), 0);
+      assertEquals(0, message2.getFooInt());
     }
 
     // Enum
     {
       TestOneof2.Builder builder = TestOneof2.newBuilder();
-      assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.FOO);
+      assertEquals(TestOneof2.NestedEnum.FOO, builder.getFooEnum());
       assertTrue(builder.setFooEnum(TestOneof2.NestedEnum.BAR).hasFooEnum());
-      assertEquals(builder.getFooEnum(), TestOneof2.NestedEnum.BAR);
+      assertEquals(TestOneof2.NestedEnum.BAR, builder.getFooEnum());
       TestOneof2 message = builder.buildPartial();
       assertTrue(message.hasFooEnum());
-      assertEquals(message.getFooEnum(), TestOneof2.NestedEnum.BAR);
+      assertEquals(TestOneof2.NestedEnum.BAR, message.getFooEnum());
 
       assertFalse(builder.clearFooEnum().hasFooEnum());
       TestOneof2 message2 = builder.build();
       assertFalse(message2.hasFooEnum());
-      assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.FOO);
+      assertEquals(TestOneof2.NestedEnum.FOO, message2.getFooEnum());
     }
 
     // String
     {
       TestOneof2.Builder builder = TestOneof2.newBuilder();
-      assertEquals(builder.getFooString(), "");
+      assertEquals("", builder.getFooString());
       builder.setFooString("foo");
       assertTrue(builder.hasFooString());
-      assertEquals(builder.getFooString(), "foo");
+      assertEquals("foo", builder.getFooString());
       TestOneof2 message = builder.buildPartial();
       assertTrue(message.hasFooString());
-      assertEquals(message.getFooString(), "foo");
+      assertEquals("foo", message.getFooString());
       assertEquals(message.getFooStringBytes(), TestUtil.toBytes("foo"));
 
       assertFalse(builder.clearFooString().hasFooString());
       TestOneof2 message2 = builder.buildPartial();
       assertFalse(message2.hasFooString());
-      assertEquals(message2.getFooString(), "");
+      assertEquals("", message2.getFooString());
       assertEquals(message2.getFooStringBytes(), TestUtil.toBytes(""));
 
       // Get method should not change the oneof value.
       builder.setFooInt(123);
-      assertEquals(builder.getFooString(), "");
+      assertEquals("", builder.getFooString());
       assertEquals(builder.getFooStringBytes(), TestUtil.toBytes(""));
       assertEquals(123, builder.getFooInt());
 
       message = builder.build();
-      assertEquals(message.getFooString(), "");
+      assertEquals("", message.getFooString());
       assertEquals(message.getFooStringBytes(), TestUtil.toBytes(""));
       assertEquals(123, message.getFooInt());
     }
@@ -1371,38 +1365,38 @@
     // Cord
     {
       TestOneof2.Builder builder = TestOneof2.newBuilder();
-      assertEquals(builder.getFooCord(), "");
+      assertEquals("", builder.getFooCord());
       builder.setFooCord("foo");
       assertTrue(builder.hasFooCord());
-      assertEquals(builder.getFooCord(), "foo");
+      assertEquals("foo", builder.getFooCord());
       TestOneof2 message = builder.buildPartial();
       assertTrue(message.hasFooCord());
-      assertEquals(message.getFooCord(), "foo");
+      assertEquals("foo", message.getFooCord());
       assertEquals(message.getFooCordBytes(), TestUtil.toBytes("foo"));
 
       assertFalse(builder.clearFooCord().hasFooCord());
       TestOneof2 message2 = builder.build();
       assertFalse(message2.hasFooCord());
-      assertEquals(message2.getFooCord(), "");
+      assertEquals("", message2.getFooCord());
       assertEquals(message2.getFooCordBytes(), TestUtil.toBytes(""));
     }
 
     // StringPiece
     {
       TestOneof2.Builder builder = TestOneof2.newBuilder();
-      assertEquals(builder.getFooStringPiece(), "");
+      assertEquals("", builder.getFooStringPiece());
       builder.setFooStringPiece("foo");
       assertTrue(builder.hasFooStringPiece());
-      assertEquals(builder.getFooStringPiece(), "foo");
+      assertEquals("foo", builder.getFooStringPiece());
       TestOneof2 message = builder.buildPartial();
       assertTrue(message.hasFooStringPiece());
-      assertEquals(message.getFooStringPiece(), "foo");
+      assertEquals("foo", message.getFooStringPiece());
       assertEquals(message.getFooStringPieceBytes(), TestUtil.toBytes("foo"));
 
       assertFalse(builder.clearFooStringPiece().hasFooStringPiece());
       TestOneof2 message2 = builder.build();
       assertFalse(message2.hasFooStringPiece());
-      assertEquals(message2.getFooStringPiece(), "");
+      assertEquals("", message2.getFooStringPiece());
       assertEquals(message2.getFooStringPieceBytes(), TestUtil.toBytes(""));
     }
 
@@ -1410,20 +1404,20 @@
     {
       // set
       TestOneof2.Builder builder = TestOneof2.newBuilder();
-      assertEquals(builder.getFooMessage().getQuxInt(), 0);
+      assertEquals(0, builder.getFooMessage().getQuxInt());
       builder.setFooMessage(
           TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build());
       assertTrue(builder.hasFooMessage());
-      assertEquals(builder.getFooMessage().getQuxInt(), 234);
+      assertEquals(234, builder.getFooMessage().getQuxInt());
       TestOneof2 message = builder.buildPartial();
       assertTrue(message.hasFooMessage());
-      assertEquals(message.getFooMessage().getQuxInt(), 234);
+      assertEquals(234, message.getFooMessage().getQuxInt());
 
       // clear
       assertFalse(builder.clearFooMessage().hasFooString());
       message = builder.build();
       assertFalse(message.hasFooMessage());
-      assertEquals(message.getFooMessage().getQuxInt(), 0);
+      assertEquals(0, message.getFooMessage().getQuxInt());
 
       // nested builder
       builder = TestOneof2.newBuilder();
@@ -1432,10 +1426,10 @@
       assertFalse(builder.hasFooMessage());
       builder.getFooMessageBuilder().setQuxInt(123);
       assertTrue(builder.hasFooMessage());
-      assertEquals(builder.getFooMessage().getQuxInt(), 123);
+      assertEquals(123, builder.getFooMessage().getQuxInt());
       message = builder.build();
       assertTrue(message.hasFooMessage());
-      assertEquals(message.getFooMessage().getQuxInt(), 123);
+      assertEquals(123, message.getFooMessage().getQuxInt());
     }
 
     // LazyMessage is tested in LazyMessageLiteTest.java
@@ -1448,7 +1442,7 @@
       TestOneof2 message = builder.setFooInt(123).build();
       TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
       assertTrue(message2.hasFooInt());
-      assertEquals(message2.getFooInt(), 123);
+      assertEquals(123, message2.getFooInt());
     }
 
     // String
@@ -1457,7 +1451,7 @@
       TestOneof2 message = builder.setFooString("foo").build();
       TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
       assertTrue(message2.hasFooString());
-      assertEquals(message2.getFooString(), "foo");
+      assertEquals("foo", message2.getFooString());
     }
 
     // Enum
@@ -1466,7 +1460,7 @@
       TestOneof2 message = builder.setFooEnum(TestOneof2.NestedEnum.BAR).build();
       TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
       assertTrue(message2.hasFooEnum());
-      assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+      assertEquals(TestOneof2.NestedEnum.BAR, message2.getFooEnum());
     }
 
     // Message
@@ -1476,7 +1470,7 @@
           TestOneof2.NestedMessage.newBuilder().setQuxInt(234).build()).build();
       TestOneof2 message2 = TestOneof2.newBuilder().mergeFrom(message).build();
       assertTrue(message2.hasFooMessage());
-      assertEquals(message2.getFooMessage().getQuxInt(), 234);
+      assertEquals(234, message2.getFooMessage().getQuxInt());
     }
   }
 
@@ -1488,7 +1482,7 @@
       ByteString serialized = message.toByteString();
       TestOneof2 message2 = TestOneof2.parseFrom(serialized);
       assertTrue(message2.hasFooInt());
-      assertEquals(message2.getFooInt(), 123);
+      assertEquals(123, message2.getFooInt());
     }
 
     // String
@@ -1498,7 +1492,7 @@
       ByteString serialized = message.toByteString();
       TestOneof2 message2 = TestOneof2.parseFrom(serialized);
       assertTrue(message2.hasFooString());
-      assertEquals(message2.getFooString(), "foo");
+      assertEquals("foo", message2.getFooString());
     }
 
     // Enum
@@ -1508,7 +1502,7 @@
       ByteString serialized = message.toByteString();
       TestOneof2 message2 = TestOneof2.parseFrom(serialized);
       assertTrue(message2.hasFooEnum());
-      assertEquals(message2.getFooEnum(), TestOneof2.NestedEnum.BAR);
+      assertEquals(TestOneof2.NestedEnum.BAR, message2.getFooEnum());
     }
 
     // Message
@@ -1519,7 +1513,7 @@
       ByteString serialized = message.toByteString();
       TestOneof2 message2 = TestOneof2.parseFrom(serialized);
       assertTrue(message2.hasFooMessage());
-      assertEquals(message2.getFooMessage().getQuxInt(), 234);
+      assertEquals(234, message2.getFooMessage().getQuxInt());
     }
   }
 
diff --git a/java/core/src/test/java/com/google/protobuf/LiteTest.java b/java/core/src/test/java/com/google/protobuf/LiteTest.java
index 98c637a..ba8bcb1 100644
--- a/java/core/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LiteTest.java
@@ -33,6 +33,7 @@
 import static java.util.Collections.emptyList;
 import static java.util.Collections.singletonList;
 
+import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
 import com.google.protobuf.UnittestImportLite.ImportEnumLite;
 import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
@@ -52,7 +53,12 @@
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
+import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
 import junit.framework.TestCase;
 
 /**
@@ -155,6 +161,31 @@
       // expected.
     }
   }
+
+  public void testMemoization() throws Exception {
+    TestAllExtensionsLite message = TestUtilLite.getAllLiteExtensionsSet();
+
+    // Test serialized size is memoized
+    message.memoizedSerializedSize = -1;
+    int size = message.getSerializedSize();
+    assertTrue(size > 0);
+    assertEquals(size, message.memoizedSerializedSize);
+
+    // Test hashCode is memoized
+    assertEquals(0, message.memoizedHashCode);
+    int hashCode = message.hashCode();
+    assertTrue(hashCode != 0);
+    assertEquals(hashCode, message.memoizedHashCode);
+
+    // Test isInitialized is memoized
+    Field memo = message.getClass().getDeclaredField("memoizedIsInitialized");
+    memo.setAccessible(true);
+    memo.set(message, (byte) -1);
+    boolean initialized = message.isInitialized();
+    assertTrue(initialized);
+    // We have to cast to Byte first. Casting to byte causes a type error
+    assertEquals(1, ((Byte) memo.get(message)).intValue());
+  }
   
   public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
     // Since builders are implemented as a thin wrapper around a message
@@ -2378,4 +2409,187 @@
           expected.getUnfinishedMessage());
     }
   }
+
+  // Make sure we haven't screwed up the code generation for packing fields by default.
+  public void testPackedSerialization() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    builder.addRepeatedInt32(4321);
+    builder.addRepeatedNestedEnum(TestAllTypes.NestedEnum.BAZ);
+    TestAllTypes message = builder.build();
+
+    CodedInputStream in = CodedInputStream.newInstance(message.toByteArray());
+
+    while (!in.isAtEnd()) {
+      int tag = in.readTag();
+      assertEquals(WireFormat.WIRETYPE_LENGTH_DELIMITED, WireFormat.getTagWireType(tag));
+      in.skipField(tag);
+    }
+  }
+
+  public void testAddAllIteratesOnce() {
+    TestAllTypesLite message =
+        TestAllTypesLite.newBuilder()
+            .addAllRepeatedBool(new OneTimeIterableList(false))
+            .addAllRepeatedInt32(new OneTimeIterableList(0))
+            .addAllRepeatedInt64(new OneTimeIterableList(0L))
+            .addAllRepeatedFloat(new OneTimeIterableList(0f))
+            .addAllRepeatedDouble(new OneTimeIterableList(0d))
+            .addAllRepeatedBytes(new OneTimeIterableList(ByteString.EMPTY))
+            .addAllRepeatedString(new OneTimeIterableList(""))
+            .addAllRepeatedNestedMessage(
+                new OneTimeIterableList(NestedMessage.getDefaultInstance()))
+            .addAllRepeatedBool(new OneTimeIterable(false))
+            .addAllRepeatedInt32(new OneTimeIterable(0))
+            .addAllRepeatedInt64(new OneTimeIterable(0L))
+            .addAllRepeatedFloat(new OneTimeIterable(0f))
+            .addAllRepeatedDouble(new OneTimeIterable(0d))
+            .addAllRepeatedBytes(new OneTimeIterable(ByteString.EMPTY))
+            .addAllRepeatedString(new OneTimeIterable(""))
+            .addAllRepeatedNestedMessage(new OneTimeIterable(NestedMessage.getDefaultInstance()))
+            .build();
+  }
+
+  public void testAddAllIteratesOnce_throwsOnNull() {
+    TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder();
+    try {
+      builder.addAllRepeatedBool(new OneTimeIterableList(true, false, (Boolean) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 2 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedBoolCount());
+    }
+
+    try {
+      builder.addAllRepeatedBool(new OneTimeIterable(true, false, (Boolean) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 2 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedBoolCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedBool(new OneTimeIterableList((Boolean) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedBoolCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedInt32(new OneTimeIterableList((Integer) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedInt32Count());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedInt64(new OneTimeIterableList((Long) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedInt64Count());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedFloat(new OneTimeIterableList((Float) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedFloatCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedDouble(new OneTimeIterableList((Double) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedDoubleCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedBytes(new OneTimeIterableList((ByteString) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedBytesCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedString(new OneTimeIterableList("", "", (String) null, ""));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 2 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedStringCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedString(new OneTimeIterable("", "", (String) null, ""));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 2 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedStringCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedString(new OneTimeIterableList((String) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedStringCount());
+    }
+
+    try {
+      builder = TestAllTypesLite.newBuilder();
+      builder.addAllRepeatedNestedMessage(new OneTimeIterableList((NestedMessage) null));
+      fail();
+    } catch (NullPointerException expected) {
+      assertEquals("Element at index 0 is null.", expected.getMessage());
+      assertEquals(0, builder.getRepeatedNestedMessageCount());
+    }
+  }
+
+  private static final class OneTimeIterableList<T> extends ArrayList<T> {
+    private boolean wasIterated = false;
+
+    OneTimeIterableList(T... contents) {
+      addAll(Arrays.asList(contents));
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+      if (wasIterated) {
+        fail();
+      }
+      wasIterated = true;
+      return super.iterator();
+    }
+  }
+
+  private static final class OneTimeIterable<T> implements Iterable<T> {
+    private final List<T> list;
+    private boolean wasIterated = false;
+
+    OneTimeIterable(T... contents) {
+      list = Arrays.asList(contents);
+    }
+
+    @Override
+    public Iterator<T> iterator() {
+      if (wasIterated) {
+        fail();
+      }
+      wasIterated = true;
+      return list.iterator();
+    }
+  }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
index 0a14f58..da9195f 100644
--- a/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java
@@ -408,12 +408,12 @@
     TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToInt32Field(5, bytes)
         .build());
-    assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
+    assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
 
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToStringField(stringKey, 5)
         .build());
-    assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
+    assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
 
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToBytesField(stringKey, 5)
@@ -423,7 +423,7 @@
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToEnumField(stringKey, bytes)
         .build());
-    assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
+    assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
 
     try {
       tryParseTestMap(BizarroTestMap.newBuilder()
@@ -439,7 +439,7 @@
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putStringToInt32Field(stringKey, bytes)
         .build());
-    assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
+    assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
   }
 
   public void testMergeFrom() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
index 453d392..37827f7 100644
--- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -546,12 +546,12 @@
     TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToInt32Field(5, bytes)
         .build());
-    assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
+    assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
 
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToStringField(stringKey, 5)
         .build());
-    assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
+    assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
 
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToBytesField(stringKey, 5)
@@ -561,7 +561,7 @@
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToEnumField(stringKey, bytes)
         .build());
-    assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
+    assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
 
     try {
       tryParseTestMap(BizarroTestMap.newBuilder()
@@ -577,7 +577,7 @@
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putStringToInt32Field(stringKey, bytes)
         .build());
-    assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
+    assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
   }
 
   public void testMergeFrom() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java
index 4501953..64ae443 100644
--- a/java/core/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -576,12 +576,12 @@
     TestMap map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToInt32Field(5, bytes)
         .build());
-    assertEquals(map.getInt32ToInt32FieldOrDefault(5, -1), 0);
+    assertEquals(0, map.getInt32ToInt32FieldOrDefault(5, -1));
 
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToStringField(stringKey, 5)
         .build());
-    assertEquals(map.getInt32ToStringFieldOrDefault(0, null), "");
+    assertEquals("", map.getInt32ToStringFieldOrDefault(0, null));
 
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToBytesField(stringKey, 5)
@@ -591,7 +591,7 @@
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putInt32ToEnumField(stringKey, bytes)
         .build());
-    assertEquals(map.getInt32ToEnumFieldOrDefault(0, null), TestMap.EnumValue.FOO);
+    assertEquals(TestMap.EnumValue.FOO, map.getInt32ToEnumFieldOrDefault(0, null));
 
     try {
       tryParseTestMap(BizarroTestMap.newBuilder()
@@ -607,7 +607,7 @@
     map = tryParseTestMap(BizarroTestMap.newBuilder()
         .putStringToInt32Field(stringKey, bytes)
         .build());
-    assertEquals(map.getStringToInt32FieldOrDefault(stringKey, -1), 0);
+    assertEquals(0, map.getStringToInt32FieldOrDefault(stringKey, -1));
   }
 
   public void testMergeFrom() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/MessageTest.java b/java/core/src/test/java/com/google/protobuf/MessageTest.java
index 75b79a3..9d55d0d 100644
--- a/java/core/src/test/java/com/google/protobuf/MessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MessageTest.java
@@ -321,8 +321,10 @@
 
     assertTrue(result.getField(result.getDescriptorForType()
         .findFieldByName("repeated_foreign_message")) instanceof List<?>);
-    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
-        .findFieldByName("repeated_foreign_message")), 0);
+    assertEquals(
+        0,
+        result.getRepeatedFieldCount(
+            result.getDescriptorForType().findFieldByName("repeated_foreign_message")));
   }
   
   /** Test reading repeated message from DynamicMessage. */
@@ -345,7 +347,9 @@
 
     assertTrue(result.getField(result.getDescriptorForType()
         .findFieldByName("repeated_foreign_message")) instanceof List<?>);
-    assertEquals(result.getRepeatedFieldCount(result.getDescriptorForType()
-        .findFieldByName("repeated_foreign_message")), 2);
+    assertEquals(
+        2,
+        result.getRepeatedFieldCount(
+            result.getDescriptorForType().findFieldByName("repeated_foreign_message")));
   }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 2c60fe0..4af5542 100644
--- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -92,5 +92,31 @@
     assertEquals(0L, message.getExtension(
         TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
 
+    assertEquals("", message.getFieldName32());
+    assertEquals("", message.getFieldName33());
+    assertEquals(0, message.get2Conflict34());
+    assertEquals(0, message.get2Conflict35());
+
+  }
+
+  public void testNumberFields() throws Exception {
+    TestBadIdentifiersProto.TestLeadingNumberFields message =
+        TestBadIdentifiersProto.TestLeadingNumberFields.getDefaultInstance();
+    // Make sure generated accessors are properly named.
+    assertFalse(message.has30DayImpressions());
+    assertEquals(0, message.get30DayImpressions());
+    assertEquals(0, message.get60DayImpressionsCount());
+    assertEquals(0, message.get60DayImpressionsList().size());
+
+    assertFalse(message.has2Underscores());
+    assertEquals("", message.get2Underscores());
+    assertEquals(0, message.get2RepeatedUnderscoresCount());
+    assertEquals(0, message.get2RepeatedUnderscoresList().size());
+
+    assertFalse(message.has32());
+    assertEquals(0, message.get32());
+    assertEquals(0, message.get64Count());
+    assertEquals(0, message.get64List().size());
+
   }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
new file mode 100644
index 0000000..37f94c0
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
@@ -0,0 +1,83 @@
+// 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.
+
+package com.google.protobuf;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that proto2 api generation doesn't cause compile errors when compiling protocol buffers
+ * that have names that would otherwise conflict if not fully qualified (like @Deprecated
+ * and @Override).
+ *
+ * <p>Forked from {@link TestBadIdentifiers}.
+ *
+ * @author [email protected] (Jon Perlow)
+ */
+public final class TestBadIdentifiersLite extends TestCase {
+
+  public void testCompilation() {
+    // If this compiles, it means the generation was correct.
+    TestBadIdentifiersProto.Deprecated.newBuilder();
+    TestBadIdentifiersProto.Override.newBuilder();
+  }
+
+  public void testConflictingFieldNames() throws Exception {
+    TestBadIdentifiersProto.TestConflictingFieldNames message =
+        TestBadIdentifiersProto.TestConflictingFieldNames.getDefaultInstance();
+    // Make sure generated accessors are properly named.
+    assertEquals(0, message.getInt32Field1Count());
+    assertEquals(0, message.getEnumField2Count());
+    assertEquals(0, message.getStringField3Count());
+    assertEquals(0, message.getBytesField4Count());
+    assertEquals(0, message.getMessageField5Count());
+
+    assertEquals(0, message.getInt32FieldCount11());
+    assertEquals(0, message.getEnumFieldCount12().getNumber());
+    assertEquals("", message.getStringFieldCount13());
+    assertEquals(ByteString.EMPTY, message.getBytesFieldCount14());
+    assertEquals(0, message.getMessageFieldCount15().getSerializedSize());
+
+    assertEquals(0, message.getInt32Field21Count());
+    assertEquals(0, message.getEnumField22Count());
+    assertEquals(0, message.getStringField23Count());
+    assertEquals(0, message.getBytesField24Count());
+    assertEquals(0, message.getMessageField25Count());
+
+    assertEquals(0, message.getInt32Field1List().size());
+    assertEquals(0, message.getInt32FieldList31());
+
+    assertEquals(0, message.getInt64FieldCount());
+    assertEquals(0L, message.getExtension(
+        TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldCount).longValue());
+    assertEquals(0L, message.getExtension(
+        TestBadIdentifiersProto.TestConflictingFieldNames.int64FieldList).longValue());
+  }
+}
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
index 249d7c5..910f360 100644
--- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -30,8 +30,6 @@
 
 package com.google.protobuf;
 
-import static com.google.common.truth.Truth.assertThat;
-
 import com.google.protobuf.Descriptors.Descriptor;
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
@@ -1079,12 +1077,12 @@
     {
       TestMap.Builder dest = TestMap.newBuilder();
       TextFormat.merge(text, dest);
-      assertThat(dest.build()).isEqualTo(message);
+      assertEquals(message, dest.build());
     }
     {
       TestMap.Builder dest = TestMap.newBuilder();
       parserWithOverwriteForbidden.merge(text, dest);
-      assertThat(dest.build()).isEqualTo(message);
+      assertEquals(message, dest.build());
     }
   }
 
@@ -1096,10 +1094,10 @@
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertThat(message.getStringToInt32Field().size()).isEqualTo(2);
-    assertThat(message.getInt32ToMessageField().size()).isEqualTo(2);
-    assertThat(message.getStringToInt32Field().get("x")).isEqualTo(10);
-    assertThat(message.getInt32ToMessageField().get(2).getValue()).isEqualTo(200);
+    assertEquals(2, message.getStringToInt32Field().size());
+    assertEquals(2, message.getInt32ToMessageField().size());
+    assertEquals(10, message.getStringToInt32Field().get("x").intValue());
+    assertEquals(200, message.getInt32ToMessageField().get(2).getValue());
   }
 
   public void testMapShortFormEmpty() throws Exception {
@@ -1108,8 +1106,8 @@
     TestMap.Builder dest = TestMap.newBuilder();
     parserWithOverwriteForbidden.merge(text, dest);
     TestMap message = dest.build();
-    assertThat(message.getStringToInt32Field().size()).isEqualTo(0);
-    assertThat(message.getInt32ToMessageField().size()).isEqualTo(0);
+    assertEquals(0, message.getStringToInt32Field().size());
+    assertEquals(0, message.getInt32ToMessageField().size());
   }
 
   public void testMapShortFormTrailingComma() throws Exception {
@@ -1119,7 +1117,7 @@
       parserWithOverwriteForbidden.merge(text, dest);
       fail("Expected parse exception.");
     } catch (TextFormat.ParseException e) {
-      assertThat(e).hasMessageThat().isEqualTo("1:48: Expected \"{\".");
+      assertEquals("1:48: Expected \"{\".", e.getMessage());
     }
   }
 
@@ -1134,8 +1132,8 @@
       TestMap.Builder builder = TestMap.newBuilder();
       defaultParser.merge(text, builder);
       TestMap map = builder.build();
-      assertThat(map.getInt32ToInt32Field().size()).isEqualTo(2);
-      assertThat(map.getInt32ToInt32Field().get(1).intValue()).isEqualTo(30);
+      assertEquals(2, map.getInt32ToInt32Field().size());
+      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
     }
 
     {
@@ -1144,8 +1142,8 @@
       TestMap.Builder builder = TestMap.newBuilder();
       defaultParser.merge(text, builder);
       TestMap map = builder.build();
-      assertThat(map.getInt32ToInt32Field().size()).isEqualTo(2);
-      assertThat(map.getInt32ToInt32Field().get(1).intValue()).isEqualTo(30);
+      assertEquals(2, map.getInt32ToInt32Field().size());
+      assertEquals(30, map.getInt32ToInt32Field().get(1).intValue());
     }
   }
 
diff --git a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
index 8f45976..88cbbf8 100644
--- a/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
+++ b/java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java
@@ -36,7 +36,6 @@
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
 import com.google.protobuf.TextFormat.ParseException;
-
 import junit.framework.TestCase;
 
 /**
@@ -151,18 +150,15 @@
     assertEquals(4321, unknown4321.getNumber());
     assertEquals(5432, unknown5432.getNumber());
     assertEquals(6543, unknown6543.getNumber());
-    
+
     // Unknown EnumValueDescriptor will map to UNRECOGNIZED.
     assertEquals(
-        TestAllTypes.NestedEnum.valueOf(unknown4321),
-        TestAllTypes.NestedEnum.UNRECOGNIZED);
+        TestAllTypes.NestedEnum.UNRECOGNIZED, TestAllTypes.NestedEnum.valueOf(unknown4321));
     assertEquals(
-        TestAllTypes.NestedEnum.valueOf(unknown5432),
-        TestAllTypes.NestedEnum.UNRECOGNIZED);
+        TestAllTypes.NestedEnum.UNRECOGNIZED, TestAllTypes.NestedEnum.valueOf(unknown5432));
     assertEquals(
-        TestAllTypes.NestedEnum.valueOf(unknown6543),
-        TestAllTypes.NestedEnum.UNRECOGNIZED);
-    
+        TestAllTypes.NestedEnum.UNRECOGNIZED, TestAllTypes.NestedEnum.valueOf(unknown6543));
+
     // Setters also accept unknown EnumValueDescriptor.
     builder.setField(optionalNestedEnumField, unknown6543);
     builder.setRepeatedField(repeatedNestedEnumField, 0, unknown4321);
diff --git a/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto b/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
index d2c7793..ff5bf3a 100644
--- a/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
+++ b/java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto
@@ -148,6 +148,12 @@
   // the method getInt32FieldList().
   required int32 int32_field_list = 31;  // NO_PROTO3
 
+  // These field pairs have the same Java converted name
+  optional string field_name = 32; // NO_PROTO3
+  optional string field__name = 33; // NO_PROTO3
+  optional int32 _2conflict = 34; // NO_PROTO3
+  optional int32 __2conflict = 35;
+
   extensions 1000 to max;  // NO_PROTO3
 
   repeated int64 int64_field = 41;
@@ -166,3 +172,14 @@
 
   map<int32, int32> map_field = 1;
 }
+
+message TestLeadingNumberFields {
+  optional int32 _30day_impressions = 1;
+  repeated string _60day_impressions = 2;
+
+  optional string __2_underscores = 3;
+  repeated string __2repeated_underscores = 4;
+
+  optional int32 _32 = 32;
+  repeated int64 _64 = 64;
+}
diff --git a/java/pom.xml b/java/pom.xml
index 81ffc48..dd3ba3b 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -11,7 +11,7 @@
 
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-parent</artifactId>
-  <version>3.3.0</version>
+  <version>3.4.0</version>
   <packaging>pom</packaging>
 
   <name>Protocol Buffers [Parent]</name>
@@ -84,13 +84,7 @@
       <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
-        <version>20.0</version>
-      </dependency>
-      <dependency>
-        <groupId>com.google.truth</groupId>
-        <artifactId>truth</artifactId>
-        <scope>test</scope>
-        <version>0.32</version>
+        <version>19.0</version>
       </dependency>
     </dependencies>
   </dependencyManagement>
diff --git a/java/util/pom.xml b/java/util/pom.xml
index c72fa65..61abd14 100644
--- a/java/util/pom.xml
+++ b/java/util/pom.xml
@@ -6,7 +6,7 @@
   <parent>
     <groupId>com.google.protobuf</groupId>
     <artifactId>protobuf-parent</artifactId>
-    <version>3.3.0</version>
+    <version>3.4.0</version>
   </parent>
 
   <artifactId>protobuf-java-util</artifactId>
diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java
index 46b2182..fb7f434 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Durations.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java
@@ -30,7 +30,6 @@
 
 package com.google.protobuf.util;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.math.IntMath.checkedAdd;
 import static com.google.common.math.IntMath.checkedSubtract;
 import static com.google.common.math.LongMath.checkedAdd;
@@ -84,6 +83,17 @@
   }
 
   /**
+   * Compares two durations. The value returned is identical to what would be returned by:
+   * {@code Durations.comparator().compare(x, y)}.
+   *
+   * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y};
+   *     and a value greater than {@code 0} if {@code x > y}
+   */
+  public static int compare(Duration x, Duration y) {
+    return COMPARATOR.compare(x, y);
+  }
+
+  /**
    * Returns true if the given {@link Duration} is valid. The {@code seconds} value must be in the
    * range [-315,576,000,000, +315,576,000,000]. The {@code nanos} value must be in the range
    * [-999,999,999, +999,999,999].
@@ -124,14 +134,13 @@
   public static Duration checkValid(Duration duration) {
     long seconds = duration.getSeconds();
     int nanos = duration.getNanos();
-    checkArgument(
-        isValid(seconds, nanos),
-        "Duration is not valid. See proto definition for valid values. "
+    if (!isValid(seconds, nanos)) {
+        throw new IllegalArgumentException(String.format(
+            "Duration is not valid. See proto definition for valid values. "
             + "Seconds (%s) must be in range [-315,576,000,000, +315,576,000,000]. "
             + "Nanos (%s) must be in range [-999,999,999, +999,999,999]. "
-            + "Nanos must have the same sign as seconds",
-        seconds,
-        nanos);
+            + "Nanos must have the same sign as seconds", seconds, nanos));
+    }
     return duration;
   }
 
diff --git a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
index 21d11b2..b2f849c 100644
--- a/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
+++ b/java/util/src/main/java/com/google/protobuf/util/FieldMaskUtil.java
@@ -311,16 +311,19 @@
       return replacePrimitiveFields;
     }
 
-    public void setReplaceMessageFields(boolean value) {
+    public MergeOptions setReplaceMessageFields(boolean value) {
       replaceMessageFields = value;
+      return this;
     }
 
-    public void setReplaceRepeatedFields(boolean value) {
+    public MergeOptions setReplaceRepeatedFields(boolean value) {
       replaceRepeatedFields = value;
+      return this;
     }
 
-    public void setReplacePrimitiveFields(boolean value) {
+    public MergeOptions setReplacePrimitiveFields(boolean value) {
       replacePrimitiveFields = value;
+      return this;
     }
   }
 
diff --git a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
index e1c2d73..a603d96 100644
--- a/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
+++ b/java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
@@ -1686,7 +1686,11 @@
     }
 
     private ByteString parseBytes(JsonElement json) throws InvalidProtocolBufferException {
-      return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
+      try {
+        return ByteString.copyFrom(BaseEncoding.base64().decode(json.getAsString()));
+      } catch (IllegalArgumentException e) {
+        return ByteString.copyFrom(BaseEncoding.base64Url().decode(json.getAsString()));
+      }
     }
 
     private EnumValueDescriptor parseEnum(EnumDescriptor enumDescriptor, JsonElement json)
diff --git a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
index d0bac41..7a1f201 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Timestamps.java
@@ -30,7 +30,6 @@
 
 package com.google.protobuf.util;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.math.IntMath.checkedAdd;
 import static com.google.common.math.IntMath.checkedSubtract;
 import static com.google.common.math.LongMath.checkedAdd;
@@ -115,6 +114,17 @@
   }
 
   /**
+   * Compares two timestamps. The value returned is identical to what would be returned by:
+   * {@code Timestamps.comparator().compare(x, y)}.
+   *
+   * @return the value {@code 0} if {@code x == y}; a value less than {@code 0} if {@code x < y};
+   *     and a value greater than {@code 0} if {@code x > y}
+   */
+  public static int compare(Timestamp x, Timestamp y) {
+    return COMPARATOR.compare(x, y);
+  }
+
+  /**
    * Returns true if the given {@link Timestamp} is valid. The {@code seconds} value must be in the
    * range [-62,135,596,800, +253,402,300,799] (i.e., between 0001-01-01T00:00:00Z and
    * 9999-12-31T23:59:59Z). The {@code nanos} value must be in the range [0, +999,999,999].
@@ -149,13 +159,12 @@
   public static Timestamp checkValid(Timestamp timestamp) {
     long seconds = timestamp.getSeconds();
     int nanos = timestamp.getNanos();
-    checkArgument(
-        isValid(seconds, nanos),
-        "Timestamp is not valid. See proto definition for valid values. "
+    if (!isValid(seconds, nanos)) {
+        throw new IllegalArgumentException(String.format(
+            "Timestamp is not valid. See proto definition for valid values. "
             + "Seconds (%s) must be in range [-62,135,596,800, +253,402,300,799]. "
-            + "Nanos (%s) must be in range [0, +999,999,999].",
-        seconds,
-        nanos);
+            + "Nanos (%s) must be in range [0, +999,999,999].", seconds, nanos));
+    }
     return timestamp;
   }
 
diff --git a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
index 460b81f..e4c5387 100644
--- a/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/JsonFormatTest.java
@@ -73,7 +73,6 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Locale;
-import java.util.Map;
 import java.util.Set;
 import junit.framework.TestCase;
 
@@ -1144,7 +1143,8 @@
   }
 
   public void testParserAcceptBase64Variants() throws Exception {
-    assertAccepts("optionalBytes", "AQI");
+    assertAccepts("optionalBytes", "AQI");  // No padding
+    assertAccepts("optionalBytes", "-_w");  // base64Url, no padding
   }
 
   public void testParserRejectInvalidEnumValue() throws Exception {
diff --git a/jenkins/docker/Dockerfile b/jenkins/docker/Dockerfile
index 6a9e7e4..3a279e6 100644
--- a/jenkins/docker/Dockerfile
+++ b/jenkins/docker/Dockerfile
@@ -129,7 +129,7 @@
 RUN cd /tmp && \
   git clone https://github.com/google/protobuf.git && \
   cd protobuf && \
-  git reset --hard c2b3b3e04e7a023efe06f2107705b45428847800 && \
+  git reset --hard 129a6e2aca95dcfb6c3e717d7b9cca1f104fde39 && \
   ./autogen.sh && \
   ./configure && \
   make -j4 && \
@@ -145,7 +145,7 @@
 RUN tar -xvf php-5.5.38.tar.bz2
 RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \
     make && make install && cd ..
-RUN cd php-5.5.38 && make clean && ./configure --prefix=/usr/local/php-5.5 && \
+RUN cd php-5.5.38 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.5 && \
     make && make install && cd ..
 
 RUN wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror
@@ -153,7 +153,7 @@
 RUN tar -xvf php-5.6.30.tar.bz2
 RUN cd php-5.6.30 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.6-zts && \
     make && make install && cd ..
-RUN cd php-5.6.30 && make clean && ./configure --prefix=/usr/local/php-5.6 && \
+RUN cd php-5.6.30 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.6 && \
     make && make install && cd ..
 
 RUN wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror
@@ -161,7 +161,15 @@
 RUN tar -xvf php-7.0.18.tar.bz2
 RUN cd php-7.0.18 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.0-zts && \
     make && make install && cd ..
-RUN cd php-7.0.18 && make clean && ./configure --prefix=/usr/local/php-7.0 && \
+RUN cd php-7.0.18 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.0 && \
+    make && make install && cd ..
+
+RUN wget http://am1.php.net/get/php-7.1.4.tar.bz2/from/this/mirror
+RUN mv mirror php-7.1.4.tar.bz2
+RUN tar -xvf php-7.1.4.tar.bz2
+RUN cd php-7.1.4 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.1-zts && \
+    make && make install && cd ..
+RUN cd php-7.1.4 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.1 && \
     make && make install && cd ..
 
 RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
@@ -174,7 +182,7 @@
   rm -rf protobuf && \
   git clone https://github.com/google/protobuf.git && \
   cd protobuf && \
-  git reset --hard 6b27c1f981a9a93918e4039f236ead27165a8e91 && \
+  git reset --hard 49b44bff2b6257a119f9c6a342d6151c736586b8 && \
   cd php && \
   ln -sfn /usr/local/php-5.5/bin/php /usr/bin/php && \
   ln -sfn /usr/local/php-5.5/bin/php-config /usr/bin/php-config && \
@@ -190,7 +198,12 @@
   ln -sfn /usr/local/php-7.0/bin/php-config /usr/bin/php-config && \
   ln -sfn /usr/local/php-7.0/bin/phpize /usr/bin/phpize && \
   composer install && \
-  mv vendor /usr/local/vendor-7.0
+  mv vendor /usr/local/vendor-7.0 && \
+  ln -sfn /usr/local/php-7.1/bin/php /usr/bin/php && \
+  ln -sfn /usr/local/php-7.1/bin/php-config /usr/bin/php-config && \
+  ln -sfn /usr/local/php-7.1/bin/phpize /usr/bin/phpize && \
+  composer install && \
+  mv vendor /usr/local/vendor-7.1
 
 ##################
 # Go dependencies.
@@ -204,6 +217,13 @@
   # -- For javascript -- \
   npm
 
+##################
+# Python 3.5 3.6 dependencies.
+RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
+  python3.5-dev \
+  python3.6-dev \
+  && apt-get clean
+
 # On Debian/Ubuntu, nodejs binary is named 'nodejs' because the name 'node'
 # is taken by another legacy binary. We don't have that legacy binary and
 # npm expects the binary to be named 'node', so we just create a symbol
diff --git a/jenkins/docker32/Dockerfile b/jenkins/docker32/Dockerfile
index ab3fd95..1278889 100644
--- a/jenkins/docker32/Dockerfile
+++ b/jenkins/docker32/Dockerfile
@@ -57,30 +57,6 @@
 
 ##################
 # PHP dependencies.
-RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
-RUN php composer-setup.php
-RUN mv composer.phar /usr/bin/composer
-RUN php -r "unlink('composer-setup.php');"
-RUN cd /tmp && \
-  git clone https://github.com/google/protobuf.git && \
-  cd protobuf/php && \
-  git reset --hard 6b27c1f981a9a93918e4039f236ead27165a8e91 && \
-  ln -sfn /usr/bin/php5.5 /usr/bin/php && \
-  ln -sfn /usr/bin/php-config5.5 /usr/bin/php-config && \
-  ln -sfn /usr/bin/phpize5.5 /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-5.5 && \
-  ln -sfn /usr/bin/php5.6 /usr/bin/php && \
-  ln -sfn /usr/bin/php-config5.6 /usr/bin/php-config && \
-  ln -sfn /usr/bin/phpize5.6 /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-5.6 && \
-  ln -sfn /usr/bin/php7.0 /usr/bin/php && \
-  ln -sfn /usr/bin/php-config7.0 /usr/bin/php-config && \
-  ln -sfn /usr/bin/phpize7.0 /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-7.0
-
 RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror
 RUN mv mirror php-5.5.38.tar.bz2
 RUN tar -xvf php-5.5.38.tar.bz2
@@ -105,6 +81,45 @@
 RUN cd php-7.0.18 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.0 && \
     make && make install && cd ..
 
+RUN wget http://am1.php.net/get/php-7.1.4.tar.bz2/from/this/mirror
+RUN mv mirror php-7.1.4.tar.bz2
+RUN tar -xvf php-7.1.4.tar.bz2
+RUN cd php-7.1.4 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.1-zts && \
+    make && make install && cd ..
+RUN cd php-7.1.4 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.1 && \
+    make && make install && cd ..
+
+RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
+RUN php composer-setup.php
+RUN mv composer.phar /usr/bin/composer
+RUN php -r "unlink('composer-setup.php');"
+RUN composer config -g -- disable-tls true
+RUN composer config -g -- secure-http false
+RUN cd /tmp && \
+  git clone https://github.com/google/protobuf.git && \
+  cd protobuf/php && \
+  git reset --hard 49b44bff2b6257a119f9c6a342d6151c736586b8 && \
+  ln -sfn /usr/local/php-5.5/bin/php /usr/bin/php && \
+  ln -sfn /usr/local/php-5.5/bin/php-config /usr/bin/php-config && \
+  ln -sfn /usr/local/php-5.5/bin/phpize /usr/bin/phpize && \
+  composer install && \
+  mv vendor /usr/local/vendor-5.5 && \
+  ln -sfn /usr/local/php-5.6/bin/php /usr/bin/php && \
+  ln -sfn /usr/local/php-5.6/bin/php-config /usr/bin/php-config && \
+  ln -sfn /usr/local/php-5.6/bin/phpize /usr/bin/phpize && \
+  composer install && \
+  mv vendor /usr/local/vendor-5.6 && \
+  ln -sfn /usr/local/php-7.0/bin/php /usr/bin/php && \
+  ln -sfn /usr/local/php-7.0/bin/php-config /usr/bin/php-config && \
+  ln -sfn /usr/local/php-7.0/bin/phpize /usr/bin/phpize && \
+  composer install && \
+  mv vendor /usr/local/vendor-7.0 && \
+  ln -sfn /usr/local/php-7.1/bin/php /usr/bin/php && \
+  ln -sfn /usr/local/php-7.1/bin/php-config /usr/bin/php-config && \
+  ln -sfn /usr/local/php-7.1/bin/phpize /usr/bin/phpize && \
+  composer install && \
+  mv vendor /usr/local/vendor-7.1
+
 ##################
 # Python dependencies
 
diff --git a/jenkins/make_test_output.py b/jenkins/make_test_output.py
index b1f2e2c..9853685 100644
--- a/jenkins/make_test_output.py
+++ b/jenkins/make_test_output.py
@@ -17,11 +17,12 @@
 finishes.
 """
 
-import os;
-import sys;
+import os
+import sys
 from yattag import Doc
 from collections import defaultdict
 
+
 def readtests(basedir):
   tests = defaultdict(dict)
 
@@ -68,6 +69,7 @@
 
   return ret
 
+
 def genxml(tests):
   doc, tag, text = Doc().tagtext()
 
@@ -86,6 +88,7 @@
 
   return doc.getvalue()
 
+
 sys.stderr.write("make_test_output.py: writing XML from directory: " +
-                 sys.argv[1] + "\n");
-print genxml(readtests(sys.argv[1]))
+                 sys.argv[1] + "\n")
+print(genxml(readtests(sys.argv[1])))
diff --git a/js/README.md b/js/README.md
index f418462..24386dc 100644
--- a/js/README.md
+++ b/js/README.md
@@ -19,7 +19,9 @@
 To use Protocol Buffers with JavaScript, you need two main components:
 
 1. The protobuf runtime library.  You can install this with
-   `npm install google-protobuf`, or use the files in this directory.
+   `npm install google-protobuf`, or use the files in this directory.  
+    If npm is not being used, as of 3.3.0, the files needed are located in binary subdirectory; 
+    arith.js, constants.js, decoder.js, encoder.js, map.js, message.js, reader.js, utils.js, writer.js
 2. The Protocol Compiler `protoc`.  This translates `.proto` files
    into `.js` files.  The compiler is not currently available via
    npm, but you can download a pre-built binary
@@ -93,6 +95,12 @@
 
     var message = proto.my.package.MyMessage();
 
+If unfamiliar with Closure or it's compiler, consider reviewing Closure documentation
+https://developers.google.com/closure/library/docs/tutorial
+https://developers.google.com/closure/library/docs/closurebuilder
+https://developers.google.com/closure/library/docs/depswriter
+At a high level, closurebuilder.py can walk dependencies, and compile your code, and all dependencies for Protobuf into a single .js file.  Using depsbuilder.py to generate a dependency file can also be considered for non-production dev environments.
+
 CommonJS imports
 ----------------
 
diff --git a/js/binary/encoder.js b/js/binary/encoder.js
index f25935f..8e9f5bb 100644
--- a/js/binary/encoder.js
+++ b/js/binary/encoder.js
@@ -390,11 +390,13 @@
 
 
 /**
- * Writes a boolean value to the buffer as a varint.
- * @param {boolean} value The value to write.
+ * Writes a boolean value to the buffer as a varint. We allow numbers as input
+ * because the JSPB code generator uses 0/1 instead of true/false to save space
+ * in the string representation of the proto.
+ * @param {boolean|number} value The value to write.
  */
 jspb.BinaryEncoder.prototype.writeBool = function(value) {
-  goog.asserts.assert(goog.isBoolean(value));
+  goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value));
   this.buffer_.push(value ? 1 : 0);
 };
 
diff --git a/js/binary/writer.js b/js/binary/writer.js
index 672e94b..037e92b 100644
--- a/js/binary/writer.js
+++ b/js/binary/writer.js
@@ -235,7 +235,7 @@
 
 
 /**
- * Converts the encoded data into a bas64-encoded string.
+ * Converts the encoded data into a base64-encoded string.
  * @return {string}
  */
 jspb.BinaryWriter.prototype.getResultBase64String = function() {
@@ -716,13 +716,15 @@
 
 
 /**
- * Writes a boolean field to the buffer.
+ * Writes a boolean field to the buffer. We allow numbers as input
+ * because the JSPB code generator uses 0/1 instead of true/false to save space
+ * in the string representation of the proto.
  * @param {number} field The field number.
- * @param {boolean?} value The value to write.
+ * @param {boolean?|number?} value The value to write.
  */
 jspb.BinaryWriter.prototype.writeBool = function(field, value) {
   if (value == null) return;
-  goog.asserts.assert(goog.isBoolean(value));
+  goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value));
   this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
   this.encoder_.writeBool(value);
 };
diff --git a/js/compatibility_tests/v3.1.0/binary/arith_test.js b/js/compatibility_tests/v3.1.0/binary/arith_test.js
new file mode 100644
index 0000000..89796bf
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/arith_test.js
@@ -0,0 +1,355 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for Int64-manipulation functions.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author [email protected] (Chris Fallin)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.arith.Int64');
+goog.require('jspb.arith.UInt64');
+
+
+describe('binaryArithTest', function() {
+  /**
+   * Tests comparison operations.
+   */
+  it('testCompare', function() {
+    var a = new jspb.arith.UInt64(1234, 5678);
+    var b = new jspb.arith.UInt64(1234, 5678);
+    assertEquals(a.cmp(b), 0);
+    assertEquals(b.cmp(a), 0);
+    b.lo -= 1;
+    assertEquals(a.cmp(b), 1);
+    assertEquals(b.cmp(a), -1);
+    b.lo += 2;
+    assertEquals(a.cmp(b), -1);
+    assertEquals(b.cmp(a), 1);
+    b.lo = a.lo;
+    b.hi = a.hi - 1;
+    assertEquals(a.cmp(b), 1);
+    assertEquals(b.cmp(a), -1);
+
+    assertEquals(a.zero(), false);
+    assertEquals(a.msb(), false);
+    assertEquals(a.lsb(), false);
+    a.hi = 0;
+    a.lo = 0;
+    assertEquals(a.zero(), true);
+    a.hi = 0x80000000;
+    assertEquals(a.zero(), false);
+    assertEquals(a.msb(), true);
+    a.lo = 0x00000001;
+    assertEquals(a.lsb(), true);
+  });
+
+
+  /**
+   * Tests shifts.
+   */
+  it('testShifts', function() {
+    var a = new jspb.arith.UInt64(1, 0);
+    assertEquals(a.lo, 1);
+    assertEquals(a.hi, 0);
+    var orig = a;
+    a = a.leftShift();
+    assertEquals(orig.lo, 1);  // original unmodified.
+    assertEquals(orig.hi, 0);
+    assertEquals(a.lo, 2);
+    assertEquals(a.hi, 0);
+    a = a.leftShift();
+    assertEquals(a.lo, 4);
+    assertEquals(a.hi, 0);
+    for (var i = 0; i < 29; i++) {
+      a = a.leftShift();
+    }
+    assertEquals(a.lo, 0x80000000);
+    assertEquals(a.hi, 0);
+    a = a.leftShift();
+    assertEquals(a.lo, 0);
+    assertEquals(a.hi, 1);
+    a = a.leftShift();
+    assertEquals(a.lo, 0);
+    assertEquals(a.hi, 2);
+    a = a.rightShift();
+    a = a.rightShift();
+    assertEquals(a.lo, 0x80000000);
+    assertEquals(a.hi, 0);
+    a = a.rightShift();
+    assertEquals(a.lo, 0x40000000);
+    assertEquals(a.hi, 0);
+  });
+
+
+  /**
+   * Tests additions.
+   */
+  it('testAdd', function() {
+    var a = new jspb.arith.UInt64(/* lo = */ 0x89abcdef,
+                                         /* hi = */ 0x01234567);
+    var b = new jspb.arith.UInt64(/* lo = */ 0xff52ab91,
+                                         /* hi = */ 0x92fa2123);
+    // Addition with carry.
+    var c = a.add(b);
+    assertEquals(a.lo, 0x89abcdef);  // originals unmodified.
+    assertEquals(a.hi, 0x01234567);
+    assertEquals(b.lo, 0xff52ab91);
+    assertEquals(b.hi, 0x92fa2123);
+    assertEquals(c.lo, 0x88fe7980);
+    assertEquals(c.hi, 0x941d668b);
+
+    // Simple addition without carry.
+    a.lo = 2;
+    a.hi = 0;
+    b.lo = 3;
+    b.hi = 0;
+    c = a.add(b);
+    assertEquals(c.lo, 5);
+    assertEquals(c.hi, 0);
+  });
+
+
+  /**
+   * Test subtractions.
+   */
+  it('testSub', function() {
+    var kLength = 10;
+    var hiValues = [0x1682ef32,
+                    0x583902f7,
+                    0xb62f5955,
+                    0x6ea99bbf,
+                    0x25a39c20,
+                    0x0700a08b,
+                    0x00f7304d,
+                    0x91a5b5af,
+                    0x89077fd2,
+                    0xe09e347c];
+    var loValues = [0xe1538b18,
+                    0xbeacd556,
+                    0x74100758,
+                    0x96e3cb26,
+                    0x56c37c3f,
+                    0xe00b3f7d,
+                    0x859f25d7,
+                    0xc2ee614a,
+                    0xe1d21cd7,
+                    0x30aae6a4];
+    for (var i = 0; i < kLength; i++) {
+      for (var j = 0; j < kLength; j++) {
+        var a = new jspb.arith.UInt64(loValues[i], hiValues[j]);
+        var b = new jspb.arith.UInt64(loValues[j], hiValues[i]);
+        var c = a.add(b).sub(b);
+        assertEquals(c.hi, a.hi);
+        assertEquals(c.lo, a.lo);
+      }
+    }
+  });
+
+
+  /**
+   * Tests 32-by-32 multiplication.
+   */
+  it('testMul32x32', function() {
+    var testData = [
+      // a        b          low(a*b)   high(a*b)
+      [0xc0abe2f8, 0x1607898a, 0x5de711b0, 0x109471b8],
+      [0x915eb3cb, 0x4fb66d0e, 0xbd0d441a, 0x2d43d0bc],
+      [0xfe4efe70, 0x80b48c37, 0xbcddea10, 0x7fdada0c],
+      [0xe222fd4a, 0xe43d524a, 0xd5e0eb64, 0xc99d549c],
+      [0xd171f469, 0xb94ebd01, 0x4be17969, 0x979bc4fa],
+      [0x829cc1df, 0xe2598b38, 0xf4157dc8, 0x737c12ad],
+      [0xf10c3767, 0x8382881e, 0x942b3612, 0x7bd428b8],
+      [0xb0f6dd24, 0x232597e1, 0x079c98a4, 0x184bbce7],
+      [0xfcdb05a7, 0x902f55bc, 0x636199a4, 0x8e69f412],
+      [0x0dd0bfa9, 0x916e27b1, 0x6e2542d9, 0x07d92e65]
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = testData[i][0] >>> 0;
+      var b = testData[i][1] >>> 0;
+      var cLow = testData[i][2] >>> 0;
+      var cHigh = testData[i][3] >>> 0;
+      var c = jspb.arith.UInt64.mul32x32(a, b);
+      assertEquals(c.lo, cLow);
+      assertEquals(c.hi, cHigh);
+    }
+  });
+
+
+  /**
+   * Tests 64-by-32 multiplication.
+   */
+  it('testMul', function() {
+    // 64x32 bits produces 96 bits of product. The multiplication function under
+    // test truncates the top 32 bits, so we compare against a 64-bit expected
+    // product.
+    var testData = [
+      // low(a)   high(a)               low(a*b)   high(a*b)
+      [0xec10955b, 0x360eb168, 0x4b7f3f5b, 0xbfcb7c59, 0x9517da5f],
+      [0x42b000fc, 0x9d101642, 0x6fa1ab72, 0x2584c438, 0x6a9e6d2b],
+      [0xf42d4fb4, 0xae366403, 0xa65a1000, 0x92434000, 0x1ff978df],
+      [0x17e2f56b, 0x25487693, 0xf13f98c7, 0x73794e2d, 0xa96b0c6a],
+      [0x492f241f, 0x76c0eb67, 0x7377ac44, 0xd4336c3c, 0xfc4b1ebe],
+      [0xd6b92321, 0xe184fa48, 0xd6e76904, 0x93141584, 0xcbf44da1],
+      [0x4bf007ea, 0x968c0a9e, 0xf5e4026a, 0x4fdb1ae4, 0x61b9fb7d],
+      [0x10a83be7, 0x2d685ba6, 0xc9e5fb7f, 0x2ad43499, 0x3742473d],
+      [0x2f261829, 0x1aca681a, 0x3d3494e3, 0x8213205b, 0x283719f8],
+      [0xe4f2ce21, 0x2e74b7bd, 0xd801b38b, 0xbc17feeb, 0xc6c44e0f]
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+      var prod = a.mul(testData[i][2]);
+      assertEquals(prod.lo, testData[i][3]);
+      assertEquals(prod.hi, testData[i][4]);
+    }
+  });
+
+
+  /**
+   * Tests 64-div-by-32 division.
+   */
+  it('testDiv', function() {
+    // Compute a/b, yielding quot = a/b and rem = a%b.
+    var testData = [
+      // --- divisors in (0, 2^32-1) to test full divisor range
+      // low(a)   high(a)    b          low(quot)  high(quot) rem
+      [0x712443f1, 0xe85cefcc, 0xc1a7050b, 0x332c79ad, 0x00000001, 0x92ffa882],
+      [0x11912915, 0xb2699eb5, 0x30467cbe, 0xb21b4be4, 0x00000003, 0x283465dd],
+      [0x0d917982, 0x201f2a6e, 0x3f35bf03, 0x8217c8e4, 0x00000000, 0x153402d6],
+      [0xa072c108, 0x74020c96, 0xc60568fd, 0x95f9613e, 0x00000000, 0x3f4676c2],
+      [0xd845d5d8, 0xcdd235c4, 0x20426475, 0x6154e78b, 0x00000006, 0x202fb751],
+      [0xa4dbf71f, 0x9e90465e, 0xf08e022f, 0xa8be947f, 0x00000000, 0xbe43b5ce],
+      [0x3dbe627f, 0xa791f4b9, 0x28a5bd89, 0x1f5dfe93, 0x00000004, 0x02bf9ed4],
+      [0x5c1c53ee, 0xccf5102e, 0x198576e7, 0x07e3ae31, 0x00000008, 0x02ea8fb7],
+      [0xfef1e581, 0x04714067, 0xca6540c1, 0x059e73ec, 0x00000000, 0x31658095],
+      [0x1e2dd90c, 0x13dd6667, 0x8b2184c3, 0x248d1a42, 0x00000000, 0x4ca6d0c6],
+      // --- divisors in (0, 2^16-1) to test larger quotient high-words
+      // low(a)   high(a)    b          low(quot)  high(quot) rem
+      [0x86722b47, 0x2cd57c9a, 0x00003123, 0x2ae41b7a, 0x0000e995, 0x00000f99],
+      [0x1dd7884c, 0xf5e839bc, 0x00009eeb, 0x5c886242, 0x00018c21, 0x000099b6],
+      [0x5c53d625, 0x899fc7e5, 0x000087d7, 0xd625007a, 0x0001035c, 0x000019af],
+      [0x6932d932, 0x9d0a5488, 0x000051fb, 0x9d976143, 0x0001ea63, 0x00004981],
+      [0x4d18bb85, 0x0c92fb31, 0x00001d9f, 0x03265ab4, 0x00006cac, 0x000001b9],
+      [0xbe756768, 0xdea67ccb, 0x00008a03, 0x58add442, 0x00019cff, 0x000056a2],
+      [0xe2466f9a, 0x2521f114, 0x0000c350, 0xa0c0860d, 0x000030ab, 0x0000a48a],
+      [0xf00ddad1, 0xe2f5446a, 0x00002cfc, 0x762697a6, 0x00050b96, 0x00000b69],
+      [0xa879152a, 0x0a70e0a5, 0x00007cdf, 0xb44151b3, 0x00001567, 0x0000363d],
+      [0x7179a74c, 0x46083fff, 0x0000253c, 0x4d39ba6e, 0x0001e17f, 0x00000f84]
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+      var result = a.div(testData[i][2]);
+      var quotient = result[0];
+      var remainder = result[1];
+      assertEquals(quotient.lo, testData[i][3]);
+      assertEquals(quotient.hi, testData[i][4]);
+      assertEquals(remainder.lo, testData[i][5]);
+    }
+  });
+
+
+  /**
+   * Tests .toString() and .fromString().
+   */
+  it('testStrings', function() {
+    var testData = [
+        [0x5e84c935, 0xcae33d0e, '14619595947299359029'],
+        [0x62b3b8b8, 0x93480544, '10612738313170434232'],
+        [0x319bfb13, 0xc01c4172, '13843011313344445203'],
+        [0x5b8a65fb, 0xa5885b31, '11927883880638080507'],
+        [0x6bdb80f1, 0xb0d1b16b, '12741159895737008369'],
+        [0x4b82b442, 0x2e0d8c97, '3318463081876730946'],
+        [0x780d5208, 0x7d76752c, '9040542135845999112'],
+        [0x2e46800f, 0x0993778d, '690026616168284175'],
+        [0xf00a7e32, 0xcd8e3931, '14811839111111540274'],
+        [0x1baeccd6, 0x923048c4, '10533999535534820566'],
+        [0x03669d29, 0xbff3ab72, '13831587386756603177'],
+        [0x2526073e, 0x01affc81, '121593346566522686'],
+        [0xc24244e0, 0xd7f40d0e, '15561076969511732448'],
+        [0xc56a341e, 0xa68b66a7, '12000798502816461854'],
+        [0x8738d64d, 0xbfe78604, '13828168534871037517'],
+        [0x5baff03b, 0xd7572aea, '15516918227177304123'],
+        [0x4a843d8a, 0x864e132b, '9677693725920476554'],
+        [0x25b4e94d, 0x22b54dc6, '2500990681505655117'],
+        [0x6bbe664b, 0x55a5cc0e, '6171563226690381387'],
+        [0xee916c81, 0xb00aabb3, '12685140089732426881']
+    ];
+
+    for (var i = 0; i < testData.length; i++) {
+      var a = new jspb.arith.UInt64(testData[i][0], testData[i][1]);
+      var roundtrip = jspb.arith.UInt64.fromString(a.toString());
+      assertEquals(roundtrip.lo, a.lo);
+      assertEquals(roundtrip.hi, a.hi);
+      assertEquals(a.toString(), testData[i][2]);
+    }
+  });
+
+
+  /**
+   * Tests signed Int64s. These are built on UInt64s, so we only need to test
+   * the explicit overrides: .toString() and .fromString().
+   */
+  it('testSignedInt64', function() {
+    var testStrings = [
+        '-7847499644178593666',
+        '3771946501229139523',
+        '2872856549054995060',
+        '-5780049594274350904',
+        '3383785956695105201',
+        '2973055184857072610',
+        '-3879428459215627206',
+        '4589812431064156631',
+        '8484075557333689940',
+        '1075325817098092407',
+        '-4346697501012292314',
+        '2488620459718316637',
+        '6112655187423520672',
+        '-3655278273928612104',
+        '3439154019435803196',
+        '1004112478843763757',
+        '-6587790776614368413',
+        '664320065099714586',
+        '4760412909973292912',
+        '-7911903989602274672'
+    ];
+
+    for (var i = 0; i < testStrings.length; i++) {
+      var roundtrip =
+          jspb.arith.Int64.fromString(testStrings[i]).toString();
+      assertEquals(roundtrip, testStrings[i]);
+    }
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/decoder_test.js b/js/compatibility_tests/v3.1.0/binary/decoder_test.js
new file mode 100644
index 0000000..ac31264
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/decoder_test.js
@@ -0,0 +1,334 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer decoder.
+ *
+ * There are two particular magic numbers that need to be pointed out -
+ * 2^64-1025 is the largest number representable as both a double and an
+ * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
+ * both a double and a signed 64-bit integer.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author [email protected] (Austin Appleby)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.BinaryEncoder');
+
+
+/**
+ * Tests encoding and decoding of unsigned types.
+ * @param {Function} readValue
+ * @param {Function} writeValue
+ * @param {number} epsilon
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @suppress {missingProperties|visibility}
+ */
+function doTestUnsignedValue(readValue,
+    writeValue, epsilon, upperLimit, filter) {
+  var encoder = new jspb.BinaryEncoder();
+
+  // Encode zero and limits.
+  writeValue.call(encoder, filter(0));
+  writeValue.call(encoder, filter(epsilon));
+  writeValue.call(encoder, filter(upperLimit));
+
+  // Encode positive values.
+  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+    writeValue.call(encoder, filter(cursor));
+  }
+
+  var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+  // Check zero and limits.
+  assertEquals(filter(0), readValue.call(decoder));
+  assertEquals(filter(epsilon), readValue.call(decoder));
+  assertEquals(filter(upperLimit), readValue.call(decoder));
+
+  // Check positive values.
+  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+    if (filter(cursor) != readValue.call(decoder)) throw 'fail!';
+  }
+
+  // Encoding values outside the valid range should assert.
+  assertThrows(function() {writeValue.call(encoder, -1);});
+  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
+}
+
+
+/**
+ * Tests encoding and decoding of signed types.
+ * @param {Function} readValue
+ * @param {Function} writeValue
+ * @param {number} epsilon
+ * @param {number} lowerLimit
+ * @param {number} upperLimit
+ * @param {Function} filter
+ * @suppress {missingProperties}
+ */
+function doTestSignedValue(readValue,
+    writeValue, epsilon, lowerLimit, upperLimit, filter) {
+  var encoder = new jspb.BinaryEncoder();
+
+  // Encode zero and limits.
+  writeValue.call(encoder, filter(lowerLimit));
+  writeValue.call(encoder, filter(-epsilon));
+  writeValue.call(encoder, filter(0));
+  writeValue.call(encoder, filter(epsilon));
+  writeValue.call(encoder, filter(upperLimit));
+
+  var inputValues = [];
+
+  // Encode negative values.
+  for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
+    var val = filter(cursor);
+    writeValue.call(encoder, val);
+    inputValues.push(val);
+  }
+
+  // Encode positive values.
+  for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+    var val = filter(cursor);
+    writeValue.call(encoder, val);
+    inputValues.push(val);
+  }
+
+  var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+  // Check zero and limits.
+  assertEquals(filter(lowerLimit), readValue.call(decoder));
+  assertEquals(filter(-epsilon), readValue.call(decoder));
+  assertEquals(filter(0), readValue.call(decoder));
+  assertEquals(filter(epsilon), readValue.call(decoder));
+  assertEquals(filter(upperLimit), readValue.call(decoder));
+
+  // Verify decoded values.
+  for (var i = 0; i < inputValues.length; i++) {
+    assertEquals(inputValues[i], readValue.call(decoder));
+  }
+
+  // Encoding values outside the valid range should assert.
+  assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);});
+  assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);});
+}
+
+describe('binaryDecoderTest', function() {
+  /**
+   * Tests the decoder instance cache.
+   */
+  it('testInstanceCache', /** @suppress {visibility} */ function() {
+    // Empty the instance caches.
+    jspb.BinaryDecoder.instanceCache_ = [];
+
+    // Allocating and then freeing a decoder should put it in the instance
+    // cache.
+    jspb.BinaryDecoder.alloc().free();
+
+    assertEquals(1, jspb.BinaryDecoder.instanceCache_.length);
+
+    // Allocating and then freeing three decoders should leave us with three in
+    // the cache.
+
+    var decoder1 = jspb.BinaryDecoder.alloc();
+    var decoder2 = jspb.BinaryDecoder.alloc();
+    var decoder3 = jspb.BinaryDecoder.alloc();
+    decoder1.free();
+    decoder2.free();
+    decoder3.free();
+
+    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
+  });
+
+
+  /**
+   * Tests reading 64-bit integers as hash strings.
+   */
+  it('testHashStrings', function() {
+    var encoder = new jspb.BinaryEncoder();
+
+    var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00,
+                                    0x00, 0x00, 0x00, 0x00);
+    var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00,
+                                    0x00, 0x00, 0x00, 0x00);
+    var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78,
+                                    0x87, 0x65, 0x43, 0x21);
+    var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF,
+                                    0xFF, 0xFF, 0xFF, 0xFF);
+
+    encoder.writeVarintHash64(hashA);
+    encoder.writeVarintHash64(hashB);
+    encoder.writeVarintHash64(hashC);
+    encoder.writeVarintHash64(hashD);
+
+    encoder.writeFixedHash64(hashA);
+    encoder.writeFixedHash64(hashB);
+    encoder.writeFixedHash64(hashC);
+    encoder.writeFixedHash64(hashD);
+
+    var decoder = jspb.BinaryDecoder.alloc(encoder.end());
+
+    assertEquals(hashA, decoder.readVarintHash64());
+    assertEquals(hashB, decoder.readVarintHash64());
+    assertEquals(hashC, decoder.readVarintHash64());
+    assertEquals(hashD, decoder.readVarintHash64());
+
+    assertEquals(hashA, decoder.readFixedHash64());
+    assertEquals(hashB, decoder.readFixedHash64());
+    assertEquals(hashC, decoder.readFixedHash64());
+    assertEquals(hashD, decoder.readFixedHash64());
+  });
+
+
+  /**
+   * Verifies that misuse of the decoder class triggers assertions.
+   * @suppress {checkTypes|visibility}
+   */
+  it('testDecodeErrors', function() {
+    // Reading a value past the end of the stream should trigger an assertion.
+    var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]);
+    assertThrows(function() {decoder.readUint64()});
+
+    // Overlong varints should trigger assertions.
+    decoder.setBlock([255, 255, 255, 255, 255, 255,
+                      255, 255, 255, 255, 255, 0]);
+    assertThrows(function() {decoder.readUnsignedVarint64()});
+    decoder.reset();
+    assertThrows(function() {decoder.readSignedVarint64()});
+    decoder.reset();
+    assertThrows(function() {decoder.readZigzagVarint64()});
+
+    // Positive 32-bit varints encoded with 1 bits in positions 33 through 35
+    // should trigger assertions.
+    decoder.setBlock([255, 255, 255, 255, 0x1F]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    decoder.setBlock([255, 255, 255, 255, 0x2F]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    decoder.setBlock([255, 255, 255, 255, 0x4F]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    // Negative 32-bit varints encoded with non-1 bits in the high dword should
+    // trigger assertions.
+    decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+
+    decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]);
+    assertThrows(function() {decoder.readUnsignedVarint32()});
+  });
+
+
+  /**
+   * Tests encoding and decoding of unsigned integers.
+   */
+  it('testUnsignedIntegers', function() {
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint8,
+        jspb.BinaryEncoder.prototype.writeUint8,
+        1, 0xFF, Math.round);
+
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint16,
+        jspb.BinaryEncoder.prototype.writeUint16,
+        1, 0xFFFF, Math.round);
+
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint32,
+        jspb.BinaryEncoder.prototype.writeUint32,
+        1, 0xFFFFFFFF, Math.round);
+
+    doTestUnsignedValue(
+        jspb.BinaryDecoder.prototype.readUint64,
+        jspb.BinaryEncoder.prototype.writeUint64,
+        1, Math.pow(2, 64) - 1025, Math.round);
+  });
+
+
+  /**
+   * Tests encoding and decoding of signed integers.
+   */
+  it('testSignedIntegers', function() {
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt8,
+        jspb.BinaryEncoder.prototype.writeInt8,
+        1, -0x80, 0x7F, Math.round);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt16,
+        jspb.BinaryEncoder.prototype.writeInt16,
+        1, -0x8000, 0x7FFF, Math.round);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt32,
+        jspb.BinaryEncoder.prototype.writeInt32,
+        1, -0x80000000, 0x7FFFFFFF, Math.round);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readInt64,
+        jspb.BinaryEncoder.prototype.writeInt64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+  });
+
+
+  /**
+   * Tests encoding and decoding of floats.
+   */
+  it('testFloats', function() {
+    /**
+     * @param {number} x
+     * @return {number}
+     */
+    function truncate(x) {
+      var temp = new Float32Array(1);
+      temp[0] = x;
+      return temp[0];
+    }
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readFloat,
+        jspb.BinaryEncoder.prototype.writeFloat,
+        jspb.BinaryConstants.FLOAT32_EPS,
+        -jspb.BinaryConstants.FLOAT32_MAX,
+        jspb.BinaryConstants.FLOAT32_MAX,
+        truncate);
+
+    doTestSignedValue(
+        jspb.BinaryDecoder.prototype.readDouble,
+        jspb.BinaryEncoder.prototype.writeDouble,
+        jspb.BinaryConstants.FLOAT64_EPS * 10,
+        -jspb.BinaryConstants.FLOAT64_MAX,
+        jspb.BinaryConstants.FLOAT64_MAX,
+        function(x) { return x; });
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/proto_test.js b/js/compatibility_tests/v3.1.0/binary/proto_test.js
new file mode 100644
index 0000000..26e1d30
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/proto_test.js
@@ -0,0 +1,628 @@
+// 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.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+goog.require('jspb.Message');
+
+// CommonJS-LoadFromFile: ../testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.ExtendsWithMessage');
+goog.require('proto.jspb.test.ForeignEnum');
+goog.require('proto.jspb.test.ForeignMessage');
+goog.require('proto.jspb.test.TestAllTypes');
+goog.require('proto.jspb.test.TestExtendable');
+goog.require('proto.jspb.test.extendOptionalBool');
+goog.require('proto.jspb.test.extendOptionalBytes');
+goog.require('proto.jspb.test.extendOptionalDouble');
+goog.require('proto.jspb.test.extendOptionalFixed32');
+goog.require('proto.jspb.test.extendOptionalFixed64');
+goog.require('proto.jspb.test.extendOptionalFloat');
+goog.require('proto.jspb.test.extendOptionalForeignEnum');
+goog.require('proto.jspb.test.extendOptionalInt32');
+goog.require('proto.jspb.test.extendOptionalInt64');
+goog.require('proto.jspb.test.extendOptionalSfixed32');
+goog.require('proto.jspb.test.extendOptionalSfixed64');
+goog.require('proto.jspb.test.extendOptionalSint32');
+goog.require('proto.jspb.test.extendOptionalSint64');
+goog.require('proto.jspb.test.extendOptionalString');
+goog.require('proto.jspb.test.extendOptionalUint32');
+goog.require('proto.jspb.test.extendOptionalUint64');
+goog.require('proto.jspb.test.extendPackedRepeatedBoolList');
+goog.require('proto.jspb.test.extendPackedRepeatedDoubleList');
+goog.require('proto.jspb.test.extendPackedRepeatedFixed32List');
+goog.require('proto.jspb.test.extendPackedRepeatedFixed64List');
+goog.require('proto.jspb.test.extendPackedRepeatedFloatList');
+goog.require('proto.jspb.test.extendPackedRepeatedForeignEnumList');
+goog.require('proto.jspb.test.extendPackedRepeatedInt32List');
+goog.require('proto.jspb.test.extendPackedRepeatedInt64List');
+goog.require('proto.jspb.test.extendPackedRepeatedSfixed32List');
+goog.require('proto.jspb.test.extendPackedRepeatedSfixed64List');
+goog.require('proto.jspb.test.extendPackedRepeatedSint32List');
+goog.require('proto.jspb.test.extendPackedRepeatedSint64List');
+goog.require('proto.jspb.test.extendPackedRepeatedUint32List');
+goog.require('proto.jspb.test.extendPackedRepeatedUint64List');
+goog.require('proto.jspb.test.extendRepeatedBoolList');
+goog.require('proto.jspb.test.extendRepeatedBytesList');
+goog.require('proto.jspb.test.extendRepeatedDoubleList');
+goog.require('proto.jspb.test.extendRepeatedFixed32List');
+goog.require('proto.jspb.test.extendRepeatedFixed64List');
+goog.require('proto.jspb.test.extendRepeatedFloatList');
+goog.require('proto.jspb.test.extendRepeatedForeignEnumList');
+goog.require('proto.jspb.test.extendRepeatedInt32List');
+goog.require('proto.jspb.test.extendRepeatedInt64List');
+goog.require('proto.jspb.test.extendRepeatedSfixed32List');
+goog.require('proto.jspb.test.extendRepeatedSfixed64List');
+goog.require('proto.jspb.test.extendRepeatedSint32List');
+goog.require('proto.jspb.test.extendRepeatedSint64List');
+goog.require('proto.jspb.test.extendRepeatedStringList');
+goog.require('proto.jspb.test.extendRepeatedUint32List');
+goog.require('proto.jspb.test.extendRepeatedUint64List');
+
+
+var suite = {};
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
+/**
+ * Helper: fill all fields on a TestAllTypes message.
+ * @param {proto.jspb.test.TestAllTypes} msg
+ */
+function fillAllFields(msg) {
+  msg.setOptionalInt32(-42);
+  // can be exactly represented by JS number (64-bit double, i.e., 52-bit
+  // mantissa).
+  msg.setOptionalInt64(-0x7fffffff00000000);
+  msg.setOptionalUint32(0x80000000);
+  msg.setOptionalUint64(0xf000000000000000);
+  msg.setOptionalSint32(-100);
+  msg.setOptionalSint64(-0x8000000000000000);
+  msg.setOptionalFixed32(1234);
+  msg.setOptionalFixed64(0x1234567800000000);
+  msg.setOptionalSfixed32(-1234);
+  msg.setOptionalSfixed64(-0x1234567800000000);
+  msg.setOptionalFloat(1.5);
+  msg.setOptionalDouble(-1.5);
+  msg.setOptionalBool(true);
+  msg.setOptionalString('hello world');
+  msg.setOptionalBytes(BYTES);
+  msg.setOptionalGroup(new proto.jspb.test.TestAllTypes.OptionalGroup());
+  msg.getOptionalGroup().setA(100);
+  var submsg = new proto.jspb.test.ForeignMessage();
+  submsg.setC(16);
+  msg.setOptionalForeignMessage(submsg);
+  msg.setOptionalForeignEnum(proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+  msg.setOneofString('oneof');
+
+
+  msg.setRepeatedInt32List([-42]);
+  msg.setRepeatedInt64List([-0x7fffffff00000000]);
+  msg.setRepeatedUint32List([0x80000000]);
+  msg.setRepeatedUint64List([0xf000000000000000]);
+  msg.setRepeatedSint32List([-100]);
+  msg.setRepeatedSint64List([-0x8000000000000000]);
+  msg.setRepeatedFixed32List([1234]);
+  msg.setRepeatedFixed64List([0x1234567800000000]);
+  msg.setRepeatedSfixed32List([-1234]);
+  msg.setRepeatedSfixed64List([-0x1234567800000000]);
+  msg.setRepeatedFloatList([1.5]);
+  msg.setRepeatedDoubleList([-1.5]);
+  msg.setRepeatedBoolList([true]);
+  msg.setRepeatedStringList(['hello world']);
+  msg.setRepeatedBytesList([BYTES, BYTES]);
+  msg.setRepeatedGroupList([new proto.jspb.test.TestAllTypes.RepeatedGroup()]);
+  msg.getRepeatedGroupList()[0].setA(100);
+  submsg = new proto.jspb.test.ForeignMessage();
+  submsg.setC(1000);
+  msg.setRepeatedForeignMessageList([submsg]);
+  msg.setRepeatedForeignEnumList([proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+  msg.setPackedRepeatedInt32List([-42]);
+  msg.setPackedRepeatedInt64List([-0x7fffffff00000000]);
+  msg.setPackedRepeatedUint32List([0x80000000]);
+  msg.setPackedRepeatedUint64List([0xf000000000000000]);
+  msg.setPackedRepeatedSint32List([-100]);
+  msg.setPackedRepeatedSint64List([-0x8000000000000000]);
+  msg.setPackedRepeatedFixed32List([1234]);
+  msg.setPackedRepeatedFixed64List([0x1234567800000000]);
+  msg.setPackedRepeatedSfixed32List([-1234]);
+  msg.setPackedRepeatedSfixed64List([-0x1234567800000000]);
+  msg.setPackedRepeatedFloatList([1.5]);
+  msg.setPackedRepeatedDoubleList([-1.5]);
+  msg.setPackedRepeatedBoolList([true]);
+
+}
+
+
+/**
+ * Helper: compare a bytes field to an expected value
+ * @param {Uint8Array|string} arr
+ * @param {Uint8Array} expected
+ * @return {boolean}
+ */
+function bytesCompare(arr, expected) {
+  if (goog.isString(arr)) {
+    arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+  }
+  if (arr.length != expected.length) {
+    return false;
+  }
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] != expected[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+/**
+ * Helper: verify contents of given TestAllTypes message as set by
+ * fillAllFields().
+ * @param {proto.jspb.test.TestAllTypes} original
+ * @param {proto.jspb.test.TestAllTypes} copy
+ */
+function checkAllFields(original, copy) {
+  assertTrue(jspb.Message.equals(original, copy));
+
+  assertEquals(copy.getOptionalInt32(), -42);
+  assertEquals(copy.getOptionalInt64(), -0x7fffffff00000000);
+  assertEquals(copy.getOptionalUint32(), 0x80000000);
+  assertEquals(copy.getOptionalUint64(), 0xf000000000000000);
+  assertEquals(copy.getOptionalSint32(), -100);
+  assertEquals(copy.getOptionalSint64(), -0x8000000000000000);
+  assertEquals(copy.getOptionalFixed32(), 1234);
+  assertEquals(copy.getOptionalFixed64(), 0x1234567800000000);
+  assertEquals(copy.getOptionalSfixed32(), -1234);
+  assertEquals(copy.getOptionalSfixed64(), -0x1234567800000000);
+  assertEquals(copy.getOptionalFloat(), 1.5);
+  assertEquals(copy.getOptionalDouble(), -1.5);
+  assertEquals(copy.getOptionalBool(), true);
+  assertEquals(copy.getOptionalString(), 'hello world');
+  assertEquals(true, bytesCompare(copy.getOptionalBytes(), BYTES));
+  assertEquals(true, bytesCompare(copy.getOptionalBytes_asU8(), BYTES));
+  assertEquals(
+      copy.getOptionalBytes_asB64(), goog.crypt.base64.encodeByteArray(BYTES));
+
+  assertEquals(copy.getOptionalGroup().getA(), 100);
+  assertEquals(copy.getOptionalForeignMessage().getC(), 16);
+  assertEquals(copy.getOptionalForeignEnum(),
+      proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+
+
+  assertEquals(copy.getOneofString(), 'oneof');
+  assertEquals(copy.getOneofFieldCase(),
+      proto.jspb.test.TestAllTypes.OneofFieldCase.ONEOF_STRING);
+
+  assertElementsEquals(copy.getRepeatedInt32List(), [-42]);
+  assertElementsEquals(copy.getRepeatedInt64List(), [-0x7fffffff00000000]);
+  assertElementsEquals(copy.getRepeatedUint32List(), [0x80000000]);
+  assertElementsEquals(copy.getRepeatedUint64List(), [0xf000000000000000]);
+  assertElementsEquals(copy.getRepeatedSint32List(), [-100]);
+  assertElementsEquals(copy.getRepeatedSint64List(), [-0x8000000000000000]);
+  assertElementsEquals(copy.getRepeatedFixed32List(), [1234]);
+  assertElementsEquals(copy.getRepeatedFixed64List(), [0x1234567800000000]);
+  assertElementsEquals(copy.getRepeatedSfixed32List(), [-1234]);
+  assertElementsEquals(copy.getRepeatedSfixed64List(), [-0x1234567800000000]);
+  assertElementsEquals(copy.getRepeatedFloatList(), [1.5]);
+  assertElementsEquals(copy.getRepeatedDoubleList(), [-1.5]);
+  assertElementsEquals(copy.getRepeatedBoolList(), [true]);
+  assertElementsEquals(copy.getRepeatedStringList(), ['hello world']);
+  assertEquals(copy.getRepeatedBytesList().length, 2);
+  assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[0], BYTES));
+  assertEquals(true, bytesCompare(copy.getRepeatedBytesList()[0], BYTES));
+  assertEquals(true, bytesCompare(copy.getRepeatedBytesList_asU8()[1], BYTES));
+  assertEquals(copy.getRepeatedBytesList_asB64()[0], BYTES_B64);
+  assertEquals(copy.getRepeatedBytesList_asB64()[1], BYTES_B64);
+  assertEquals(copy.getRepeatedGroupList().length, 1);
+  assertEquals(copy.getRepeatedGroupList()[0].getA(), 100);
+  assertEquals(copy.getRepeatedForeignMessageList().length, 1);
+  assertEquals(copy.getRepeatedForeignMessageList()[0].getC(), 1000);
+  assertElementsEquals(copy.getRepeatedForeignEnumList(),
+      [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+  assertElementsEquals(copy.getPackedRepeatedInt32List(), [-42]);
+  assertElementsEquals(copy.getPackedRepeatedInt64List(),
+      [-0x7fffffff00000000]);
+  assertElementsEquals(copy.getPackedRepeatedUint32List(), [0x80000000]);
+  assertElementsEquals(copy.getPackedRepeatedUint64List(),
+      [0xf000000000000000]);
+  assertElementsEquals(copy.getPackedRepeatedSint32List(), [-100]);
+  assertElementsEquals(copy.getPackedRepeatedSint64List(),
+      [-0x8000000000000000]);
+  assertElementsEquals(copy.getPackedRepeatedFixed32List(), [1234]);
+  assertElementsEquals(copy.getPackedRepeatedFixed64List(),
+      [0x1234567800000000]);
+  assertElementsEquals(copy.getPackedRepeatedSfixed32List(), [-1234]);
+  assertElementsEquals(copy.getPackedRepeatedSfixed64List(),
+      [-0x1234567800000000]);
+  assertElementsEquals(copy.getPackedRepeatedFloatList(), [1.5]);
+  assertElementsEquals(copy.getPackedRepeatedDoubleList(), [-1.5]);
+
+}
+
+
+/**
+ * Helper: verify that all expected extensions are present.
+ * @param {!proto.jspb.test.TestExtendable} msg
+ */
+function checkExtensions(msg) {
+  assertEquals(-42,
+      msg.getExtension(proto.jspb.test.extendOptionalInt32));
+  assertEquals(-0x7fffffff00000000,
+      msg.getExtension(proto.jspb.test.extendOptionalInt64));
+  assertEquals(0x80000000,
+      msg.getExtension(proto.jspb.test.extendOptionalUint32));
+  assertEquals(0xf000000000000000,
+      msg.getExtension(proto.jspb.test.extendOptionalUint64));
+  assertEquals(-100,
+      msg.getExtension(proto.jspb.test.extendOptionalSint32));
+  assertEquals(-0x8000000000000000,
+      msg.getExtension(proto.jspb.test.extendOptionalSint64));
+  assertEquals(1234,
+      msg.getExtension(proto.jspb.test.extendOptionalFixed32));
+  assertEquals(0x1234567800000000,
+      msg.getExtension(proto.jspb.test.extendOptionalFixed64));
+  assertEquals(-1234,
+      msg.getExtension(proto.jspb.test.extendOptionalSfixed32));
+  assertEquals(-0x1234567800000000,
+      msg.getExtension(proto.jspb.test.extendOptionalSfixed64));
+  assertEquals(1.5,
+      msg.getExtension(proto.jspb.test.extendOptionalFloat));
+  assertEquals(-1.5,
+      msg.getExtension(proto.jspb.test.extendOptionalDouble));
+  assertEquals(true,
+      msg.getExtension(proto.jspb.test.extendOptionalBool));
+  assertEquals('hello world',
+      msg.getExtension(proto.jspb.test.extendOptionalString));
+  assertEquals(
+      true, bytesCompare(
+                msg.getExtension(proto.jspb.test.extendOptionalBytes), BYTES));
+  assertEquals(16,
+      msg.getExtension(
+          proto.jspb.test.ExtendsWithMessage.optionalExtension).getFoo());
+
+
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedInt32List),
+      [-42]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedInt64List),
+      [-0x7fffffff00000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedUint32List),
+      [0x80000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedUint64List),
+      [0xf000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSint32List),
+      [-100]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSint64List),
+      [-0x8000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedFixed32List),
+      [1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedFixed64List),
+      [0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSfixed32List),
+      [-1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedSfixed64List),
+      [-0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedFloatList),
+      [1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedDoubleList),
+      [-1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedBoolList),
+      [true]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedStringList),
+      ['hello world']);
+  assertEquals(
+      true,
+      bytesCompare(
+          msg.getExtension(proto.jspb.test.extendRepeatedBytesList)[0], BYTES));
+  assertEquals(1000,
+      msg.getExtension(
+          proto.jspb.test.ExtendsWithMessage.repeatedExtensionList)[0]
+      .getFoo());
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendRepeatedForeignEnumList),
+      [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedInt32List),
+      [-42]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedInt64List),
+      [-0x7fffffff00000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedUint32List),
+      [0x80000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedUint64List),
+      [0xf000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSint32List),
+      [-100]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSint64List),
+      [-0x8000000000000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed32List),
+      [1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed64List),
+      [0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed32List),
+      [-1234]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed64List),
+      [-0x1234567800000000]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedFloatList),
+      [1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedDoubleList),
+      [-1.5]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedBoolList),
+      [true]);
+  assertElementsEquals(
+      msg.getExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList),
+      [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+}
+
+
+describe('protoBinaryTest', function() {
+  /**
+   * Tests a basic serialization-deserializaton round-trip with all supported
+   * field types (on the TestAllTypes message type).
+   */
+  it('testRoundTrip', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+    fillAllFields(msg);
+    var encoded = msg.serializeBinary();
+    var decoded = proto.jspb.test.TestAllTypes.deserializeBinary(encoded);
+    checkAllFields(msg, decoded);
+  });
+
+  /**
+   * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+   */
+  it('testBytesFieldsGettersInterop', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+    // Set from a base64 string and check all the getters work.
+    msg.setOptionalBytes(BYTES_B64);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    // Test binary serialize round trip doesn't break it.
+    msg = proto.jspb.test.TestAllTypes.deserializeBinary(msg.serializeBinary());
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg = new proto.jspb.test.TestAllTypes();
+    // Set from a Uint8Array and check all the getters work.
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+  });
+
+  /**
+   * Test that bytes setters will receive result of any of the getters.
+   */
+  it('testBytesFieldsSettersInterop', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg.setOptionalBytes(msg.getOptionalBytes());
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+    msg.setOptionalBytes(msg.getOptionalBytes_asB64());
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+    msg.setOptionalBytes(msg.getOptionalBytes_asU8());
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+  });
+
+  /**
+   * Test that bytes setters will receive result of any of the getters.
+   */
+  it('testRepeatedBytesGetters', function() {
+    var msg = new proto.jspb.test.TestAllTypes();
+
+    function assertGetters() {
+      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[0]));
+      assertTrue(goog.isString(msg.getRepeatedBytesList_asB64()[1]));
+      assertTrue(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array);
+      assertTrue(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array);
+
+      assertTrue(bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList()[1], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[0], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asB64()[1], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[0], BYTES));
+      assertTrue(bytesCompare(msg.getRepeatedBytesList_asU8()[1], BYTES));
+    }
+
+    msg.setRepeatedBytesList([BYTES, BYTES]);
+    assertGetters();
+
+    msg.setRepeatedBytesList([BYTES_B64, BYTES_B64]);
+    assertGetters();
+
+    msg.setRepeatedBytesList([]);
+    assertEquals(0, msg.getRepeatedBytesList().length);
+    assertEquals(0, msg.getRepeatedBytesList_asB64().length);
+    assertEquals(0, msg.getRepeatedBytesList_asU8().length);
+  });
+
+  /**
+   * Helper: fill all extension values.
+   * @param {proto.jspb.test.TestExtendable} msg
+   */
+  function fillExtensions(msg) {
+    msg.setExtension(
+        proto.jspb.test.extendOptionalInt32, -42);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalInt64, -0x7fffffff00000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalUint32, 0x80000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalUint64, 0xf000000000000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSint32, -100);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSint64, -0x8000000000000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalFixed32, 1234);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalFixed64, 0x1234567800000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSfixed32, -1234);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalSfixed64, -0x1234567800000000);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalFloat, 1.5);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalDouble, -1.5);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalBool, true);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalString, 'hello world');
+    msg.setExtension(proto.jspb.test.extendOptionalBytes, BYTES);
+    var submsg = new proto.jspb.test.ExtendsWithMessage();
+    submsg.setFoo(16);
+    msg.setExtension(
+        proto.jspb.test.ExtendsWithMessage.optionalExtension, submsg);
+    msg.setExtension(
+        proto.jspb.test.extendOptionalForeignEnum,
+        proto.jspb.test.ForeignEnum.FOREIGN_FOO);
+
+
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedInt32List, [-42]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedInt64List, [-0x7fffffff00000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedUint32List, [0x80000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedUint64List, [0xf000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSint32List, [-100]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSint64List, [-0x8000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedFixed32List, [1234]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedFixed64List, [0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSfixed32List, [-1234]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedSfixed64List, [-0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedFloatList, [1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedDoubleList, [-1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedBoolList, [true]);
+    msg.setExtension(
+        proto.jspb.test.extendRepeatedStringList, ['hello world']);
+    msg.setExtension(proto.jspb.test.extendRepeatedBytesList, [BYTES]);
+    submsg = new proto.jspb.test.ExtendsWithMessage();
+    submsg.setFoo(1000);
+    msg.setExtension(
+        proto.jspb.test.ExtendsWithMessage.repeatedExtensionList, [submsg]);
+    msg.setExtension(proto.jspb.test.extendRepeatedForeignEnumList,
+        [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedInt32List, [-42]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedInt64List, [-0x7fffffff00000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedUint32List, [0x80000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedUint64List, [0xf000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSint32List, [-100]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSint64List, [-0x8000000000000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedFixed32List, [1234]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedFixed64List, [0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSfixed32List, [-1234]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedSfixed64List,
+        [-0x1234567800000000]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedFloatList, [1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedDoubleList, [-1.5]);
+    msg.setExtension(
+        proto.jspb.test.extendPackedRepeatedBoolList, [true]);
+    msg.setExtension(proto.jspb.test.extendPackedRepeatedForeignEnumList,
+        [proto.jspb.test.ForeignEnum.FOREIGN_FOO]);
+
+  }
+
+
+  /**
+   * Tests extension serialization and deserialization.
+   */
+  it('testExtensions', function() {
+    var msg = new proto.jspb.test.TestExtendable();
+    fillExtensions(msg);
+    var encoded = msg.serializeBinary();
+    var decoded = proto.jspb.test.TestExtendable.deserializeBinary(encoded);
+    checkExtensions(decoded);
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/reader_test.js b/js/compatibility_tests/v3.1.0/binary/reader_test.js
new file mode 100644
index 0000000..9571138
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/reader_test.js
@@ -0,0 +1,922 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer reader.
+ *
+ * There are two particular magic numbers that need to be pointed out -
+ * 2^64-1025 is the largest number representable as both a double and an
+ * unsigned 64-bit integer, and 2^63-513 is the largest number representable as
+ * both a double and a signed 64-bit integer.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author [email protected] (Austin Appleby)
+ */
+
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryDecoder');
+goog.require('jspb.BinaryReader');
+goog.require('jspb.BinaryWriter');
+
+
+
+describe('binaryReaderTest', function() {
+  /**
+   * Tests the reader instance cache.
+   */
+  it('testInstanceCaches', /** @suppress {visibility} */ function() {
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    writer.writeMessage(1, dummyMessage, goog.nullFunction);
+    writer.writeMessage(2, dummyMessage, goog.nullFunction);
+
+    var buffer = writer.getResultBuffer();
+
+    // Empty the instance caches.
+    jspb.BinaryReader.instanceCache_ = [];
+
+    // Allocating and then freeing three decoders should leave us with three in
+    // the cache.
+
+    var decoder1 = jspb.BinaryDecoder.alloc();
+    var decoder2 = jspb.BinaryDecoder.alloc();
+    var decoder3 = jspb.BinaryDecoder.alloc();
+    decoder1.free();
+    decoder2.free();
+    decoder3.free();
+
+    assertEquals(3, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+    // Allocating and then freeing a reader should remove one decoder from its
+    // cache, but it should stay stuck to the reader afterwards since we can't
+    // have a reader without a decoder.
+    jspb.BinaryReader.alloc().free();
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
+
+    // Allocating a reader should remove a reader from the cache.
+    var reader = jspb.BinaryReader.alloc(buffer);
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+    // Processing the message reuses the current reader.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+    });
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+    });
+
+    assertEquals(false, reader.nextField());
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(0, jspb.BinaryReader.instanceCache_.length);
+
+    // Freeing the reader should put it back into the cache.
+    reader.free();
+
+    assertEquals(2, jspb.BinaryDecoder.instanceCache_.length);
+    assertEquals(1, jspb.BinaryReader.instanceCache_.length);
+  });
+
+
+  /**
+   * @param {number} x
+   * @return {number}
+   */
+  function truncate(x) {
+    var temp = new Float32Array(1);
+    temp[0] = x;
+    return temp[0];
+  }
+
+
+  /**
+   * Verifies that misuse of the reader class triggers assertions.
+   */
+  it('testReadErrors', /** @suppress {checkTypes|visibility} */ function() {
+    // Calling readMessage on a non-delimited field should trigger an
+    // assertion.
+    var reader = jspb.BinaryReader.alloc([8, 1]);
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    reader.nextField();
+    assertThrows(function() {
+      reader.readMessage(dummyMessage, goog.nullFunction);
+    });
+
+    // Reading past the end of the stream should trigger an assertion.
+    reader = jspb.BinaryReader.alloc([9, 1]);
+    reader.nextField();
+    assertThrows(function() {reader.readFixed64()});
+
+    // Reading past the end of a submessage should trigger an assertion.
+    reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]);
+    reader.nextField();
+    reader.readMessage(dummyMessage, function() {
+      reader.nextField();
+      assertThrows(function() {reader.readFixed32()});
+    });
+
+    // Skipping an invalid field should trigger an assertion.
+    reader = jspb.BinaryReader.alloc([12, 1]);
+    reader.nextWireType_ = 1000;
+    assertThrows(function() {reader.skipField()});
+
+    // Reading fields with the wrong wire type should assert.
+    reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]);
+    reader.nextField();
+    assertThrows(function() {reader.readInt32()});
+    assertThrows(function() {reader.readInt32String()});
+    assertThrows(function() {reader.readInt64()});
+    assertThrows(function() {reader.readInt64String()});
+    assertThrows(function() {reader.readUint32()});
+    assertThrows(function() {reader.readUint32String()});
+    assertThrows(function() {reader.readUint64()});
+    assertThrows(function() {reader.readUint64String()});
+    assertThrows(function() {reader.readSint32()});
+    assertThrows(function() {reader.readBool()});
+    assertThrows(function() {reader.readEnum()});
+
+    reader = jspb.BinaryReader.alloc([8, 1]);
+    reader.nextField();
+    assertThrows(function() {reader.readFixed32()});
+    assertThrows(function() {reader.readFixed64()});
+    assertThrows(function() {reader.readSfixed32()});
+    assertThrows(function() {reader.readSfixed64()});
+    assertThrows(function() {reader.readFloat()});
+    assertThrows(function() {reader.readDouble()});
+
+    assertThrows(function() {reader.readString()});
+    assertThrows(function() {reader.readBytes()});
+  });
+
+
+  /**
+   * Tests encoding and decoding of unsigned field types.
+   * @param {Function} readField
+   * @param {Function} writeField
+   * @param {number} epsilon
+   * @param {number} upperLimit
+   * @param {Function} filter
+   * @private
+   * @suppress {missingProperties}
+   */
+  var doTestUnsignedField_ = function(readField,
+      writeField, epsilon, upperLimit, filter) {
+    assertNotNull(readField);
+    assertNotNull(writeField);
+
+    var writer = new jspb.BinaryWriter();
+
+    // Encode zero and limits.
+    writeField.call(writer, 1, filter(0));
+    writeField.call(writer, 2, filter(epsilon));
+    writeField.call(writer, 3, filter(upperLimit));
+
+    // Encode positive values.
+    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+      writeField.call(writer, 4, filter(cursor));
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    // Check zero and limits.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(filter(0), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(filter(epsilon), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(3, reader.getFieldNumber());
+    assertEquals(filter(upperLimit), readField.call(reader));
+
+    // Check positive values.
+    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+      reader.nextField();
+      if (4 != reader.getFieldNumber()) throw 'fail!';
+      if (filter(cursor) != readField.call(reader)) throw 'fail!';
+    }
+  };
+
+
+  /**
+   * Tests encoding and decoding of signed field types.
+   * @param {Function} readField
+   * @param {Function} writeField
+   * @param {number} epsilon
+   * @param {number} lowerLimit
+   * @param {number} upperLimit
+   * @param {Function} filter
+   * @private
+   * @suppress {missingProperties}
+   */
+  var doTestSignedField_ = function(readField,
+      writeField, epsilon, lowerLimit, upperLimit, filter) {
+    var writer = new jspb.BinaryWriter();
+
+    // Encode zero and limits.
+    writeField.call(writer, 1, filter(lowerLimit));
+    writeField.call(writer, 2, filter(-epsilon));
+    writeField.call(writer, 3, filter(0));
+    writeField.call(writer, 4, filter(epsilon));
+    writeField.call(writer, 5, filter(upperLimit));
+
+    var inputValues = [];
+
+    // Encode negative values.
+    for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) {
+      var val = filter(cursor);
+      writeField.call(writer, 6, val);
+      inputValues.push({
+        fieldNumber: 6,
+        value: val
+      });
+    }
+
+    // Encode positive values.
+    for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) {
+      var val = filter(cursor);
+      writeField.call(writer, 7, val);
+      inputValues.push({
+        fieldNumber: 7,
+        value: val
+      });
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    // Check zero and limits.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(filter(lowerLimit), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(filter(-epsilon), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(3, reader.getFieldNumber());
+    assertEquals(filter(0), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(4, reader.getFieldNumber());
+    assertEquals(filter(epsilon), readField.call(reader));
+
+    reader.nextField();
+    assertEquals(5, reader.getFieldNumber());
+    assertEquals(filter(upperLimit), readField.call(reader));
+
+    for (var i = 0; i < inputValues.length; i++) {
+      var expected = inputValues[i];
+      reader.nextField();
+      assertEquals(expected.fieldNumber, reader.getFieldNumber());
+      assertEquals(expected.value, readField.call(reader));
+    }
+  };
+
+
+  /**
+   * Tests fields that use varint encoding.
+   */
+  it('testVarintFields', function() {
+    assertNotUndefined(jspb.BinaryReader.prototype.readUint32);
+    assertNotUndefined(jspb.BinaryWriter.prototype.writeUint32);
+    assertNotUndefined(jspb.BinaryReader.prototype.readUint64);
+    assertNotUndefined(jspb.BinaryWriter.prototype.writeUint64);
+    assertNotUndefined(jspb.BinaryReader.prototype.readBool);
+    assertNotUndefined(jspb.BinaryWriter.prototype.writeBool);
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readUint32,
+        jspb.BinaryWriter.prototype.writeUint32,
+        1, Math.pow(2, 32) - 1, Math.round);
+
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readUint64,
+        jspb.BinaryWriter.prototype.writeUint64,
+        1, Math.pow(2, 64) - 1025, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readInt32,
+        jspb.BinaryWriter.prototype.writeInt32,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readInt64,
+        jspb.BinaryWriter.prototype.writeInt64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readEnum,
+        jspb.BinaryWriter.prototype.writeEnum,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readBool,
+        jspb.BinaryWriter.prototype.writeBool,
+        1, 1, function(x) { return !!x; });
+  });
+
+
+  /**
+   * Tests reading a field from hexadecimal string (format: '08 BE EF').
+   * @param {Function} readField
+   * @param {number} expected
+   * @param {string} hexString
+   */
+  function doTestHexStringVarint_(readField, expected, hexString) {
+    var bytesCount = (hexString.length + 1) / 3;
+    var bytes = new Uint8Array(bytesCount);
+    for (var i = 0; i < bytesCount; i++) {
+      bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16);
+    }
+    var reader = jspb.BinaryReader.alloc(bytes);
+    reader.nextField();
+    assertEquals(expected, readField.call(reader));
+  }
+
+
+  /**
+   * Tests non-canonical redundant varint decoding.
+   */
+  it('testRedundantVarintFields', function() {
+    assertNotNull(jspb.BinaryReader.prototype.readUint32);
+    assertNotNull(jspb.BinaryReader.prototype.readUint64);
+    assertNotNull(jspb.BinaryReader.prototype.readSint32);
+    assertNotNull(jspb.BinaryReader.prototype.readSint64);
+
+    // uint32 and sint32 take no more than 5 bytes
+    // 08 - field prefix (type = 0 means varint)
+    doTestHexStringVarint_(
+      jspb.BinaryReader.prototype.readUint32,
+      12, '08 8C 80 80 80 00');
+
+    // 11 stands for -6 in zigzag encoding
+    doTestHexStringVarint_(
+      jspb.BinaryReader.prototype.readSint32,
+      -6, '08 8B 80 80 80 00');
+
+    // uint64 and sint64 take no more than 10 bytes
+    // 08 - field prefix (type = 0 means varint)
+    doTestHexStringVarint_(
+      jspb.BinaryReader.prototype.readUint64,
+      12, '08 8C 80 80 80 80 80 80 80 80 00');
+
+    // 11 stands for -6 in zigzag encoding
+    doTestHexStringVarint_(
+      jspb.BinaryReader.prototype.readSint64,
+      -6, '08 8B 80 80 80 80 80 80 80 80 00');
+  });
+
+
+  /**
+   * Tests 64-bit fields that are handled as strings.
+   */
+  it('testStringInt64Fields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var testSignedData = [
+      '2730538252207801776',
+      '-2688470994844604560',
+      '3398529779486536359',
+      '3568577411627971000',
+      '272477188847484900',
+      '-6649058714086158188',
+      '-7695254765712060806',
+      '-4525541438037104029',
+      '-4993706538836508568',
+      '4990160321893729138'
+    ];
+    var testUnsignedData = [
+      '7822732630241694882',
+      '6753602971916687352',
+      '2399935075244442116',
+      '8724292567325338867',
+      '16948784802625696584',
+      '4136275908516066934',
+      '3575388346793700364',
+      '5167142028379259461',
+      '1557573948689737699',
+      '17100725280812548567'
+    ];
+
+    for (var i = 0; i < testSignedData.length; i++) {
+      writer.writeInt64String(2 * i + 1, testSignedData[i]);
+      writer.writeUint64String(2 * i + 2, testUnsignedData[i]);
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    for (var i = 0; i < testSignedData.length; i++) {
+      reader.nextField();
+      assertEquals(2 * i + 1, reader.getFieldNumber());
+      assertEquals(testSignedData[i], reader.readInt64String());
+      reader.nextField();
+      assertEquals(2 * i + 2, reader.getFieldNumber());
+      assertEquals(testUnsignedData[i], reader.readUint64String());
+    }
+  });
+
+
+  /**
+   * Tests fields that use zigzag encoding.
+   */
+  it('testZigzagFields', function() {
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSint32,
+        jspb.BinaryWriter.prototype.writeSint32,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSint64,
+        jspb.BinaryWriter.prototype.writeSint64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+  });
+
+
+  /**
+   * Tests fields that use fixed-length encoding.
+   */
+  it('testFixedFields', function() {
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readFixed32,
+        jspb.BinaryWriter.prototype.writeFixed32,
+        1, Math.pow(2, 32) - 1, Math.round);
+
+    doTestUnsignedField_(
+        jspb.BinaryReader.prototype.readFixed64,
+        jspb.BinaryWriter.prototype.writeFixed64,
+        1, Math.pow(2, 64) - 1025, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSfixed32,
+        jspb.BinaryWriter.prototype.writeSfixed32,
+        1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readSfixed64,
+        jspb.BinaryWriter.prototype.writeSfixed64,
+        1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round);
+  });
+
+
+  /**
+   * Tests floating point fields.
+   */
+  it('testFloatFields', function() {
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readFloat,
+        jspb.BinaryWriter.prototype.writeFloat,
+        jspb.BinaryConstants.FLOAT32_MIN,
+        -jspb.BinaryConstants.FLOAT32_MAX,
+        jspb.BinaryConstants.FLOAT32_MAX,
+        truncate);
+
+    doTestSignedField_(
+        jspb.BinaryReader.prototype.readDouble,
+        jspb.BinaryWriter.prototype.writeDouble,
+        jspb.BinaryConstants.FLOAT64_EPS * 10,
+        -jspb.BinaryConstants.FLOAT64_MIN,
+        jspb.BinaryConstants.FLOAT64_MIN,
+        function(x) { return x; });
+  });
+
+
+  /**
+   * Tests length-delimited string fields.
+   */
+  it('testStringFields', function() {
+    var s1 = 'The quick brown fox jumps over the lazy dog.';
+    var s2 = '人人生而自由,在尊嚴和權利上一律平等。';
+
+    var writer = new jspb.BinaryWriter();
+
+    writer.writeString(1, s1);
+    writer.writeString(2, s2);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(s1, reader.readString());
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(s2, reader.readString());
+  });
+
+
+  /**
+   * Tests length-delimited byte fields.
+   */
+  it('testByteFields', function() {
+    var message = [];
+    var lowerLimit = 1;
+    var upperLimit = 256;
+    var scale = 1.1;
+
+    var writer = new jspb.BinaryWriter();
+
+    for (var cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) {
+      var len = Math.round(cursor);
+      var bytes = [];
+      for (var i = 0; i < len; i++) bytes.push(i % 256);
+
+      writer.writeBytes(len, bytes);
+    }
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    for (var cursor = lowerLimit; reader.nextField(); cursor *= 1.1) {
+      var len = Math.round(cursor);
+      if (len != reader.getFieldNumber()) throw 'fail!';
+
+      var bytes = reader.readBytes();
+      if (len != bytes.length) throw 'fail!';
+      for (var i = 0; i < bytes.length; i++) {
+        if (i % 256 != bytes[i]) throw 'fail!';
+      }
+    }
+  });
+
+
+  /**
+   * Tests nested messages.
+   */
+  it('testNesting', function() {
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    writer.writeInt32(1, 100);
+
+    // Add one message with 3 int fields.
+    writer.writeMessage(2, dummyMessage, function() {
+      writer.writeInt32(3, 300);
+      writer.writeInt32(4, 400);
+      writer.writeInt32(5, 500);
+    });
+
+    // Add one empty message.
+    writer.writeMessage(6, dummyMessage, goog.nullFunction);
+
+    writer.writeInt32(7, 700);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    // Validate outermost message.
+
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(100, reader.readInt32());
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      // Validate embedded message 1.
+      reader.nextField();
+      assertEquals(3, reader.getFieldNumber());
+      assertEquals(300, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(4, reader.getFieldNumber());
+      assertEquals(400, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(5, reader.getFieldNumber());
+      assertEquals(500, reader.readInt32());
+
+      assertEquals(false, reader.nextField());
+    });
+
+    reader.nextField();
+    assertEquals(6, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      // Validate embedded message 2.
+
+      assertEquals(false, reader.nextField());
+    });
+
+    reader.nextField();
+    assertEquals(7, reader.getFieldNumber());
+    assertEquals(700, reader.readInt32());
+
+    assertEquals(false, reader.nextField());
+  });
+
+  /**
+   * Tests skipping fields of each type by interleaving them with sentinel
+   * values and skipping everything that's not a sentinel.
+   */
+  it('testSkipField', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var sentinel = 123456789;
+
+    // Write varint fields of different sizes.
+    writer.writeInt32(1, sentinel);
+    writer.writeInt32(1, 1);
+    writer.writeInt32(1, 1000);
+    writer.writeInt32(1, 1000000);
+    writer.writeInt32(1, 1000000000);
+
+    // Write fixed 64-bit encoded fields.
+    writer.writeInt32(2, sentinel);
+    writer.writeDouble(2, 1);
+    writer.writeFixed64(2, 1);
+    writer.writeSfixed64(2, 1);
+
+    // Write fixed 32-bit encoded fields.
+    writer.writeInt32(3, sentinel);
+    writer.writeFloat(3, 1);
+    writer.writeFixed32(3, 1);
+    writer.writeSfixed32(3, 1);
+
+    // Write delimited fields.
+    writer.writeInt32(4, sentinel);
+    writer.writeBytes(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
+    writer.writeString(4, 'The quick brown fox jumps over the lazy dog');
+
+    // Write a group with a nested group inside.
+    writer.writeInt32(5, sentinel);
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+    writer.writeGroup(5, dummyMessage, function() {
+      writer.writeInt64(42, 42);
+      writer.writeGroup(6, dummyMessage, function() {
+        writer.writeInt64(84, 42);
+      });
+    });
+
+    // Write final sentinel.
+    writer.writeInt32(6, sentinel);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    function skip(field, count) {
+      for (var i = 0; i < count; i++) {
+        reader.nextField();
+        if (field != reader.getFieldNumber()) throw 'fail!';
+        reader.skipField();
+      }
+    }
+
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(1, 4);
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(2, 3);
+
+    reader.nextField();
+    assertEquals(3, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(3, 3);
+
+    reader.nextField();
+    assertEquals(4, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(4, 2);
+
+    reader.nextField();
+    assertEquals(5, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+    skip(5, 1);
+
+    reader.nextField();
+    assertEquals(6, reader.getFieldNumber());
+    assertEquals(sentinel, reader.readInt32());
+  });
+
+
+  /**
+   * Tests packed fields.
+   */
+  it('testPackedFields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var sentinel = 123456789;
+
+    var unsignedData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    var signedData = [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10];
+    var floatData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
+    var doubleData = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10];
+    var boolData = [true, false, true, true, false, false, true, false];
+
+    for (var i = 0; i < floatData.length; i++) {
+      floatData[i] = truncate(floatData[i]);
+    }
+
+    writer.writeInt32(1, sentinel);
+
+    writer.writePackedInt32(2, signedData);
+    writer.writePackedInt64(2, signedData);
+    writer.writePackedUint32(2, unsignedData);
+    writer.writePackedUint64(2, unsignedData);
+    writer.writePackedSint32(2, signedData);
+    writer.writePackedSint64(2, signedData);
+    writer.writePackedFixed32(2, unsignedData);
+    writer.writePackedFixed64(2, unsignedData);
+    writer.writePackedSfixed32(2, signedData);
+    writer.writePackedSfixed64(2, signedData);
+    writer.writePackedFloat(2, floatData);
+    writer.writePackedDouble(2, doubleData);
+    writer.writePackedBool(2, boolData);
+    writer.writePackedEnum(2, unsignedData);
+
+    writer.writeInt32(3, sentinel);
+
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    reader.nextField();
+    assertEquals(sentinel, reader.readInt32());
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedInt32(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedInt64(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedUint32(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedUint64(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSint32(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSint64(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedFixed32(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedFixed64(), unsignedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSfixed32(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedSfixed64(), signedData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedFloat(), floatData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedDouble(), doubleData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedBool(), boolData);
+
+    reader.nextField();
+    assertElementsEquals(reader.readPackedEnum(), unsignedData);
+
+    reader.nextField();
+    assertEquals(sentinel, reader.readInt32());
+  });
+
+
+  /**
+   * Byte blobs inside nested messages should always have their byte offset set
+   * relative to the start of the outermost blob, not the start of their parent
+   * blob.
+   */
+  it('testNestedBlobs', function() {
+    // Create a proto consisting of two nested messages, with the inner one
+    // containing a blob of bytes.
+
+    var fieldTag = (1 << 3) | jspb.BinaryConstants.WireType.DELIMITED;
+    var blob = [1, 2, 3, 4, 5];
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    writer.writeMessage(1, dummyMessage, function() {
+      writer.writeMessage(1, dummyMessage, function() {
+        writer.writeBytes(1, blob);
+      });
+    });
+
+    // Peel off the outer two message layers. Each layer should have two bytes
+    // of overhead, one for the field tag and one for the length of the inner
+    // blob.
+
+    var decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer());
+    assertEquals(fieldTag, decoder1.readUnsignedVarint32());
+    assertEquals(blob.length + 4, decoder1.readUnsignedVarint32());
+
+    var decoder2 = new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4));
+    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
+    assertEquals(blob.length + 2, decoder2.readUnsignedVarint32());
+
+    assertEquals(fieldTag, decoder2.readUnsignedVarint32());
+    assertEquals(blob.length, decoder2.readUnsignedVarint32());
+    var bytes = decoder2.readBytes(blob.length);
+
+    assertElementsEquals(bytes, blob);
+  });
+
+
+  /**
+   * Tests read callbacks.
+   */
+  it('testReadCallbacks', function() {
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    // Add an int, a submessage, and another int.
+    writer.writeInt32(1, 100);
+
+    writer.writeMessage(2, dummyMessage, function() {
+      writer.writeInt32(3, 300);
+      writer.writeInt32(4, 400);
+      writer.writeInt32(5, 500);
+    });
+
+    writer.writeInt32(7, 700);
+
+    // Create the reader and register a custom read callback.
+    var reader = jspb.BinaryReader.alloc(writer.getResultBuffer());
+
+    /**
+     * @param {!jspb.BinaryReader} reader
+     * @return {*}
+     */
+    function readCallback(reader) {
+      reader.nextField();
+      assertEquals(3, reader.getFieldNumber());
+      assertEquals(300, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(4, reader.getFieldNumber());
+      assertEquals(400, reader.readInt32());
+
+      reader.nextField();
+      assertEquals(5, reader.getFieldNumber());
+      assertEquals(500, reader.readInt32());
+
+      assertEquals(false, reader.nextField());
+    };
+
+    reader.registerReadCallback('readCallback', readCallback);
+
+    // Read the container message.
+    reader.nextField();
+    assertEquals(1, reader.getFieldNumber());
+    assertEquals(100, reader.readInt32());
+
+    reader.nextField();
+    assertEquals(2, reader.getFieldNumber());
+    reader.readMessage(dummyMessage, function() {
+      // Decode the embedded message using the registered callback.
+      reader.runReadCallback('readCallback');
+    });
+
+    reader.nextField();
+    assertEquals(7, reader.getFieldNumber());
+    assertEquals(700, reader.readInt32());
+
+    assertEquals(false, reader.nextField());
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/utils_test.js b/js/compatibility_tests/v3.1.0/binary/utils_test.js
new file mode 100644
index 0000000..d27e5ea
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/utils_test.js
@@ -0,0 +1,668 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's helper functions.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author [email protected] (Austin Appleby)
+ */
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryConstants');
+goog.require('jspb.BinaryWriter');
+goog.require('jspb.utils');
+
+
+/**
+ * @param {number} x
+ * @return {number}
+ */
+function truncate(x) {
+  var temp = new Float32Array(1);
+  temp[0] = x;
+  return temp[0];
+}
+
+
+/**
+ * Converts an 64-bit integer in split representation to a 64-bit hash string
+ * (8 bits encoded per character).
+ * @param {number} bitsLow The low 32 bits of the split 64-bit integer.
+ * @param {number} bitsHigh The high 32 bits of the split 64-bit integer.
+ * @return {string} The encoded hash string, 8 bits per character.
+ */
+function toHashString(bitsLow, bitsHigh) {
+  return String.fromCharCode((bitsLow >>> 0) & 0xFF,
+                             (bitsLow >>> 8) & 0xFF,
+                             (bitsLow >>> 16) & 0xFF,
+                             (bitsLow >>> 24) & 0xFF,
+                             (bitsHigh >>> 0) & 0xFF,
+                             (bitsHigh >>> 8) & 0xFF,
+                             (bitsHigh >>> 16) & 0xFF,
+                             (bitsHigh >>> 24) & 0xFF);
+}
+
+
+describe('binaryUtilsTest', function() {
+  /**
+   * Tests lossless binary-to-decimal conversion.
+   */
+  it('testDecimalConversion', function() {
+    // Check some magic numbers.
+    var result =
+        jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304);
+    assertEquals('10000000000000000001', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b);
+    assertEquals('123456789123456789', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c);
+    assertEquals('12345678901234567890', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8);
+    assertEquals('9876543210987654321', result);
+
+    // Check limits.
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000);
+    assertEquals('0', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF);
+    assertEquals('18446744073709551615', result);
+
+    // Check each bit of the low dword.
+    for (var i = 0; i < 32; i++) {
+      var low = (1 << i) >>> 0;
+      result = jspb.utils.joinUnsignedDecimalString(low, 0);
+      assertEquals('' + Math.pow(2, i), result);
+    }
+
+    // Check the first 20 bits of the high dword.
+    for (var i = 0; i < 20; i++) {
+      var high = (1 << i) >>> 0;
+      result = jspb.utils.joinUnsignedDecimalString(0, high);
+      assertEquals('' + Math.pow(2, 32 + i), result);
+    }
+
+    // V8's internal double-to-string conversion is inaccurate for values above
+    // 2^52, even if they're representable integers - check the rest of the bits
+    // manually against the correct string representations of 2^N.
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000);
+    assertEquals('4503599627370496', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000);
+    assertEquals('9007199254740992', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000);
+    assertEquals('18014398509481984', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000);
+    assertEquals('36028797018963968', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000);
+    assertEquals('72057594037927936', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000);
+    assertEquals('144115188075855872', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000);
+    assertEquals('288230376151711744', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000);
+    assertEquals('576460752303423488', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000);
+    assertEquals('1152921504606846976', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000);
+    assertEquals('2305843009213693952', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000);
+    assertEquals('4611686018427387904', result);
+
+    result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000);
+    assertEquals('9223372036854775808', result);
+  });
+
+
+  /**
+   * Going from hash strings to decimal strings should also be lossless.
+   */
+  it('testHashToDecimalConversion', function() {
+    var result;
+    var convert = jspb.utils.hash64ToDecimalString;
+
+    result = convert(toHashString(0x00000000, 0x00000000), false);
+    assertEquals('0', result);
+
+    result = convert(toHashString(0x00000000, 0x00000000), true);
+    assertEquals('0', result);
+
+    result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false);
+    assertEquals('18446744073709551615', result);
+
+    result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true);
+    assertEquals('-1', result);
+
+    result = convert(toHashString(0x00000000, 0x80000000), false);
+    assertEquals('9223372036854775808', result);
+
+    result = convert(toHashString(0x00000000, 0x80000000), true);
+    assertEquals('-9223372036854775808', result);
+
+    result = convert(toHashString(0xacd05f15, 0x01b69b4b), false);
+    assertEquals('123456789123456789', result);
+
+    result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true);
+    assertEquals('-123456789123456789', result);
+
+    // And converting arrays of hashes should work the same way.
+    result = jspb.utils.hash64ArrayToDecimalStrings([
+      toHashString(0xFFFFFFFF, 0xFFFFFFFF),
+      toHashString(0x00000000, 0x80000000),
+      toHashString(0xacd05f15, 0x01b69b4b)], false);
+    assertEquals(3, result.length);
+    assertEquals('18446744073709551615', result[0]);
+    assertEquals('9223372036854775808', result[1]);
+    assertEquals('123456789123456789', result[2]);
+  });
+
+  /*
+   * Going from decimal strings to hash strings should be lossless.
+   */
+  it('testDecimalToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.decimalStringToHash64;
+
+    result = convert('0');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+    result = convert('-1');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    result = convert('18446744073709551615');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    result = convert('9223372036854775808');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+    result = convert('-9223372036854775808');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80]), result);
+
+    result = convert('123456789123456789');
+    assertEquals(String.fromCharCode.apply(null,
+      [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01]), result);
+
+    result = convert('-123456789123456789');
+    assertEquals(String.fromCharCode.apply(null,
+      [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE]), result);
+  });
+
+  /**
+   * Going from hash strings to hex strings should be lossless.
+   */
+  it('testHashToHexConversion', function() {
+    var result;
+    var convert = jspb.utils.hash64ToHexString;
+
+    result = convert(toHashString(0x00000000, 0x00000000));
+    assertEquals('0x0000000000000000', result);
+
+    result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF));
+    assertEquals('0xffffffffffffffff', result);
+
+    result = convert(toHashString(0x12345678, 0x9ABCDEF0));
+    assertEquals('0x9abcdef012345678', result);
+  });
+
+
+  /**
+   * Going from hex strings to hash strings should be lossless.
+   */
+  it('testHexToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.hexStringToHash64;
+
+    result = convert('0x0000000000000000');
+    assertEquals(String.fromCharCode.apply(null,
+        [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]), result);
+
+    result = convert('0xffffffffffffffff');
+    assertEquals(String.fromCharCode.apply(null,
+        [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]), result);
+
+    // Hex string is big-endian, hash string is little-endian.
+    result = convert('0x123456789ABCDEF0');
+    assertEquals(String.fromCharCode.apply(null,
+        [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12]), result);
+
+    // Capitalization should not matter.
+    result = convert('0x0000abcdefABCDEF');
+    assertEquals(String.fromCharCode.apply(null,
+        [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00]), result);
+  });
+
+
+  /**
+   * Going from numbers to hash strings should be lossless for up to 53 bits of
+   * precision.
+   */
+  it('testNumberToHashConversion', function() {
+    var result;
+    var convert = jspb.utils.numberToHash64;
+
+    result = convert(0x0000000000000);
+    assertEquals('0x0000000000000000', jspb.utils.hash64ToHexString(result));
+
+    result = convert(0xFFFFFFFFFFFFF);
+    assertEquals('0x000fffffffffffff', jspb.utils.hash64ToHexString(result));
+
+    result = convert(0x123456789ABCD);
+    assertEquals('0x000123456789abcd', jspb.utils.hash64ToHexString(result));
+
+    result = convert(0xDCBA987654321);
+    assertEquals('0x000dcba987654321', jspb.utils.hash64ToHexString(result));
+
+    // 53 bits of precision should not be truncated.
+    result = convert(0x10000000000001);
+    assertEquals('0x0010000000000001', jspb.utils.hash64ToHexString(result));
+
+    // 54 bits of precision should be truncated.
+    result = convert(0x20000000000001);
+    assertNotEquals(
+        '0x0020000000000001', jspb.utils.hash64ToHexString(result));
+  });
+
+
+  /**
+   * Sanity check the behavior of Javascript's strings when doing funny things
+   * with unicode characters.
+   */
+  it('sanityCheckUnicodeStrings', function() {
+    var strings = new Array(65536);
+
+    // All possible unsigned 16-bit values should be storable in a string, they
+    // shouldn't do weird things with the length of the string, and they should
+    // come back out of the string unchanged.
+    for (var i = 0; i < 65536; i++) {
+      strings[i] = 'a' + String.fromCharCode(i) + 'a';
+      if (3 != strings[i].length) throw 'fail!';
+      if (i != strings[i].charCodeAt(1)) throw 'fail!';
+    }
+
+    // Each unicode character should compare equal to itself and not equal to a
+    // different unicode character.
+    for (var i = 0; i < 65536; i++) {
+      if (strings[i] != strings[i]) throw 'fail!';
+      if (strings[i] == strings[(i + 1) % 65536]) throw 'fail!';
+    }
+  });
+
+
+  /**
+   * Tests conversion from 32-bit floating point numbers to split64 numbers.
+   */
+  it('testFloat32ToSplit64', function() {
+    var f32_eps = jspb.BinaryConstants.FLOAT32_EPS;
+    var f32_min = jspb.BinaryConstants.FLOAT32_MIN;
+    var f32_max = jspb.BinaryConstants.FLOAT32_MAX;
+
+    // NaN.
+    jspb.utils.splitFloat32(NaN);
+    if (!isNaN(jspb.utils.joinFloat32(jspb.utils.split64Low,
+                                      jspb.utils.split64High))) {
+      throw 'fail!';
+    }
+
+    /**
+     * @param {number} x
+     * @param {number=} opt_bits
+     */
+    function test(x, opt_bits) {
+      jspb.utils.splitFloat32(x);
+      if (goog.isDef(opt_bits)) {
+        if (opt_bits != jspb.utils.split64Low) throw 'fail!';
+      }
+      if (truncate(x) != jspb.utils.joinFloat32(jspb.utils.split64Low,
+          jspb.utils.split64High)) {
+        throw 'fail!';
+      }
+    }
+
+    // Positive and negative infinity.
+    test(Infinity, 0x7f800000);
+    test(-Infinity, 0xff800000);
+
+    // Positive and negative zero.
+    test(0, 0x00000000);
+    test(-0, 0x80000000);
+
+    // Positive and negative epsilon.
+    test(f32_eps, 0x00000001);
+    test(-f32_eps, 0x80000001);
+
+    // Positive and negative min.
+    test(f32_min, 0x00800000);
+    test(-f32_min, 0x80800000);
+
+    // Positive and negative max.
+    test(f32_max, 0x7F7FFFFF);
+    test(-f32_max, 0xFF7FFFFF);
+
+    // Various positive values.
+    var cursor = f32_eps * 10;
+    while (cursor != Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+
+    // Various negative values.
+    cursor = -f32_eps * 10;
+    while (cursor != -Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+  });
+
+
+  /**
+   * Tests conversion from 64-bit floating point numbers to split64 numbers.
+   */
+  it('testFloat64ToSplit64', function() {
+    var f64_eps = jspb.BinaryConstants.FLOAT64_EPS;
+    var f64_min = jspb.BinaryConstants.FLOAT64_MIN;
+    var f64_max = jspb.BinaryConstants.FLOAT64_MAX;
+
+    // NaN.
+    jspb.utils.splitFloat64(NaN);
+    if (!isNaN(jspb.utils.joinFloat64(jspb.utils.split64Low,
+        jspb.utils.split64High))) {
+      throw 'fail!';
+    }
+
+    /**
+     * @param {number} x
+     * @param {number=} opt_highBits
+     * @param {number=} opt_lowBits
+     */
+    function test(x, opt_highBits, opt_lowBits) {
+      jspb.utils.splitFloat64(x);
+      if (goog.isDef(opt_highBits)) {
+        if (opt_highBits != jspb.utils.split64High) throw 'fail!';
+      }
+      if (goog.isDef(opt_lowBits)) {
+        if (opt_lowBits != jspb.utils.split64Low) throw 'fail!';
+      }
+      if (x != jspb.utils.joinFloat64(jspb.utils.split64Low,
+          jspb.utils.split64High)) {
+        throw 'fail!';
+      }
+    }
+
+    // Positive and negative infinity.
+    test(Infinity, 0x7ff00000, 0x00000000);
+    test(-Infinity, 0xfff00000, 0x00000000);
+
+    // Positive and negative zero.
+    test(0, 0x00000000, 0x00000000);
+    test(-0, 0x80000000, 0x00000000);
+
+    // Positive and negative epsilon.
+    test(f64_eps, 0x00000000, 0x00000001);
+    test(-f64_eps, 0x80000000, 0x00000001);
+
+    // Positive and negative min.
+    test(f64_min, 0x00100000, 0x00000000);
+    test(-f64_min, 0x80100000, 0x00000000);
+
+    // Positive and negative max.
+    test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF);
+    test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF);
+
+    // Various positive values.
+    var cursor = f64_eps * 10;
+    while (cursor != Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+
+    // Various negative values.
+    cursor = -f64_eps * 10;
+    while (cursor != -Infinity) {
+      test(cursor);
+      cursor *= 1.1;
+    }
+  });
+
+
+  /**
+   * Tests counting packed varints.
+   */
+  it('testCountVarints', function() {
+    var values = [];
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      values.push(Math.floor(i));
+    }
+
+    var writer = new jspb.BinaryWriter();
+    writer.writePackedUint64(1, values);
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+
+    // We should have two more varints than we started with - one for the field
+    // tag, one for the packed length.
+    assertEquals(values.length + 2,
+                 jspb.utils.countVarints(buffer, 0, buffer.length));
+  });
+
+
+  /**
+   * Tests counting matching varint fields.
+   */
+  it('testCountVarintFields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeUint64(1, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countVarintFields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeUint64(123456789, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests counting matching fixed32 fields.
+   */
+  it('testCountFixed32Fields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeFixed32(1, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeFixed32(123456789, Math.floor(i));
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests counting matching fixed64 fields.
+   */
+  it('testCountFixed64Fields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeDouble(1, i);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000000000; i *= 1.1) {
+      writer.writeDouble(123456789, i);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests counting matching delimited fields.
+   */
+  it('testCountDelimitedFields', function() {
+    var writer = new jspb.BinaryWriter();
+
+    var count = 0;
+    for (var i = 1; i < 1000; i *= 1.1) {
+      writer.writeBytes(1, [Math.floor(i)]);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    var buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1));
+
+    writer = new jspb.BinaryWriter();
+
+    count = 0;
+    for (var i = 1; i < 1000; i *= 1.1) {
+      writer.writeBytes(123456789, [Math.floor(i)]);
+      count++;
+    }
+    writer.writeString(2, 'terminator');
+
+    buffer = new Uint8Array(writer.getResultBuffer());
+    assertEquals(count,
+        jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789));
+  });
+
+
+  /**
+   * Tests byte format for debug strings.
+   */
+  it('testDebugBytesToTextFormat', function() {
+    assertEquals('""', jspb.utils.debugBytesToTextFormat(null));
+    assertEquals('"\\x00\\x10\\xff"',
+        jspb.utils.debugBytesToTextFormat([0, 16, 255]));
+  });
+
+
+  /**
+   * Tests converting byte blob sources into byte blobs.
+   */
+  it('testByteSourceToUint8Array', function() {
+    var convert = jspb.utils.byteSourceToUint8Array;
+
+    var sourceData = [];
+    for (var i = 0; i < 256; i++) {
+      sourceData.push(i);
+    }
+
+    var sourceBytes = new Uint8Array(sourceData);
+    var sourceBuffer = sourceBytes.buffer;
+    var sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData);
+    var sourceString = String.fromCharCode.apply(null, sourceData);
+
+    function check(result) {
+      assertEquals(Uint8Array, result.constructor);
+      assertEquals(sourceData.length, result.length);
+      for (var i = 0; i < result.length; i++) {
+        assertEquals(sourceData[i], result[i]);
+      }
+    }
+
+    // Converting Uint8Arrays into Uint8Arrays should be a no-op.
+    assertEquals(sourceBytes, convert(sourceBytes));
+
+    // Converting Array.<numbers> into Uint8Arrays should work.
+    check(convert(sourceData));
+
+    // Converting ArrayBuffers into Uint8Arrays should work.
+    check(convert(sourceBuffer));
+
+    // Converting base64-encoded strings into Uint8Arrays should work.
+    check(convert(sourceBase64));
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/binary/writer_test.js b/js/compatibility_tests/v3.1.0/binary/writer_test.js
new file mode 100644
index 0000000..d5dadb4
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/binary/writer_test.js
@@ -0,0 +1,122 @@
+// 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.
+
+/**
+ * @fileoverview Test cases for jspb's binary protocol buffer writer. In
+ * practice BinaryWriter is used to drive the Decoder and Reader test cases,
+ * so only writer-specific tests are here.
+ *
+ * Test suite is written using Jasmine -- see http://jasmine.github.io/
+ *
+ * @author [email protected] (Austin Appleby)
+ */
+
+goog.require('goog.crypt');
+goog.require('goog.testing.asserts');
+goog.require('jspb.BinaryWriter');
+
+
+/**
+ * @param {function()} func This function should throw an error when run.
+ */
+function assertFails(func) {
+  var e = assertThrows(func);
+  //assertNotNull(e.toString().match(/Error/));
+}
+
+
+describe('binaryWriterTest', function() {
+  /**
+   * Verifies that misuse of the writer class triggers assertions.
+   */
+  it('testWriteErrors', function() {
+    // Submessages with invalid field indices should assert.
+    var writer = new jspb.BinaryWriter();
+    var dummyMessage = /** @type {!jspb.BinaryMessage} */({});
+
+    assertFails(function() {
+      writer.writeMessage(-1, dummyMessage, goog.nullFunction);
+    });
+
+    // Writing invalid field indices should assert.
+    writer = new jspb.BinaryWriter();
+    assertFails(function() {writer.writeUint64(-1, 1);});
+
+    // Writing out-of-range field values should assert.
+    writer = new jspb.BinaryWriter();
+
+    assertFails(function() {writer.writeInt32(1, -Infinity);});
+    assertFails(function() {writer.writeInt32(1, Infinity);});
+
+    assertFails(function() {writer.writeInt64(1, -Infinity);});
+    assertFails(function() {writer.writeInt64(1, Infinity);});
+
+    assertFails(function() {writer.writeUint32(1, -1);});
+    assertFails(function() {writer.writeUint32(1, Infinity);});
+
+    assertFails(function() {writer.writeUint64(1, -1);});
+    assertFails(function() {writer.writeUint64(1, Infinity);});
+
+    assertFails(function() {writer.writeSint32(1, -Infinity);});
+    assertFails(function() {writer.writeSint32(1, Infinity);});
+
+    assertFails(function() {writer.writeSint64(1, -Infinity);});
+    assertFails(function() {writer.writeSint64(1, Infinity);});
+
+    assertFails(function() {writer.writeFixed32(1, -1);});
+    assertFails(function() {writer.writeFixed32(1, Infinity);});
+
+    assertFails(function() {writer.writeFixed64(1, -1);});
+    assertFails(function() {writer.writeFixed64(1, Infinity);});
+
+    assertFails(function() {writer.writeSfixed32(1, -Infinity);});
+    assertFails(function() {writer.writeSfixed32(1, Infinity);});
+
+    assertFails(function() {writer.writeSfixed64(1, -Infinity);});
+    assertFails(function() {writer.writeSfixed64(1, Infinity);});
+  });
+
+
+  /**
+   * Basic test of retrieving the result as a Uint8Array buffer
+   */
+  it('testGetResultBuffer', function() {
+    var expected = '0864120b48656c6c6f20776f726c641a0301020320c801';
+
+    var writer = new jspb.BinaryWriter();
+    writer.writeUint32(1, 100);
+    writer.writeString(2, 'Hello world');
+    writer.writeBytes(3, new Uint8Array([1, 2, 3]));
+    writer.writeUint32(4, 200);
+
+    var buffer = writer.getResultBuffer();
+    assertEquals(expected, goog.crypt.byteArrayToHex(buffer));
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto b/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto
new file mode 100644
index 0000000..a060925
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/commonjs/test6/test6.proto
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test.importing;
+
+message ImportedMessage {
+  string string_value = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto b/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto
new file mode 100644
index 0000000..f5574a3
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/commonjs/test7/test7.proto
@@ -0,0 +1,42 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2016 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";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test.framing;
+
+import "test6/test6.proto";
+
+message FramingMessage {
+  jspb.test.importing.ImportedMessage imported_message = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/data.proto b/js/compatibility_tests/v3.1.0/data.proto
new file mode 100644
index 0000000..74a8a99
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/data.proto
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: [email protected] (Mark Rawling)
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test;
+
+// legacy data, must be nested
+message data {
+  message NestedData {
+    required string str = 1;
+  }
+}
+
+// new data, does not require nesting
+message UnnestedData {
+  required string str = 1;
+}
+
diff --git a/js/compatibility_tests/v3.1.0/debug_test.js b/js/compatibility_tests/v3.1.0/debug_test.js
new file mode 100644
index 0000000..702cc76
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/debug_test.js
@@ -0,0 +1,105 @@
+// 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.
+
+goog.setTestOnly();
+
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: google-protobuf
+goog.require('jspb.debug');
+
+// CommonJS-LoadFromFile: test_pb
+goog.require('proto.jspb.test.HasExtensions');
+goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.Simple1');
+
+
+
+describe('debugTest', function() {
+  it('testSimple1', function() {
+    if (COMPILED) {
+      return;
+    }
+    var message = new proto.jspb.test.Simple1();
+    message.setAString('foo');
+    assertObjectEquals({
+      $name: 'proto.jspb.test.Simple1',
+      'aString': 'foo',
+      'aRepeatedStringList': []
+    }, jspb.debug.dump(message));
+
+    message.setABoolean(true);
+    message.setARepeatedStringList(['1', '2']);
+
+    assertObjectEquals({
+      $name: 'proto.jspb.test.Simple1',
+      'aString': 'foo',
+      'aRepeatedStringList': ['1', '2'],
+      'aBoolean': true
+    }, jspb.debug.dump(message));
+
+    message.clearAString();
+
+    assertObjectEquals({
+      $name: 'proto.jspb.test.Simple1',
+      'aRepeatedStringList': ['1', '2'],
+      'aBoolean': true
+    }, jspb.debug.dump(message));
+  });
+
+
+  it('testExtensions', function() {
+    if (COMPILED) {
+      return;
+    }
+    var extension = new proto.jspb.test.IsExtension();
+    extension.setExt1('ext1field');
+    var extendable = new proto.jspb.test.HasExtensions();
+    extendable.setStr1('v1');
+    extendable.setStr2('v2');
+    extendable.setStr3('v3');
+    extendable.setExtension(proto.jspb.test.IsExtension.extField, extension);
+
+    assertObjectEquals({
+      '$name': 'proto.jspb.test.HasExtensions',
+      'str1': 'v1',
+      'str2': 'v2',
+      'str3': 'v3',
+      '$extensions': {
+        'extField': {
+          '$name': 'proto.jspb.test.IsExtension',
+          'ext1': 'ext1field'
+        },
+        'repeatedSimpleList': []
+      }
+    }, jspb.debug.dump(extendable));
+  });
+
+});
diff --git a/js/compatibility_tests/v3.1.0/maps_test.js b/js/compatibility_tests/v3.1.0/maps_test.js
new file mode 100644
index 0000000..0d442f4
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/maps_test.js
@@ -0,0 +1,301 @@
+// 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.
+
+goog.require('goog.testing.asserts');
+goog.require('goog.userAgent');
+
+// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.MapValueEnum');
+goog.require('proto.jspb.test.MapValueMessage');
+goog.require('proto.jspb.test.TestMapFields');
+
+// CommonJS-LoadFromFile: test_pb proto.jspb.test
+goog.require('proto.jspb.test.MapValueMessageNoBinary');
+goog.require('proto.jspb.test.TestMapFieldsNoBinary');
+
+/**
+ * Helper: check that the given map has exactly this set of (sorted) entries.
+ * @param {!jspb.Map} map
+ * @param {!Array<!Array<?>>} entries
+ */
+function checkMapEquals(map, entries) {
+  var arr = map.toArray();
+  assertEquals(arr.length, entries.length);
+  for (var i = 0; i < arr.length; i++) {
+    assertElementsEquals(arr[i], entries[i]);
+  }
+}
+
+/**
+ * Converts an ES6 iterator to an array.
+ * @template T
+ * @param {!Iterator<T>} iter an iterator
+ * @return {!Array<T>}
+ */
+function toArray(iter) {
+  var arr = [];
+  while (true) {
+    var val = iter.next();
+    if (val.done) {
+      break;
+    }
+    arr.push(val.value);
+  }
+  return arr;
+}
+
+
+/**
+ * Helper: generate test methods for this TestMapFields class.
+ * @param {?} msgInfo
+ * @param {?} submessageCtor
+ * @param {!string} suffix
+ */
+function makeTests(msgInfo, submessageCtor, suffix) {
+  /**
+   * Helper: fill all maps on a TestMapFields.
+   * @param {?} msg
+   */
+  var fillMapFields = function(msg) {
+    msg.getMapStringStringMap().set('asdf', 'jkl;').set('key 2', 'hello world');
+    msg.getMapStringInt32Map().set('a', 1).set('b', -2);
+    msg.getMapStringInt64Map().set('c', 0x100000000).set('d', 0x200000000);
+    msg.getMapStringBoolMap().set('e', true).set('f', false);
+    msg.getMapStringDoubleMap().set('g', 3.14159).set('h', 2.71828);
+    msg.getMapStringEnumMap()
+        .set('i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR)
+        .set('j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ);
+    msg.getMapStringMsgMap()
+        .set('k', new submessageCtor())
+        .set('l', new submessageCtor());
+    msg.getMapStringMsgMap().get('k').setFoo(42);
+    msg.getMapStringMsgMap().get('l').setFoo(84);
+    msg.getMapInt32StringMap().set(-1, 'a').set(42, 'b');
+    msg.getMapInt64StringMap().set(0x123456789abc, 'c').set(0xcba987654321, 'd');
+    msg.getMapBoolStringMap().set(false, 'e').set(true, 'f');
+  };
+
+  /**
+   * Helper: check all maps on a TestMapFields.
+   * @param {?} msg
+   */
+  var checkMapFields = function(msg) {
+    checkMapEquals(msg.getMapStringStringMap(), [
+          ['asdf', 'jkl;'],
+          ['key 2', 'hello world']
+    ]);
+    checkMapEquals(msg.getMapStringInt32Map(), [
+          ['a', 1],
+          ['b', -2]
+    ]);
+    checkMapEquals(msg.getMapStringInt64Map(), [
+          ['c', 0x100000000],
+          ['d', 0x200000000]
+    ]);
+    checkMapEquals(msg.getMapStringBoolMap(), [
+          ['e', true],
+          ['f', false]
+    ]);
+    checkMapEquals(msg.getMapStringDoubleMap(), [
+          ['g', 3.14159],
+          ['h', 2.71828]
+    ]);
+    checkMapEquals(msg.getMapStringEnumMap(), [
+          ['i', proto.jspb.test.MapValueEnum.MAP_VALUE_BAR],
+          ['j', proto.jspb.test.MapValueEnum.MAP_VALUE_BAZ]
+    ]);
+    checkMapEquals(msg.getMapInt32StringMap(), [
+          [-1, 'a'],
+          [42, 'b']
+    ]);
+    checkMapEquals(msg.getMapInt64StringMap(), [
+          [0x123456789abc, 'c'],
+          [0xcba987654321, 'd']
+    ]);
+    checkMapEquals(msg.getMapBoolStringMap(), [
+          [false, 'e'],
+          [true, 'f']
+    ]);
+
+    assertEquals(msg.getMapStringMsgMap().getLength(), 2);
+    assertEquals(msg.getMapStringMsgMap().get('k').getFoo(), 42);
+    assertEquals(msg.getMapStringMsgMap().get('l').getFoo(), 84);
+
+    var entries = toArray(msg.getMapStringMsgMap().entries());
+    assertEquals(entries.length, 2);
+    entries.forEach(function(entry) {
+      var key = entry[0];
+      var val = entry[1];
+      assert(val === msg.getMapStringMsgMap().get(key));
+    });
+
+    msg.getMapStringMsgMap().forEach(function(val, key) {
+      assert(val === msg.getMapStringMsgMap().get(key));
+    });
+  };
+
+  it('testMapStringStringField' + suffix, function() {
+    var msg = new msgInfo.constructor();
+    assertEquals(msg.getMapStringStringMap().getLength(), 0);
+    assertEquals(msg.getMapStringInt32Map().getLength(), 0);
+    assertEquals(msg.getMapStringInt64Map().getLength(), 0);
+    assertEquals(msg.getMapStringBoolMap().getLength(), 0);
+    assertEquals(msg.getMapStringDoubleMap().getLength(), 0);
+    assertEquals(msg.getMapStringEnumMap().getLength(), 0);
+    assertEquals(msg.getMapStringMsgMap().getLength(), 0);
+
+    // Re-create to clear out any internally-cached wrappers, etc.
+    msg = new msgInfo.constructor();
+    var m = msg.getMapStringStringMap();
+    assertEquals(m.has('asdf'), false);
+    assertEquals(m.get('asdf'), undefined);
+    m.set('asdf', 'hello world');
+    assertEquals(m.has('asdf'), true);
+    assertEquals(m.get('asdf'), 'hello world');
+    m.set('jkl;', 'key 2');
+    assertEquals(m.has('jkl;'), true);
+    assertEquals(m.get('jkl;'), 'key 2');
+    assertEquals(m.getLength(), 2);
+    var it = m.entries();
+    assertElementsEquals(it.next().value, ['asdf', 'hello world']);
+    assertElementsEquals(it.next().value, ['jkl;', 'key 2']);
+    assertEquals(it.next().done, true);
+    checkMapEquals(m, [
+        ['asdf', 'hello world'],
+        ['jkl;', 'key 2']
+    ]);
+    m.del('jkl;');
+    assertEquals(m.has('jkl;'), false);
+    assertEquals(m.get('jkl;'), undefined);
+    assertEquals(m.getLength(), 1);
+    it = m.keys();
+    assertEquals(it.next().value, 'asdf');
+    assertEquals(it.next().done, true);
+    it = m.values();
+    assertEquals(it.next().value, 'hello world');
+    assertEquals(it.next().done, true);
+
+    var count = 0;
+    m.forEach(function(value, key, map) {
+      assertEquals(map, m);
+      assertEquals(key, 'asdf');
+      assertEquals(value, 'hello world');
+      count++;
+    });
+    assertEquals(count, 1);
+
+    m.clear();
+    assertEquals(m.getLength(), 0);
+  });
+
+
+  /**
+   * Tests operations on maps with all key and value types.
+   */
+  it('testAllMapTypes' + suffix, function() {
+    var msg = new msgInfo.constructor();
+    fillMapFields(msg);
+    checkMapFields(msg);
+  });
+
+
+  if (msgInfo.deserializeBinary) {
+    /**
+     * Tests serialization and deserialization in binary format.
+     */
+    it('testBinaryFormat' + suffix, function() {
+      if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
+        // IE8/9 currently doesn't support binary format because they lack
+        // TypedArray.
+        return;
+      }
+
+      // Check that the format is correct.
+      var msg = new msgInfo.constructor();
+      msg.getMapStringStringMap().set('A', 'a');
+      var serialized = msg.serializeBinary();
+      var expectedSerialized = [
+          0x0a, 0x6, // field 1 (map_string_string), delimited, length 6
+          0x0a, 0x1, // field 1 in submessage (key), delimited, length 1
+          0x41,      // ASCII 'A'
+          0x12, 0x1, // field 2 in submessage (value), delimited, length 1
+          0x61       // ASCII 'a'
+      ];
+      assertEquals(serialized.length, expectedSerialized.length);
+      for (var i = 0; i < serialized.length; i++) {
+        assertEquals(serialized[i], expectedSerialized[i]);
+      }
+
+      // Check that all map fields successfully round-trip.
+      msg = new msgInfo.constructor();
+      fillMapFields(msg);
+      serialized = msg.serializeBinary();
+      var decoded = msgInfo.deserializeBinary(serialized);
+      checkMapFields(decoded);
+    });
+  }
+
+  /**
+   * Exercises the lazy map<->underlying array sync.
+   */
+  it('testLazyMapSync' + suffix, function() {
+    // Start with a JSPB array containing a few map entries.
+    var entries = [
+        ['a', 'entry 1'],
+        ['c', 'entry 2'],
+        ['b', 'entry 3']
+    ];
+    var msg = new msgInfo.constructor([entries]);
+    assertEquals(entries.length, 3);
+    assertEquals(entries[0][0], 'a');
+    assertEquals(entries[1][0], 'c');
+    assertEquals(entries[2][0], 'b');
+    msg.getMapStringStringMap().del('a');
+    assertEquals(entries.length, 3);  // not yet sync'd
+    msg.toArray();                // force a sync
+    assertEquals(entries.length, 2);
+    assertEquals(entries[0][0], 'b'); // now in sorted order
+    assertEquals(entries[1][0], 'c');
+
+    var a = msg.toArray();
+    assertEquals(a[0], entries);  // retains original reference
+  });
+}
+
+describe('mapsTest', function() {
+  makeTests({
+    constructor: proto.jspb.test.TestMapFields,
+    deserializeBinary: proto.jspb.test.TestMapFields.deserializeBinary
+  }, proto.jspb.test.MapValueMessage, "_Binary");
+  makeTests({
+    constructor: proto.jspb.test.TestMapFieldsNoBinary,
+    deserializeBinary: null
+  }, proto.jspb.test.MapValueMessageNoBinary, "_NoBinary");
+});
diff --git a/js/compatibility_tests/v3.1.0/message_test.js b/js/compatibility_tests/v3.1.0/message_test.js
new file mode 100644
index 0000000..b46e50d
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/message_test.js
@@ -0,0 +1,1037 @@
+// 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.
+
+// Test suite is written using Jasmine -- see http://jasmine.github.io/
+
+goog.setTestOnly();
+
+goog.require('goog.json');
+goog.require('goog.testing.asserts');
+goog.require('goog.userAgent');
+
+// CommonJS-LoadFromFile: google-protobuf jspb
+goog.require('jspb.Message');
+
+// CommonJS-LoadFromFile: test5_pb proto.jspb.exttest.beta
+goog.require('proto.jspb.exttest.beta.floatingStrField');
+
+// CommonJS-LoadFromFile: test3_pb proto.jspb.exttest
+goog.require('proto.jspb.exttest.floatingMsgField');
+
+// CommonJS-LoadFromFile: test4_pb proto.jspb.exttest
+goog.require('proto.jspb.exttest.floatingMsgFieldTwo');
+
+// CommonJS-LoadFromFile: test_pb proto.jspb.test
+goog.require('proto.jspb.test.CloneExtension');
+goog.require('proto.jspb.test.Complex');
+goog.require('proto.jspb.test.DefaultValues');
+goog.require('proto.jspb.test.Empty');
+goog.require('proto.jspb.test.EnumContainer');
+goog.require('proto.jspb.test.floatingMsgField');
+goog.require('proto.jspb.test.FloatingPointFields');
+goog.require('proto.jspb.test.floatingStrField');
+goog.require('proto.jspb.test.HasExtensions');
+goog.require('proto.jspb.test.IndirectExtension');
+goog.require('proto.jspb.test.IsExtension');
+goog.require('proto.jspb.test.OptionalFields');
+goog.require('proto.jspb.test.OuterEnum');
+goog.require('proto.jspb.test.OuterMessage.Complex');
+goog.require('proto.jspb.test.Simple1');
+goog.require('proto.jspb.test.Simple2');
+goog.require('proto.jspb.test.SpecialCases');
+goog.require('proto.jspb.test.TestClone');
+goog.require('proto.jspb.test.TestEndsWithBytes');
+goog.require('proto.jspb.test.TestGroup');
+goog.require('proto.jspb.test.TestGroup1');
+goog.require('proto.jspb.test.TestMessageWithOneof');
+goog.require('proto.jspb.test.TestReservedNames');
+goog.require('proto.jspb.test.TestReservedNamesExtension');
+
+// CommonJS-LoadFromFile: test2_pb proto.jspb.test
+goog.require('proto.jspb.test.ExtensionMessage');
+goog.require('proto.jspb.test.TestExtensionsMessage');
+
+
+
+
+describe('Message test suite', function() {
+  it('testEmptyProto', function() {
+    var empty1 = new proto.jspb.test.Empty([]);
+    var empty2 = new proto.jspb.test.Empty([]);
+    assertObjectEquals({}, empty1.toObject());
+    assertObjectEquals('Message should not be corrupted:', empty2, empty1);
+  });
+
+  it('testTopLevelEnum', function() {
+    var response = new proto.jspb.test.EnumContainer([]);
+    response.setOuterEnum(proto.jspb.test.OuterEnum.FOO);
+    assertEquals(proto.jspb.test.OuterEnum.FOO, response.getOuterEnum());
+  });
+
+  it('testByteStrings', function() {
+    var data = new proto.jspb.test.DefaultValues([]);
+    data.setBytesField('some_bytes');
+    assertEquals('some_bytes', data.getBytesField());
+  });
+
+  it('testComplexConversion', function() {
+    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var data2 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var foo = new proto.jspb.test.Complex(data1);
+    var bar = new proto.jspb.test.Complex(data2);
+    var result = foo.toObject();
+    assertObjectEquals({
+      aString: 'a',
+      anOutOfOrderBool: 1,
+      aNestedMessage: {
+        anInt: 11
+      },
+      aRepeatedMessageList: [{anInt: 22}, {anInt: 33}],
+      aRepeatedStringList: ['s1', 's2']
+    }, result);
+
+    // Now test with the jspb instances included.
+    result = foo.toObject(true /* opt_includeInstance */);
+    assertObjectEquals({
+      aString: 'a',
+      anOutOfOrderBool: 1,
+      aNestedMessage: {
+        anInt: 11,
+        $jspbMessageInstance: foo.getANestedMessage()
+      },
+      aRepeatedMessageList: [
+        {anInt: 22, $jspbMessageInstance: foo.getARepeatedMessageList()[0]},
+        {anInt: 33, $jspbMessageInstance: foo.getARepeatedMessageList()[1]}
+      ],
+      aRepeatedStringList: ['s1', 's2'],
+      $jspbMessageInstance: foo
+    }, result);
+
+  });
+
+  it('testMissingFields', function() {
+    var foo = new proto.jspb.test.Complex([
+        undefined, undefined, undefined, [],
+        undefined, undefined, undefined, undefined]);
+    var bar = new proto.jspb.test.Complex([
+        undefined, undefined, undefined, [],
+        undefined, undefined, undefined, undefined]);
+    var result = foo.toObject();
+    assertObjectEquals({
+      aString: undefined,
+      anOutOfOrderBool: undefined,
+      aNestedMessage: {
+        anInt: undefined
+      },
+      // Note: JsPb converts undefined repeated fields to empty arrays.
+      aRepeatedMessageList: [],
+      aRepeatedStringList: []
+    }, result);
+
+  });
+
+  it('testNestedComplexMessage', function() {
+    // Instantiate the message and set a unique field, just to ensure that we
+    // are not getting jspb.test.Complex instead.
+    var msg = new proto.jspb.test.OuterMessage.Complex();
+    msg.setInnerComplexField(5);
+  });
+
+  it('testSpecialCases', function() {
+    // Note: Some property names are reserved in JavaScript.
+    // These names are converted to the Js property named pb_<reserved_name>.
+    var special =
+        new proto.jspb.test.SpecialCases(['normal', 'default', 'function',
+        'var']);
+    var result = special.toObject();
+    assertObjectEquals({
+      normal: 'normal',
+      pb_default: 'default',
+      pb_function: 'function',
+      pb_var: 'var'
+    }, result);
+  });
+
+  it('testDefaultValues', function() {
+    var defaultString = "default<>\'\"abc";
+    var response = new proto.jspb.test.DefaultValues();
+
+    // Test toObject
+    var expectedObject = {
+      stringField: defaultString,
+      boolField: true,
+      intField: 11,
+      enumField: 13,
+      emptyField: '',
+      bytesField: 'bW9v'
+    };
+    assertObjectEquals(expectedObject, response.toObject());
+
+
+    // Test getters
+    response = new proto.jspb.test.DefaultValues();
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+    assertEquals('', response.getEmptyField());
+    assertEquals('bW9v', response.getBytesField());
+
+    function makeDefault(values) {
+      return new proto.jspb.test.DefaultValues(values);
+    }
+
+    // Test with undefined values,
+    // Use push to workaround IE treating undefined array elements as holes.
+    response = makeDefault([undefined, undefined, undefined, undefined]);
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+    assertFalse(response.hasStringField());
+    assertFalse(response.hasBoolField());
+    assertFalse(response.hasIntField());
+    assertFalse(response.hasEnumField());
+
+    // Test with null values, as would be returned by a JSON serializer.
+    response = makeDefault([null, null, null, null]);
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+    assertFalse(response.hasStringField());
+    assertFalse(response.hasBoolField());
+    assertFalse(response.hasIntField());
+    assertFalse(response.hasEnumField());
+
+    // Test with false-like values.
+    response = makeDefault(['', false, 0, 0]);
+    assertEquals('', response.getStringField());
+    assertEquals(false, response.getBoolField());
+    assertEquals(true, response.getIntField() == 0);
+    assertEquals(true, response.getEnumField() == 0);
+    assertTrue(response.hasStringField());
+    assertTrue(response.hasBoolField());
+    assertTrue(response.hasIntField());
+    assertTrue(response.hasEnumField());
+
+    // Test that clearing the values reverts them to the default state.
+    response = makeDefault(['blah', false, 111, 77]);
+    response.clearStringField(); response.clearBoolField();
+    response.clearIntField(); response.clearEnumField();
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+    assertFalse(response.hasStringField());
+    assertFalse(response.hasBoolField());
+    assertFalse(response.hasIntField());
+    assertFalse(response.hasEnumField());
+
+    // Test that setFoo(null) clears the values.
+    response = makeDefault(['blah', false, 111, 77]);
+    response.setStringField(null); response.setBoolField(null);
+    response.setIntField(undefined); response.setEnumField(undefined);
+    assertEquals(defaultString, response.getStringField());
+    assertEquals(true, response.getBoolField());
+    assertEquals(11, response.getIntField());
+    assertEquals(13, response.getEnumField());
+    assertFalse(response.hasStringField());
+    assertFalse(response.hasBoolField());
+    assertFalse(response.hasIntField());
+    assertFalse(response.hasEnumField());
+  });
+
+  it('testClearFields', function() {
+    var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
+    var foo = new proto.jspb.test.OptionalFields(data);
+    foo.clearAString();
+    foo.clearABool();
+    foo.clearANestedMessage();
+    foo.clearARepeatedMessageList();
+    foo.clearARepeatedStringList();
+    assertEquals('', foo.getAString());
+    assertEquals(false, foo.getABool());
+    assertUndefined(foo.getANestedMessage());
+    assertFalse(foo.hasAString());
+    assertFalse(foo.hasABool());
+    assertObjectEquals([], foo.getARepeatedMessageList());
+    assertObjectEquals([], foo.getARepeatedStringList());
+    // NOTE: We want the missing fields in 'expected' to be undefined,
+    // but we actually get a sparse array instead. We could use something
+    // like [1,undefined,2] to avoid this, except that this is still
+    // sparse on IE. No comment...
+    var expected = [,,, [], []];
+    expected[0] = expected[1] = expected[2] = undefined;
+    assertObjectEquals(expected, foo.toArray());
+  });
+
+  it('testDifferenceRawObject', /** @suppress {visibility} */ function() {
+    var p1 = new proto.jspb.test.HasExtensions(['hi', 'diff', {}]);
+    var p2 = new proto.jspb.test.HasExtensions(['hi', 'what',
+                                               {1000: 'unique'}]);
+    var diff = /** @type {proto.jspb.test.HasExtensions} */
+        (jspb.Message.difference(p1, p2));
+    assertEquals('', diff.getStr1());
+    assertEquals('what', diff.getStr2());
+    assertEquals('', diff.getStr3());
+    assertEquals('unique', diff.extensionObject_[1000]);
+  });
+
+  it('testEqualsSimple', function() {
+    var s1 = new proto.jspb.test.Simple1(['hi']);
+    assertTrue(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['hi'])));
+    assertFalse(jspb.Message.equals(s1, new proto.jspb.test.Simple1(['bye'])));
+    var s1b = new proto.jspb.test.Simple1(['hi', ['hello']]);
+    assertTrue(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['hi', ['hello']])));
+    assertTrue(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['hi', ['hello', undefined,
+                                            undefined, undefined]])));
+    assertFalse(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['no', ['hello']])));
+    // Test with messages of different types
+    var s2 = new proto.jspb.test.Simple2(['hi']);
+    assertFalse(jspb.Message.equals(s1, s2));
+  });
+
+  it('testEquals_softComparison', function() {
+    var s1 = new proto.jspb.test.Simple1(['hi', [], null]);
+    assertTrue(jspb.Message.equals(s1,
+        new proto.jspb.test.Simple1(['hi', []])));
+
+    var s1b = new proto.jspb.test.Simple1(['hi', [], true]);
+    assertTrue(jspb.Message.equals(s1b,
+        new proto.jspb.test.Simple1(['hi', [], 1])));
+  });
+
+  it('testEqualsComplex', function() {
+    var data1 = ['a',,, [, 11], [[, 22], [, 33]],, ['s1', 's2'],, 1];
+    var data2 = ['a',,, [, 11], [[, 22], [, 34]],, ['s1', 's2'],, 1];
+    var data3 = ['a',,, [, 11], [[, 22]],, ['s1', 's2'],, 1];
+    var data4 = ['hi'];
+    var c1a = new proto.jspb.test.Complex(data1);
+    var c1b = new proto.jspb.test.Complex(data1);
+    var c2 = new proto.jspb.test.Complex(data2);
+    var c3 = new proto.jspb.test.Complex(data3);
+    var s1 = new proto.jspb.test.Simple1(data4);
+
+    assertTrue(jspb.Message.equals(c1a, c1b));
+    assertFalse(jspb.Message.equals(c1a, c2));
+    assertFalse(jspb.Message.equals(c2, c3));
+    assertFalse(jspb.Message.equals(c1a, s1));
+  });
+
+  it('testEqualsExtensionsConstructed', function() {
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([]),
+        new proto.jspb.test.HasExtensions([{}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
+    ));
+    assertFalse(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'b'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions([,,, {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions([{100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}])
+    ));
+    assertTrue(jspb.Message.equals(
+        new proto.jspb.test.HasExtensions(['hi',,, {100: [{200: 'a'}]}]),
+        new proto.jspb.test.HasExtensions(['hi', {100: [{200: 'a'}]}])
+    ));
+  });
+
+  it('testEqualsExtensionsUnconstructed', function() {
+    assertTrue(jspb.Message.compareFields([], [{}]));
+    assertTrue(jspb.Message.compareFields([,,, {}], []));
+    assertTrue(jspb.Message.compareFields([,,, {}], [,, {}]));
+    assertTrue(jspb.Message.compareFields(
+        ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+    assertFalse(jspb.Message.compareFields(
+        ['hi', {100: [{200: 'a'}]}], ['hi', {100: [{200: 'b'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        [{100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        [{100: [{200: 'a'}]}], [,,, {100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        [,,, {100: [{200: 'a'}]}], [{100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        ['hi', {100: [{200: 'a'}]}], ['hi',,, {100: [{200: 'a'}]}]));
+    assertTrue(jspb.Message.compareFields(
+        ['hi',,, {100: [{200: 'a'}]}], ['hi', {100: [{200: 'a'}]}]));
+  });
+
+  it('testToMap', function() {
+    var p1 = new proto.jspb.test.Simple1(['k', ['v']]);
+    var p2 = new proto.jspb.test.Simple1(['k1', ['v1', 'v2']]);
+    var soymap = jspb.Message.toMap([p1, p2],
+        proto.jspb.test.Simple1.prototype.getAString,
+        proto.jspb.test.Simple1.prototype.toObject);
+    assertEquals('k', soymap['k'].aString);
+    assertArrayEquals(['v'], soymap['k'].aRepeatedStringList);
+    var protomap = jspb.Message.toMap([p1, p2],
+        proto.jspb.test.Simple1.prototype.getAString);
+    assertEquals('k', protomap['k'].getAString());
+    assertArrayEquals(['v'], protomap['k'].getARepeatedStringList());
+  });
+
+  it('testClone', function() {
+    var supportsUint8Array =
+        !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10');
+    var original = new proto.jspb.test.TestClone();
+    original.setStr('v1');
+    var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]);
+    var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]);
+    var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]);
+    original.setSimple1(simple1);
+    original.setSimple2List([simple2, simple3]);
+    var bytes1 = supportsUint8Array ? new Uint8Array([1, 2, 3]) : '123';
+    original.setBytesField(bytes1);
+    var extension = new proto.jspb.test.CloneExtension();
+    extension.setExt('e1');
+    original.setExtension(proto.jspb.test.IsExtension.extField, extension);
+    var clone = original.clone();
+    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
+      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+        clone.toArray());
+    clone.setStr('v2');
+    var simple4 = new proto.jspb.test.Simple1(['a1', ['b1', 'c1']]);
+    var simple5 = new proto.jspb.test.Simple1(['a2', ['b2', 'c2']]);
+    var simple6 = new proto.jspb.test.Simple1(['a3', ['b3', 'c3']]);
+    clone.setSimple1(simple4);
+    clone.setSimple2List([simple5, simple6]);
+    if (supportsUint8Array) {
+      clone.getBytesField()[0] = 4;
+      assertObjectEquals(bytes1, original.getBytesField());
+    }
+    var bytes2 = supportsUint8Array ? new Uint8Array([4, 5, 6]) : '456';
+    clone.setBytesField(bytes2);
+    var newExtension = new proto.jspb.test.CloneExtension();
+    newExtension.setExt('e2');
+    clone.setExtension(proto.jspb.test.CloneExtension.extField, newExtension);
+    assertArrayEquals(['v2',, ['a1', ['b1', 'c1']],,
+      [['a2', ['b2', 'c2']], ['a3', ['b3', 'c3']]], bytes2,, { 100: [, 'e2'] }],
+        clone.toArray());
+    assertArrayEquals(['v1',, ['x1', ['y1', 'z1']],,
+      [['x2', ['y2', 'z2']], ['x3', ['y3', 'z3']]], bytes1,, { 100: [, 'e1'] }],
+        original.toArray());
+  });
+
+  it('testCopyInto', function() {
+    var supportsUint8Array =
+        !goog.userAgent.IE || goog.userAgent.isVersionOrHigher('10');
+    var original = new proto.jspb.test.TestClone();
+    original.setStr('v1');
+    var dest = new proto.jspb.test.TestClone();
+    dest.setStr('override');
+    var simple1 = new proto.jspb.test.Simple1(['x1', ['y1', 'z1']]);
+    var simple2 = new proto.jspb.test.Simple1(['x2', ['y2', 'z2']]);
+    var simple3 = new proto.jspb.test.Simple1(['x3', ['y3', 'z3']]);
+    var destSimple1 = new proto.jspb.test.Simple1(['ox1', ['oy1', 'oz1']]);
+    var destSimple2 = new proto.jspb.test.Simple1(['ox2', ['oy2', 'oz2']]);
+    var destSimple3 = new proto.jspb.test.Simple1(['ox3', ['oy3', 'oz3']]);
+    original.setSimple1(simple1);
+    original.setSimple2List([simple2, simple3]);
+    dest.setSimple1(destSimple1);
+    dest.setSimple2List([destSimple2, destSimple3]);
+    var bytes1 = supportsUint8Array ? new Uint8Array([1, 2, 3]) : '123';
+    var bytes2 = supportsUint8Array ? new Uint8Array([4, 5, 6]) : '456';
+    original.setBytesField(bytes1);
+    dest.setBytesField(bytes2);
+    var extension = new proto.jspb.test.CloneExtension();
+    extension.setExt('e1');
+    original.setExtension(proto.jspb.test.CloneExtension.extField, extension);
+
+    jspb.Message.copyInto(original, dest);
+    assertArrayEquals(original.toArray(), dest.toArray());
+    assertEquals('x1', dest.getSimple1().getAString());
+    assertEquals('e1',
+        dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt());
+    dest.getSimple1().setAString('new value');
+    assertNotEquals(dest.getSimple1().getAString(),
+        original.getSimple1().getAString());
+    if (supportsUint8Array) {
+      dest.getBytesField()[0] = 7;
+      assertObjectEquals(bytes1, original.getBytesField());
+      assertObjectEquals(new Uint8Array([7, 2, 3]), dest.getBytesField());
+    } else {
+      dest.setBytesField('789');
+      assertObjectEquals(bytes1, original.getBytesField());
+      assertObjectEquals('789', dest.getBytesField());
+    }
+    dest.getExtension(proto.jspb.test.CloneExtension.extField).
+        setExt('new value');
+    assertNotEquals(
+        dest.getExtension(proto.jspb.test.CloneExtension.extField).getExt(),
+        original.getExtension(
+            proto.jspb.test.CloneExtension.extField).getExt());
+  });
+
+  it('testCopyInto_notSameType', function() {
+    var a = new proto.jspb.test.TestClone();
+    var b = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
+
+    var e = assertThrows(function() {
+      jspb.Message.copyInto(a, b);
+    });
+    assertContains('should have the same type', e.message);
+  });
+
+  it('testExtensions', function() {
+    var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
+    var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2']]);
+    var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+    extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
+                            extension2);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
+    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
+        ['a', 'b']);
+    var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
+    var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2']]);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedSimpleList,
+        [s1, s2]);
+    assertObjectEquals(extension1,
+        extendable.getExtension(proto.jspb.test.IsExtension.extField));
+    assertObjectEquals(extension2,
+        extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
+    assertObjectEquals('xyzzy',
+        extendable.getExtension(proto.jspb.test.IndirectExtension.str));
+    assertObjectEquals(['a', 'b'], extendable.getExtension(
+        proto.jspb.test.IndirectExtension.repeatedStrList));
+    assertObjectEquals([s1, s2], extendable.getExtension(
+        proto.jspb.test.IndirectExtension.repeatedSimpleList));
+    // Not supported yet, but it should work...
+    extendable.setExtension(proto.jspb.test.IndirectExtension.simple, null);
+    assertNull(
+        extendable.getExtension(proto.jspb.test.IndirectExtension.simple));
+    extendable.setExtension(proto.jspb.test.IndirectExtension.str, null);
+    assertNull(extendable.getExtension(proto.jspb.test.IndirectExtension.str));
+
+
+    // Extension fields with jspb.ignore = true are ignored.
+    assertUndefined(proto.jspb.test.IndirectExtension['ignored']);
+    assertUndefined(proto.jspb.test.HasExtensions['ignoredFloating']);
+  });
+
+  it('testFloatingExtensions', function() {
+    // From an autogenerated container.
+    var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+    var extension = new proto.jspb.test.Simple1(['foo', ['s1', 's2']]);
+    extendable.setExtension(proto.jspb.test.simple1, extension);
+    assertObjectEquals(extension,
+        extendable.getExtension(proto.jspb.test.simple1));
+
+    // From _lib mode.
+    extension = new proto.jspb.test.ExtensionMessage(['s1']);
+    extendable = new proto.jspb.test.TestExtensionsMessage([16]);
+    extendable.setExtension(proto.jspb.test.floatingMsgField, extension);
+    extendable.setExtension(proto.jspb.test.floatingStrField, 's2');
+    assertObjectEquals(extension,
+        extendable.getExtension(proto.jspb.test.floatingMsgField));
+    assertObjectEquals('s2',
+        extendable.getExtension(proto.jspb.test.floatingStrField));
+    assertNotUndefined(proto.jspb.exttest.floatingMsgField);
+    assertNotUndefined(proto.jspb.exttest.floatingMsgFieldTwo);
+    assertNotUndefined(proto.jspb.exttest.beta.floatingStrField);
+  });
+
+  it('testToObject_extendedObject', function() {
+    var extension1 = new proto.jspb.test.IsExtension(['ext1field']);
+    var extension2 = new proto.jspb.test.Simple1(['str', ['s1', 's2'], true]);
+    var extendable = new proto.jspb.test.HasExtensions(['v1', 'v2', 'v3']);
+    extendable.setExtension(proto.jspb.test.IsExtension.extField, extension1);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.simple,
+                            extension2);
+    extendable.setExtension(proto.jspb.test.IndirectExtension.str, 'xyzzy');
+    extendable.setExtension(proto.jspb.test.IndirectExtension.repeatedStrList,
+        ['a', 'b']);
+    var s1 = new proto.jspb.test.Simple1(['foo', ['s1', 's2'], true]);
+    var s2 = new proto.jspb.test.Simple1(['bar', ['t1', 't2'], false]);
+    extendable.setExtension(
+        proto.jspb.test.IndirectExtension.repeatedSimpleList,
+        [s1, s2]);
+    assertObjectEquals({
+      str1: 'v1', str2: 'v2', str3: 'v3',
+      extField: { ext1: 'ext1field' },
+      simple: {
+        aString: 'str', aRepeatedStringList: ['s1', 's2'], aBoolean: true
+      },
+      str: 'xyzzy',
+      repeatedStrList: ['a', 'b'],
+      repeatedSimpleList: [
+        { aString: 'foo', aRepeatedStringList: ['s1', 's2'], aBoolean: true},
+        { aString: 'bar', aRepeatedStringList: ['t1', 't2'], aBoolean: false}
+      ]
+    }, extendable.toObject());
+
+    // Now, with instances included.
+    assertObjectEquals({
+      str1: 'v1', str2: 'v2', str3: 'v3',
+      extField: {
+        ext1: 'ext1field',
+        $jspbMessageInstance:
+            extendable.getExtension(proto.jspb.test.IsExtension.extField)
+      },
+      simple: {
+        aString: 'str',
+        aRepeatedStringList: ['s1', 's2'],
+        aBoolean: true,
+        $jspbMessageInstance:
+            extendable.getExtension(proto.jspb.test.IndirectExtension.simple)
+      },
+      str: 'xyzzy',
+      repeatedStrList: ['a', 'b'],
+      repeatedSimpleList: [{
+        aString: 'foo',
+        aRepeatedStringList: ['s1', 's2'],
+        aBoolean: true,
+        $jspbMessageInstance: s1
+      }, {
+        aString: 'bar',
+        aRepeatedStringList: ['t1', 't2'],
+        aBoolean: false,
+        $jspbMessageInstance: s2
+      }],
+      $jspbMessageInstance: extendable
+    }, extendable.toObject(true /* opt_includeInstance */));
+  });
+
+  it('testInitialization_emptyArray', function() {
+    var msg = new proto.jspb.test.HasExtensions([]);
+    if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
+      assertArrayEquals([], msg.toArray());
+    } else {
+      // Extension object is created past all regular fields.
+      assertArrayEquals([,,, {}], msg.toArray());
+    }
+  });
+
+  it('testInitialization_justExtensionObject', function() {
+    var msg = new proto.jspb.test.Empty([{1: 'hi'}]);
+    // The extensionObject is not moved from its original location.
+    assertArrayEquals([{1: 'hi'}], msg.toArray());
+  });
+
+  it('testInitialization_incompleteList', function() {
+    var msg = new proto.jspb.test.Empty([1, {4: 'hi'}]);
+    // The extensionObject is not moved from its original location.
+    assertArrayEquals([1, {4: 'hi'}], msg.toArray());
+  });
+
+  it('testInitialization_forwardCompatible', function() {
+    var msg = new proto.jspb.test.Empty([1, 2, 3, {1: 'hi'}]);
+    assertArrayEquals([1, 2, 3, {1: 'hi'}], msg.toArray());
+  });
+
+  it('testExtendedMessageEnsureObject',
+     /** @suppress {visibility} */ function() {
+       var data =
+           new proto.jspb.test.HasExtensions(['str1', {'a_key': 'an_object'}]);
+       assertEquals('an_object', data.extensionObject_['a_key']);
+     });
+
+  it('testToObject_hasExtensionField', function() {
+    var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+    var obj = data.toObject();
+    assertEquals('str1', obj.str1);
+    assertEquals('ext1', obj.extField.ext1);
+  });
+
+  it('testGetExtension', function() {
+    var data = new proto.jspb.test.HasExtensions(['str1', {100: ['ext1']}]);
+    assertEquals('str1', data.getStr1());
+    var extension = data.getExtension(proto.jspb.test.IsExtension.extField);
+    assertNotNull(extension);
+    assertEquals('ext1', extension.getExt1());
+  });
+
+  it('testSetExtension', function() {
+    var data = new proto.jspb.test.HasExtensions();
+    var extensionMessage = new proto.jspb.test.IsExtension(['is_extension']);
+    data.setExtension(proto.jspb.test.IsExtension.extField, extensionMessage);
+    var obj = data.toObject();
+    assertNotNull(
+        data.getExtension(proto.jspb.test.IsExtension.extField));
+    assertEquals('is_extension', obj.extField.ext1);
+  });
+
+  /**
+   * Note that group is long deprecated, we only support it because JsPb has
+   * a goal of being able to generate JS classes for all proto descriptors.
+   */
+  it('testGroups', function() {
+    var group = new proto.jspb.test.TestGroup();
+    var someGroup = new proto.jspb.test.TestGroup.RepeatedGroup();
+    someGroup.setId('g1');
+    someGroup.setSomeBoolList([true, false]);
+    group.setRepeatedGroupList([someGroup]);
+    var groups = group.getRepeatedGroupList();
+    assertEquals('g1', groups[0].getId());
+    assertObjectEquals([true, false], groups[0].getSomeBoolList());
+    assertObjectEquals({id: 'g1', someBoolList: [true, false]},
+        groups[0].toObject());
+    assertObjectEquals({
+      repeatedGroupList: [{id: 'g1', someBoolList: [true, false]}],
+      requiredGroup: {id: undefined},
+      optionalGroup: undefined,
+      requiredSimple: {aRepeatedStringList: [], aString: undefined},
+      optionalSimple: undefined,
+      id: undefined
+    }, group.toObject());
+    var group1 = new proto.jspb.test.TestGroup1();
+    group1.setGroup(someGroup);
+    assertEquals(someGroup, group1.getGroup());
+  });
+
+  it('testNonExtensionFieldsAfterExtensionRange', function() {
+    var data = [{'1': 'a_string'}];
+    var message = new proto.jspb.test.Complex(data);
+    assertArrayEquals([], message.getARepeatedStringList());
+  });
+
+  it('testReservedGetterNames', function() {
+    var message = new proto.jspb.test.TestReservedNames();
+    message.setExtension$(11);
+    message.setExtension(proto.jspb.test.TestReservedNamesExtension.foo, 12);
+    assertEquals(11, message.getExtension$());
+    assertEquals(12, message.getExtension(
+        proto.jspb.test.TestReservedNamesExtension.foo));
+    assertObjectEquals({extension: 11, foo: 12}, message.toObject());
+  });
+
+  it('testInitializeMessageWithUnsetOneof', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof([]);
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+            PARTIAL_ONEOF_NOT_SET,
+        message.getPartialOneofCase());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
+            RECURSIVE_ONEOF_NOT_SET,
+        message.getRecursiveOneofCase());
+  });
+
+  it('testInitializeMessageWithSingleValueSetInOneof', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x']);
+
+    assertEquals('x', message.getPone());
+    assertEquals('', message.getPthree());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+        message.getPartialOneofCase());
+  });
+
+  it('testKeepsLastWireValueSetInUnion_multipleValues', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof([,, 'x',, 'y']);
+
+    assertEquals('', message.getPone());
+    assertEquals('y', message.getPthree());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+        message.getPartialOneofCase());
+  });
+
+  it('testSettingOneofFieldClearsOthers', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals('', message.getPone());
+    assertEquals('', message.getPthree());
+    assertFalse(message.hasPone());
+    assertFalse(message.hasPthree());
+
+    message.setPone('hi');
+    assertEquals('hi', message.getPone());
+    assertEquals('', message.getPthree());
+    assertTrue(message.hasPone());
+    assertFalse(message.hasPthree());
+
+    message.setPthree('bye');
+    assertEquals('', message.getPone());
+    assertEquals('bye', message.getPthree());
+    assertFalse(message.hasPone());
+    assertTrue(message.hasPthree());
+  });
+
+  it('testSettingOneofFieldDoesNotClearFieldsFromOtherUnions', function() {
+    var other = new proto.jspb.test.TestMessageWithOneof;
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals('', message.getPone());
+    assertEquals('', message.getPthree());
+    assertUndefined(message.getRone());
+    assertFalse(message.hasPone());
+    assertFalse(message.hasPthree());
+
+    message.setPone('hi');
+    message.setRone(other);
+    assertEquals('hi', message.getPone());
+    assertEquals('', message.getPthree());
+    assertEquals(other, message.getRone());
+    assertTrue(message.hasPone());
+    assertFalse(message.hasPthree());
+
+    message.setPthree('bye');
+    assertEquals('', message.getPone());
+    assertEquals('bye', message.getPthree());
+    assertEquals(other, message.getRone());
+    assertFalse(message.hasPone());
+    assertTrue(message.hasPthree());
+  });
+
+  it('testUnsetsOneofCaseWhenFieldIsCleared', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+            PARTIAL_ONEOF_NOT_SET,
+        message.getPartialOneofCase());
+
+    message.setPone('hi');
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+        message.getPartialOneofCase());
+
+    message.clearPone();
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.
+            PARTIAL_ONEOF_NOT_SET,
+        message.getPartialOneofCase());
+  });
+
+  it('testMessageWithDefaultOneofValues', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(1234, message.getAone());
+    assertEquals(0, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
+            .DEFAULT_ONEOF_A_NOT_SET,
+        message.getDefaultOneofACase());
+
+    message.setAone(567);
+    assertEquals(567, message.getAone());
+    assertEquals(0, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
+        message.getDefaultOneofACase());
+
+    message.setAtwo(890);
+    assertEquals(1234, message.getAone());
+    assertEquals(890, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+        message.getDefaultOneofACase());
+
+    message.clearAtwo();
+    assertEquals(1234, message.getAone());
+    assertEquals(0, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase
+            .DEFAULT_ONEOF_A_NOT_SET,
+        message.getDefaultOneofACase());
+  });
+
+  it('testMessageWithDefaultOneofValues_defaultNotOnFirstField', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(0, message.getBone());
+    assertEquals(1234, message.getBtwo());
+    assertFalse(message.hasBone());
+    assertFalse(message.hasBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
+            .DEFAULT_ONEOF_B_NOT_SET,
+        message.getDefaultOneofBCase());
+
+    message.setBone(2);
+    assertEquals(2, message.getBone());
+    assertEquals(1234, message.getBtwo());
+    assertTrue(message.hasBone());
+    assertFalse(message.hasBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+        message.getDefaultOneofBCase());
+
+    message.setBtwo(3);
+    assertEquals(0, message.getBone());
+    assertFalse(message.hasBone());
+    assertTrue(message.hasBtwo());
+    assertEquals(3, message.getBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+        message.getDefaultOneofBCase());
+
+    message.clearBtwo();
+    assertEquals(0, message.getBone());
+    assertFalse(message.hasBone());
+    assertFalse(message.hasBtwo());
+    assertEquals(1234, message.getBtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase
+            .DEFAULT_ONEOF_B_NOT_SET,
+        message.getDefaultOneofBCase());
+  });
+
+  it('testInitializeMessageWithOneofDefaults', function() {
+    var message =
+        new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567));
+    assertEquals(567, message.getAone());
+    assertEquals(0, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.AONE,
+        message.getDefaultOneofACase());
+
+    message =
+        new proto.jspb.test.TestMessageWithOneof(new Array(10).concat(890));
+    assertEquals(1234, message.getAone());
+    assertEquals(890, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+        message.getDefaultOneofACase());
+
+    message =
+        new proto.jspb.test.TestMessageWithOneof(new Array(9).concat(567, 890));
+    assertEquals(1234, message.getAone());
+    assertEquals(890, message.getAtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.DefaultOneofACase.ATWO,
+        message.getDefaultOneofACase());
+  });
+
+  it('testInitializeMessageWithOneofDefaults_defaultNotSetOnFirstField',
+      function() {
+        var message;
+
+        message =
+            new proto.jspb.test.TestMessageWithOneof(new Array(11).concat(567));
+        assertEquals(567, message.getBone());
+        assertEquals(1234, message.getBtwo());
+        assertEquals(
+            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BONE,
+            message.getDefaultOneofBCase());
+
+        message =
+            new proto.jspb.test.TestMessageWithOneof(new Array(12).concat(890));
+        assertEquals(0, message.getBone());
+        assertEquals(890, message.getBtwo());
+        assertEquals(
+            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+            message.getDefaultOneofBCase());
+
+        message = new proto.jspb.test.TestMessageWithOneof(
+            new Array(11).concat(567, 890));
+        assertEquals(0, message.getBone());
+        assertEquals(890, message.getBtwo());
+        assertEquals(
+            proto.jspb.test.TestMessageWithOneof.DefaultOneofBCase.BTWO,
+            message.getDefaultOneofBCase());
+      });
+
+  it('testOneofContainingAnotherMessage', function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.
+            RECURSIVE_ONEOF_NOT_SET,
+        message.getRecursiveOneofCase());
+
+    var other = new proto.jspb.test.TestMessageWithOneof;
+    message.setRone(other);
+    assertEquals(other, message.getRone());
+    assertEquals('', message.getRtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RONE,
+        message.getRecursiveOneofCase());
+
+    message.setRtwo('hi');
+    assertUndefined(message.getRone());
+    assertEquals('hi', message.getRtwo());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.RecursiveOneofCase.RTWO,
+        message.getRecursiveOneofCase());
+  });
+
+  it('testQueryingOneofCaseEnsuresOnlyOneFieldIsSetInUnderlyingArray',
+     function() {
+    var message = new proto.jspb.test.TestMessageWithOneof;
+    message.setPone('x');
+    assertEquals('x', message.getPone());
+    assertEquals('', message.getPthree());
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PONE,
+        message.getPartialOneofCase());
+
+    var array = message.toArray();
+    assertEquals('x', array[2]);
+    assertUndefined(array[4]);
+    array[4] = 'y';
+
+    assertEquals(
+        proto.jspb.test.TestMessageWithOneof.PartialOneofCase.PTHREE,
+        message.getPartialOneofCase());
+    assertUndefined(array[2]);
+    assertEquals('y', array[4]);
+  });
+
+  it('testFloatingPointFieldsSupportNan', function() {
+    var assertNan = function(x) {
+      assertTrue('Expected ' + x + ' (' + goog.typeOf(x) + ') to be NaN.',
+          goog.isNumber(x) && isNaN(x));
+    };
+
+    var message = new proto.jspb.test.FloatingPointFields([
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN',
+      'NaN', 'NaN', ['NaN', 'NaN'], 'NaN'
+    ]);
+    assertNan(message.getOptionalFloatField());
+    assertNan(message.getRequiredFloatField());
+    assertNan(message.getRepeatedFloatFieldList()[0]);
+    assertNan(message.getRepeatedFloatFieldList()[1]);
+    assertNan(message.getDefaultFloatField());
+    assertNan(message.getOptionalDoubleField());
+    assertNan(message.getRequiredDoubleField());
+    assertNan(message.getRepeatedDoubleFieldList()[0]);
+    assertNan(message.getRepeatedDoubleFieldList()[1]);
+    assertNan(message.getDefaultDoubleField());
+  });
+
+});
diff --git a/js/compatibility_tests/v3.1.0/proto3_test.js b/js/compatibility_tests/v3.1.0/proto3_test.js
new file mode 100644
index 0000000..3c929ef
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/proto3_test.js
@@ -0,0 +1,329 @@
+// 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.
+
+goog.require('goog.crypt.base64');
+goog.require('goog.testing.asserts');
+
+// CommonJS-LoadFromFile: testbinary_pb proto.jspb.test
+goog.require('proto.jspb.test.ForeignMessage');
+
+// CommonJS-LoadFromFile: proto3_test_pb proto.jspb.test
+goog.require('proto.jspb.test.Proto3Enum');
+goog.require('proto.jspb.test.TestProto3');
+
+
+var BYTES = new Uint8Array([1, 2, 8, 9]);
+var BYTES_B64 = goog.crypt.base64.encodeByteArray(BYTES);
+
+
+/**
+ * Helper: compare a bytes field to an expected value
+ * @param {Uint8Array|string} arr
+ * @param {Uint8Array} expected
+ * @return {boolean}
+ */
+function bytesCompare(arr, expected) {
+  if (goog.isString(arr)) {
+    arr = goog.crypt.base64.decodeStringToUint8Array(arr);
+  }
+  if (arr.length != expected.length) {
+    return false;
+  }
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] != expected[i]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+
+describe('proto3Test', function() {
+  /**
+   * Test defaults for proto3 message fields.
+   */
+  it('testProto3FieldDefaults', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    assertEquals(msg.getOptionalInt32(), 0);
+    assertEquals(msg.getOptionalInt64(), 0);
+    assertEquals(msg.getOptionalUint32(), 0);
+    assertEquals(msg.getOptionalUint64(), 0);
+    assertEquals(msg.getOptionalSint32(), 0);
+    assertEquals(msg.getOptionalSint64(), 0);
+    assertEquals(msg.getOptionalFixed32(), 0);
+    assertEquals(msg.getOptionalFixed64(), 0);
+    assertEquals(msg.getOptionalSfixed32(), 0);
+    assertEquals(msg.getOptionalSfixed64(), 0);
+    assertEquals(msg.getOptionalFloat(), 0);
+    assertEquals(msg.getOptionalDouble(), 0);
+    assertEquals(msg.getOptionalString(), '');
+
+    // TODO(b/26173701): when we change bytes fields default getter to return
+    // Uint8Array, we'll want to switch this assertion to match the u8 case.
+    assertEquals(typeof msg.getOptionalBytes(), 'string');
+    assertEquals(msg.getOptionalBytes_asU8() instanceof Uint8Array, true);
+    assertEquals(typeof msg.getOptionalBytes_asB64(), 'string');
+    assertEquals(msg.getOptionalBytes().length, 0);
+    assertEquals(msg.getOptionalBytes_asU8().length, 0);
+    assertEquals(msg.getOptionalBytes_asB64(), '');
+
+    assertEquals(msg.getOptionalForeignEnum(),
+                 proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    assertEquals(msg.getOptionalForeignMessage(), undefined);
+    assertEquals(msg.getOptionalForeignMessage(), undefined);
+
+    assertEquals(msg.getRepeatedInt32List().length, 0);
+    assertEquals(msg.getRepeatedInt64List().length, 0);
+    assertEquals(msg.getRepeatedUint32List().length, 0);
+    assertEquals(msg.getRepeatedUint64List().length, 0);
+    assertEquals(msg.getRepeatedSint32List().length, 0);
+    assertEquals(msg.getRepeatedSint64List().length, 0);
+    assertEquals(msg.getRepeatedFixed32List().length, 0);
+    assertEquals(msg.getRepeatedFixed64List().length, 0);
+    assertEquals(msg.getRepeatedSfixed32List().length, 0);
+    assertEquals(msg.getRepeatedSfixed64List().length, 0);
+    assertEquals(msg.getRepeatedFloatList().length, 0);
+    assertEquals(msg.getRepeatedDoubleList().length, 0);
+    assertEquals(msg.getRepeatedStringList().length, 0);
+    assertEquals(msg.getRepeatedBytesList().length, 0);
+    assertEquals(msg.getRepeatedForeignEnumList().length, 0);
+    assertEquals(msg.getRepeatedForeignMessageList().length, 0);
+
+  });
+
+
+  /**
+   * Test that all fields can be set and read via a serialization roundtrip.
+   */
+  it('testProto3FieldSetGet', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    msg.setOptionalInt32(-42);
+    msg.setOptionalInt64(-0x7fffffff00000000);
+    msg.setOptionalUint32(0x80000000);
+    msg.setOptionalUint64(0xf000000000000000);
+    msg.setOptionalSint32(-100);
+    msg.setOptionalSint64(-0x8000000000000000);
+    msg.setOptionalFixed32(1234);
+    msg.setOptionalFixed64(0x1234567800000000);
+    msg.setOptionalSfixed32(-1234);
+    msg.setOptionalSfixed64(-0x1234567800000000);
+    msg.setOptionalFloat(1.5);
+    msg.setOptionalDouble(-1.5);
+    msg.setOptionalBool(true);
+    msg.setOptionalString('hello world');
+    msg.setOptionalBytes(BYTES);
+    var submsg = new proto.jspb.test.ForeignMessage();
+    submsg.setC(16);
+    msg.setOptionalForeignMessage(submsg);
+    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+
+    msg.setRepeatedInt32List([-42]);
+    msg.setRepeatedInt64List([-0x7fffffff00000000]);
+    msg.setRepeatedUint32List([0x80000000]);
+    msg.setRepeatedUint64List([0xf000000000000000]);
+    msg.setRepeatedSint32List([-100]);
+    msg.setRepeatedSint64List([-0x8000000000000000]);
+    msg.setRepeatedFixed32List([1234]);
+    msg.setRepeatedFixed64List([0x1234567800000000]);
+    msg.setRepeatedSfixed32List([-1234]);
+    msg.setRepeatedSfixed64List([-0x1234567800000000]);
+    msg.setRepeatedFloatList([1.5]);
+    msg.setRepeatedDoubleList([-1.5]);
+    msg.setRepeatedBoolList([true]);
+    msg.setRepeatedStringList(['hello world']);
+    msg.setRepeatedBytesList([BYTES]);
+    submsg = new proto.jspb.test.ForeignMessage();
+    submsg.setC(1000);
+    msg.setRepeatedForeignMessageList([submsg]);
+    msg.setRepeatedForeignEnumList([proto.jspb.test.Proto3Enum.PROTO3_BAR]);
+
+    msg.setOneofString('asdf');
+
+    var serialized = msg.serializeBinary();
+    msg = proto.jspb.test.TestProto3.deserializeBinary(serialized);
+
+    assertEquals(msg.getOptionalInt32(), -42);
+    assertEquals(msg.getOptionalInt64(), -0x7fffffff00000000);
+    assertEquals(msg.getOptionalUint32(), 0x80000000);
+    assertEquals(msg.getOptionalUint64(), 0xf000000000000000);
+    assertEquals(msg.getOptionalSint32(), -100);
+    assertEquals(msg.getOptionalSint64(), -0x8000000000000000);
+    assertEquals(msg.getOptionalFixed32(), 1234);
+    assertEquals(msg.getOptionalFixed64(), 0x1234567800000000);
+    assertEquals(msg.getOptionalSfixed32(), -1234);
+    assertEquals(msg.getOptionalSfixed64(), -0x1234567800000000);
+    assertEquals(msg.getOptionalFloat(), 1.5);
+    assertEquals(msg.getOptionalDouble(), -1.5);
+    assertEquals(msg.getOptionalBool(), true);
+    assertEquals(msg.getOptionalString(), 'hello world');
+    assertEquals(true, bytesCompare(msg.getOptionalBytes(), BYTES));
+    assertEquals(msg.getOptionalForeignMessage().getC(), 16);
+    assertEquals(msg.getOptionalForeignEnum(),
+        proto.jspb.test.Proto3Enum.PROTO3_BAR);
+
+    assertElementsEquals(msg.getRepeatedInt32List(), [-42]);
+    assertElementsEquals(msg.getRepeatedInt64List(), [-0x7fffffff00000000]);
+    assertElementsEquals(msg.getRepeatedUint32List(), [0x80000000]);
+    assertElementsEquals(msg.getRepeatedUint64List(), [0xf000000000000000]);
+    assertElementsEquals(msg.getRepeatedSint32List(), [-100]);
+    assertElementsEquals(msg.getRepeatedSint64List(), [-0x8000000000000000]);
+    assertElementsEquals(msg.getRepeatedFixed32List(), [1234]);
+    assertElementsEquals(msg.getRepeatedFixed64List(), [0x1234567800000000]);
+    assertElementsEquals(msg.getRepeatedSfixed32List(), [-1234]);
+    assertElementsEquals(msg.getRepeatedSfixed64List(), [-0x1234567800000000]);
+    assertElementsEquals(msg.getRepeatedFloatList(), [1.5]);
+    assertElementsEquals(msg.getRepeatedDoubleList(), [-1.5]);
+    assertElementsEquals(msg.getRepeatedBoolList(), [true]);
+    assertElementsEquals(msg.getRepeatedStringList(), ['hello world']);
+    assertEquals(msg.getRepeatedBytesList().length, 1);
+    assertEquals(true, bytesCompare(msg.getRepeatedBytesList()[0], BYTES));
+    assertEquals(msg.getRepeatedForeignMessageList().length, 1);
+    assertEquals(msg.getRepeatedForeignMessageList()[0].getC(), 1000);
+    assertElementsEquals(msg.getRepeatedForeignEnumList(),
+        [proto.jspb.test.Proto3Enum.PROTO3_BAR]);
+
+    assertEquals(msg.getOneofString(), 'asdf');
+  });
+
+
+  /**
+   * Test that oneofs continue to have a notion of field presence.
+   */
+  it('testOneofs', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    assertEquals(msg.getOneofUint32(), 0);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), '');
+    assertEquals(msg.getOneofBytes(), '');
+    assertFalse(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofString());
+    assertFalse(msg.hasOneofBytes());
+
+    msg.setOneofUint32(42);
+    assertEquals(msg.getOneofUint32(), 42);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), '');
+    assertEquals(msg.getOneofBytes(), '');
+    assertTrue(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofString());
+    assertFalse(msg.hasOneofBytes());
+
+
+    var submsg = new proto.jspb.test.ForeignMessage();
+    msg.setOneofForeignMessage(submsg);
+    assertEquals(msg.getOneofUint32(), 0);
+    assertEquals(msg.getOneofForeignMessage(), submsg);
+    assertEquals(msg.getOneofString(), '');
+    assertEquals(msg.getOneofBytes(), '');
+    assertFalse(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofString());
+    assertFalse(msg.hasOneofBytes());
+
+    msg.setOneofString('hello');
+    assertEquals(msg.getOneofUint32(), 0);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), 'hello');
+    assertEquals(msg.getOneofBytes(), '');
+    assertFalse(msg.hasOneofUint32());
+    assertTrue(msg.hasOneofString());
+    assertFalse(msg.hasOneofBytes());
+
+    msg.setOneofBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+    assertEquals(msg.getOneofUint32(), 0);
+    assertEquals(msg.getOneofForeignMessage(), undefined);
+    assertEquals(msg.getOneofString(), '');
+    assertEquals(msg.getOneofBytes_asB64(),
+        goog.crypt.base64.encodeString('\u00FF\u00FF'));
+    assertFalse(msg.hasOneofUint32());
+    assertFalse(msg.hasOneofString());
+    assertTrue(msg.hasOneofBytes());
+  });
+
+
+  /**
+   * Test that "default"-valued primitive fields are not emitted on the wire.
+   */
+  it('testNoSerializeDefaults', function() {
+    var msg = new proto.jspb.test.TestProto3();
+
+    // Set each primitive to a non-default value, then back to its default, to
+    // ensure that the serialization is actually checking the value and not just
+    // whether it has ever been set.
+    msg.setOptionalInt32(42);
+    msg.setOptionalInt32(0);
+    msg.setOptionalDouble(3.14);
+    msg.setOptionalDouble(0.0);
+    msg.setOptionalBool(true);
+    msg.setOptionalBool(false);
+    msg.setOptionalString('hello world');
+    msg.setOptionalString('');
+    msg.setOptionalBytes(goog.crypt.base64.encodeString('\u00FF\u00FF'));
+    msg.setOptionalBytes('');
+    msg.setOptionalForeignMessage(new proto.jspb.test.ForeignMessage());
+    msg.setOptionalForeignMessage(null);
+    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR);
+    msg.setOptionalForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_FOO);
+    msg.setOneofUint32(32);
+    msg.clearOneofUint32();
+
+
+    var serialized = msg.serializeBinary();
+    assertEquals(0, serialized.length);
+  });
+
+  /**
+   * Test that base64 string and Uint8Array are interchangeable in bytes fields.
+   */
+  it('testBytesFieldsInterop', function() {
+    var msg = new proto.jspb.test.TestProto3();
+    // Set as a base64 string and check all the getters work.
+    msg.setOptionalBytes(BYTES_B64);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    // Test binary serialize round trip doesn't break it.
+    msg = proto.jspb.test.TestProto3.deserializeBinary(msg.serializeBinary());
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+    msg = new proto.jspb.test.TestProto3();
+    // Set as a Uint8Array and check all the getters work.
+    msg.setOptionalBytes(BYTES);
+    assertTrue(bytesCompare(msg.getOptionalBytes_asU8(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes_asB64(), BYTES));
+    assertTrue(bytesCompare(msg.getOptionalBytes(), BYTES));
+
+  });
+});
diff --git a/js/compatibility_tests/v3.1.0/proto3_test.proto b/js/compatibility_tests/v3.1.0/proto3_test.proto
new file mode 100644
index 0000000..acb6716
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/proto3_test.proto
@@ -0,0 +1,89 @@
+// 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 "testbinary.proto";
+
+package jspb.test;
+
+message TestProto3 {
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
+
+  ForeignMessage optional_foreign_message = 19;
+  Proto3Enum     optional_foreign_enum    = 22;
+
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated ForeignMessage repeated_foreign_message = 49;
+  repeated Proto3Enum     repeated_foreign_enum    = 52;
+
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    ForeignMessage oneof_foreign_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+}
+
+enum Proto3Enum {
+  PROTO3_FOO = 0;
+  PROTO3_BAR = 1;
+  PROTO3_BAZ = 2;
+}
diff --git a/js/compatibility_tests/v3.1.0/test.proto b/js/compatibility_tests/v3.1.0/test.proto
new file mode 100644
index 0000000..48cb37e
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test.proto
@@ -0,0 +1,262 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: [email protected] (Mark Rawling)
+
+syntax = "proto2";
+
+option java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+import "google/protobuf/descriptor.proto";
+
+package jspb.test;
+
+message Empty {
+}
+
+enum OuterEnum {
+  FOO = 1;
+  BAR = 2;
+}
+
+message EnumContainer {
+  optional OuterEnum outer_enum = 1;
+}
+
+message Simple1 {
+  required string a_string = 1;
+  repeated string a_repeated_string = 2;
+  optional bool a_boolean = 3;
+}
+
+// A message that differs from Simple1 only by name
+message Simple2 {
+  required string a_string = 1;
+  repeated string a_repeated_string = 2;
+}
+
+message SpecialCases {
+  required string normal = 1;
+  // Examples of Js reserved names that are converted to pb_<name>.
+  required string default = 2;
+  required string function = 3;
+  required string var = 4;
+}
+
+message OptionalFields {
+  message Nested {
+    optional int32 an_int = 1;
+  }
+  optional string a_string = 1;
+  required bool a_bool = 2;
+  optional Nested a_nested_message = 3;
+  repeated Nested a_repeated_message = 4;
+  repeated string a_repeated_string = 5;
+}
+
+message HasExtensions {
+  optional string str1 = 1;
+  optional string str2 = 2;
+  optional string str3 = 3;
+  extensions 10 to max;
+}
+
+message Complex {
+  message Nested {
+    required int32 an_int = 2;
+  }
+  required string a_string = 1;
+  required bool an_out_of_order_bool = 9;
+  optional Nested a_nested_message = 4;
+  repeated Nested a_repeated_message = 5;
+  repeated string a_repeated_string = 7;
+}
+
+message OuterMessage {
+  // Make sure this doesn't conflict with the other Complex message.
+  message Complex {
+    optional int32 inner_complex_field = 1;
+  }
+}
+
+message IsExtension {
+  extend HasExtensions {
+    optional IsExtension ext_field = 100;
+  }
+  optional string ext1 = 1;
+
+  // Extensions of proto2 Descriptor messages will be ignored.
+  extend google.protobuf.EnumOptions {
+    optional string simple_option = 42113038;
+  }
+}
+
+message IndirectExtension {
+  extend HasExtensions {
+    optional Simple1 simple = 101;
+    optional string str = 102;
+    repeated string repeated_str = 103;
+    repeated Simple1 repeated_simple = 104;
+  }
+}
+
+extend HasExtensions {
+  optional Simple1 simple1 = 105;
+}
+
+message DefaultValues {
+  enum Enum {
+    E1 = 13;
+    E2 = 77;
+  }
+  optional string string_field = 1 [default="default<>\'\"abc"];
+  optional bool bool_field = 2 [default=true];
+  optional int64 int_field = 3 [default=11];
+  optional Enum enum_field = 4 [default=E1];
+  optional string empty_field = 6 [default=""];
+  optional bytes bytes_field = 8 [default="moo"]; // Base64 encoding is "bW9v"
+}
+
+message FloatingPointFields {
+  optional float optional_float_field = 1;
+  required float required_float_field = 2;
+  repeated float repeated_float_field = 3;
+  optional float default_float_field = 4 [default = 2.0];
+  optional double optional_double_field = 5;
+  required double required_double_field = 6;
+  repeated double repeated_double_field = 7;
+  optional double default_double_field = 8 [default = 2.0];
+}
+
+message TestClone {
+  optional string str = 1;
+  optional Simple1 simple1 = 3;
+  repeated Simple1 simple2 = 5;
+  optional bytes bytes_field = 6;
+  optional string unused = 7;
+  extensions 10 to max;
+}
+
+message CloneExtension {
+  extend TestClone {
+    optional CloneExtension ext_field = 100;
+  }
+  optional string ext = 2;
+}
+
+message TestGroup {
+  repeated group RepeatedGroup = 1 {
+    required string id = 1;
+    repeated bool some_bool = 2;
+  }
+  required group RequiredGroup = 2 {
+    required string id = 1;
+  }
+  optional group OptionalGroup = 3 {
+    required string id = 1;
+  }
+  optional string id = 4;
+  required Simple2 required_simple = 5;
+  optional Simple2 optional_simple = 6;
+}
+
+message TestGroup1 {
+  optional TestGroup.RepeatedGroup group = 1;
+}
+
+message TestReservedNames {
+  optional int32 extension = 1;
+  extensions 10 to max;
+}
+
+message TestReservedNamesExtension {
+  extend TestReservedNames {
+    optional int32 foo = 10;
+  }
+}
+
+message TestMessageWithOneof {
+
+  oneof partial_oneof {
+    string pone = 3;
+    string pthree = 5;
+  }
+
+  oneof recursive_oneof {
+    TestMessageWithOneof rone = 6;
+    string rtwo = 7;
+  }
+
+  optional bool normal_field = 8;
+  repeated string repeated_field = 9;
+
+  oneof default_oneof_a {
+    int32 aone = 10 [default = 1234];
+    int32 atwo = 11;
+  }
+
+  oneof default_oneof_b {
+    int32 bone = 12;
+    int32 btwo = 13 [default = 1234];
+  }
+}
+
+message TestEndsWithBytes {
+  optional int32 value = 1;
+  optional bytes data = 2;
+}
+
+message TestMapFieldsNoBinary {
+  map<string, string> map_string_string = 1;
+  map<string, int32> map_string_int32 = 2;
+  map<string, int64> map_string_int64 = 3;
+  map<string, bool> map_string_bool = 4;
+  map<string, double> map_string_double = 5;
+  map<string, MapValueEnumNoBinary> map_string_enum = 6;
+  map<string, MapValueMessageNoBinary> map_string_msg = 7;
+
+  map<int32, string> map_int32_string = 8;
+  map<int64, string> map_int64_string = 9;
+  map<bool, string> map_bool_string = 10;
+
+  optional TestMapFieldsNoBinary test_map_fields = 11;
+  map<string, TestMapFieldsNoBinary> map_string_testmapfields = 12;
+}
+
+enum MapValueEnumNoBinary {
+  MAP_VALUE_FOO_NOBINARY = 0;
+  MAP_VALUE_BAR_NOBINARY = 1;
+  MAP_VALUE_BAZ_NOBINARY = 2;
+}
+
+message MapValueMessageNoBinary {
+  optional int32 foo = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/test2.proto b/js/compatibility_tests/v3.1.0/test2.proto
new file mode 100644
index 0000000..44e55ef
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test2.proto
@@ -0,0 +1,54 @@
+// 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 java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.test;
+
+message TestExtensionsMessage {
+  optional int32 intfield = 1;
+  extensions 100 to max;
+}
+
+message ExtensionMessage {
+  extend TestExtensionsMessage {
+    optional ExtensionMessage ext_field = 100;
+  }
+  optional string ext1 = 1;
+}
+
+// Floating extensions are only supported when generating a _lib.js library.
+extend TestExtensionsMessage {
+  optional ExtensionMessage floating_msg_field = 101;
+  optional string floating_str_field = 102;
+}
diff --git a/js/compatibility_tests/v3.1.0/test3.proto b/js/compatibility_tests/v3.1.0/test3.proto
new file mode 100644
index 0000000..940a552
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test3.proto
@@ -0,0 +1,53 @@
+// 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 java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest;
+
+message TestExtensionsMessage {
+  optional int32 intfield = 1;
+  extensions 100 to max;
+}
+
+message ExtensionMessage {
+  extend TestExtensionsMessage {
+    optional ExtensionMessage ext_field = 100;
+  }
+  optional string ext1 = 1;
+}
+
+extend TestExtensionsMessage {
+  optional ExtensionMessage floating_msg_field = 101;
+  optional string floating_str_field = 102;
+}
diff --git a/js/compatibility_tests/v3.1.0/test4.proto b/js/compatibility_tests/v3.1.0/test4.proto
new file mode 100644
index 0000000..cf2451e
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test4.proto
@@ -0,0 +1,42 @@
+// 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 java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest;
+
+import "test3.proto";
+
+extend TestExtensionsMessage {
+  optional ExtensionMessage floating_msg_field_two = 103;
+}
diff --git a/js/compatibility_tests/v3.1.0/test5.proto b/js/compatibility_tests/v3.1.0/test5.proto
new file mode 100644
index 0000000..3497951
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/test5.proto
@@ -0,0 +1,44 @@
+// 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 java_package = "com.google.apps.jspb.proto";
+option java_multiple_files = true;
+
+package jspb.exttest.beta;
+
+message TestBetaExtensionsMessage {
+  extensions 100 to max;
+}
+
+extend TestBetaExtensionsMessage {
+  optional string floating_str_field = 101;
+}
diff --git a/js/compatibility_tests/v3.1.0/testbinary.proto b/js/compatibility_tests/v3.1.0/testbinary.proto
new file mode 100644
index 0000000..116f17f
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/testbinary.proto
@@ -0,0 +1,212 @@
+// 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.
+
+// LINT: ALLOW_GROUPS
+
+syntax = "proto2";
+
+
+package jspb.test;
+
+// These types are borrowed from `unittest.proto` in the protobuf tree. We want
+// to ensure that the binary-format support will handle all field types
+// properly.
+message TestAllTypes {
+  optional    int32 optional_int32    =  1;
+  optional    int64 optional_int64    =  2;
+  optional   uint32 optional_uint32   =  3;
+  optional   uint64 optional_uint64   =  4;
+  optional   sint32 optional_sint32   =  5;
+  optional   sint64 optional_sint64   =  6;
+  optional  fixed32 optional_fixed32  =  7;
+  optional  fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional    float optional_float    = 11;
+  optional   double optional_double   = 12;
+  optional     bool optional_bool     = 13;
+  optional   string optional_string   = 14;
+  optional    bytes optional_bytes    = 15;
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+
+  optional ForeignMessage                       optional_foreign_message = 19;
+  optional ForeignEnum                          optional_foreign_enum    = 22;
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated group RepeatedGroup = 46 {
+    optional int32 a = 47;
+  }
+
+  repeated ForeignMessage                       repeated_foreign_message = 49;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+
+  // Packed repeated
+  repeated    int32 packed_repeated_int32    = 61 [packed=true];
+  repeated    int64 packed_repeated_int64    = 62 [packed=true];
+  repeated   uint32 packed_repeated_uint32   = 63 [packed=true];
+  repeated   uint64 packed_repeated_uint64   = 64 [packed=true];
+  repeated   sint32 packed_repeated_sint32   = 65 [packed=true];
+  repeated   sint64 packed_repeated_sint64   = 66 [packed=true];
+  repeated  fixed32 packed_repeated_fixed32  = 67 [packed=true];
+  repeated  fixed64 packed_repeated_fixed64  = 68 [packed=true];
+  repeated sfixed32 packed_repeated_sfixed32 = 69 [packed=true];
+  repeated sfixed64 packed_repeated_sfixed64 = 70 [packed=true];
+  repeated    float packed_repeated_float    = 71 [packed=true];
+  repeated   double packed_repeated_double   = 72 [packed=true];
+  repeated     bool packed_repeated_bool     = 73 [packed=true];
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    ForeignMessage oneof_foreign_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+  }
+
+}
+
+message ForeignMessage {
+  optional int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+message TestExtendable {
+  extensions 1 to max;
+}
+
+message ExtendsWithMessage {
+  extend TestExtendable {
+    optional ExtendsWithMessage optional_extension = 19;
+    repeated ExtendsWithMessage repeated_extension = 49;
+  }
+  optional int32 foo = 1;
+}
+
+extend TestExtendable {
+  optional    int32 extend_optional_int32    =  1;
+  optional    int64 extend_optional_int64    =  2;
+  optional   uint32 extend_optional_uint32   =  3;
+  optional   uint64 extend_optional_uint64   =  4;
+  optional   sint32 extend_optional_sint32   =  5;
+  optional   sint64 extend_optional_sint64   =  6;
+  optional  fixed32 extend_optional_fixed32  =  7;
+  optional  fixed64 extend_optional_fixed64  =  8;
+  optional sfixed32 extend_optional_sfixed32 =  9;
+  optional sfixed64 extend_optional_sfixed64 = 10;
+  optional    float extend_optional_float    = 11;
+  optional   double extend_optional_double   = 12;
+  optional     bool extend_optional_bool     = 13;
+  optional   string extend_optional_string   = 14;
+  optional    bytes extend_optional_bytes    = 15;
+  optional ForeignEnum extend_optional_foreign_enum    = 22;
+
+  repeated    int32 extend_repeated_int32    = 31;
+  repeated    int64 extend_repeated_int64    = 32;
+  repeated   uint32 extend_repeated_uint32   = 33;
+  repeated   uint64 extend_repeated_uint64   = 34;
+  repeated   sint32 extend_repeated_sint32   = 35;
+  repeated   sint64 extend_repeated_sint64   = 36;
+  repeated  fixed32 extend_repeated_fixed32  = 37;
+  repeated  fixed64 extend_repeated_fixed64  = 38;
+  repeated sfixed32 extend_repeated_sfixed32 = 39;
+  repeated sfixed64 extend_repeated_sfixed64 = 40;
+  repeated    float extend_repeated_float    = 41;
+  repeated   double extend_repeated_double   = 42;
+  repeated     bool extend_repeated_bool     = 43;
+  repeated   string extend_repeated_string   = 44;
+  repeated    bytes extend_repeated_bytes    = 45;
+  repeated ForeignEnum extend_repeated_foreign_enum    = 52;
+
+  repeated    int32 extend_packed_repeated_int32    = 61 [packed=true];
+  repeated    int64 extend_packed_repeated_int64    = 62 [packed=true];
+  repeated   uint32 extend_packed_repeated_uint32   = 63 [packed=true];
+  repeated   uint64 extend_packed_repeated_uint64   = 64 [packed=true];
+  repeated   sint32 extend_packed_repeated_sint32   = 65 [packed=true];
+  repeated   sint64 extend_packed_repeated_sint64   = 66 [packed=true];
+  repeated  fixed32 extend_packed_repeated_fixed32  = 67 [packed=true];
+  repeated  fixed64 extend_packed_repeated_fixed64  = 68 [packed=true];
+  repeated sfixed32 extend_packed_repeated_sfixed32 = 69 [packed=true];
+  repeated sfixed64 extend_packed_repeated_sfixed64 = 70 [packed=true];
+  repeated    float extend_packed_repeated_float    = 71 [packed=true];
+  repeated   double extend_packed_repeated_double   = 72 [packed=true];
+  repeated     bool extend_packed_repeated_bool     = 73 [packed=true];
+  repeated ForeignEnum extend_packed_repeated_foreign_enum    = 82
+      [packed=true];
+
+}
+
+message TestMapFields {
+  map<string, string> map_string_string = 1;
+  map<string, int32> map_string_int32 = 2;
+  map<string, int64> map_string_int64 = 3;
+  map<string, bool> map_string_bool = 4;
+  map<string, double> map_string_double = 5;
+  map<string, MapValueEnum> map_string_enum = 6;
+  map<string, MapValueMessage> map_string_msg = 7;
+
+  map<int32, string> map_int32_string = 8;
+  map<int64, string> map_int64_string = 9;
+  map<bool, string> map_bool_string = 10;
+
+  optional TestMapFields test_map_fields = 11;
+  map<string, TestMapFields> map_string_testmapfields = 12;
+}
+
+enum MapValueEnum {
+  MAP_VALUE_FOO = 0;
+  MAP_VALUE_BAR = 1;
+  MAP_VALUE_BAZ = 2;
+}
+
+message MapValueMessage {
+  optional int32 foo = 1;
+}
diff --git a/js/compatibility_tests/v3.1.0/testempty.proto b/js/compatibility_tests/v3.1.0/testempty.proto
new file mode 100644
index 0000000..960bce4
--- /dev/null
+++ b/js/compatibility_tests/v3.1.0/testempty.proto
@@ -0,0 +1,34 @@
+// 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";
+
+package javatests.com.google.apps.jspb;
+
diff --git a/js/message.js b/js/message.js
index 1f6bf16..f7dcfa9 100644
--- a/js/message.js
+++ b/js/message.js
@@ -41,7 +41,6 @@
 goog.require('goog.array');
 goog.require('goog.asserts');
 goog.require('goog.crypt.base64');
-goog.require('goog.json');
 goog.require('jspb.Map');
 
 // Not needed in compilation units that have no protos with xids.
@@ -192,8 +191,8 @@
 
 /**
  * @define {boolean} Whether to generate toString methods for objects. Turn
- *     this off if you do use toString in your project and want to trim it from
- *     compiled JS.
+ *     this off if you do not use toString in your project and want to trim it
+ *     from the compiled JS.
  */
 goog.define('jspb.Message.GENERATE_TO_STRING', true);
 
@@ -351,7 +350,7 @@
   // which would otherwise go unused.
   msg.arrayIndexOffset_ = messageId === 0 ? -1 : 0;
   msg.array = data;
-  jspb.Message.materializeExtensionObject_(msg, suggestedPivot);
+  jspb.Message.initPivotAndExtensionObject_(msg, suggestedPivot);
   msg.convertedFloatingPointFields_ = {};
 
   if (repeatedFields) {
@@ -364,6 +363,7 @@
                 jspb.Message.EMPTY_LIST_SENTINEL_ :
                 []);
       } else {
+        jspb.Message.maybeInitEmptyExtensionObject_(msg);
         msg.extensionObject_[fieldNumber] =
             msg.extensionObject_[fieldNumber] ||
             (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS ?
@@ -408,17 +408,16 @@
 
 
 /**
- * Ensures that the array contains an extension object if necessary.
  * If the array contains an extension object in its last position, then the
- * object is kept in place and its position is used as the pivot.  If not, then
- * create an extension object using suggestedPivot.  If suggestedPivot is -1,
- * we don't have an extension object at all, in which case all fields are stored
- * in the array.
+ * object is kept in place and its position is used as the pivot.  If not,
+ * decides the pivot of the message based on suggestedPivot without
+ * materializing the extension object.
+ *
  * @param {!jspb.Message} msg The JsPb proto to modify.
  * @param {number} suggestedPivot See description for initialize().
  * @private
  */
-jspb.Message.materializeExtensionObject_ = function(msg, suggestedPivot) {
+jspb.Message.initPivotAndExtensionObject_ = function(msg, suggestedPivot) {
   if (msg.array.length) {
     var foundIndex = msg.array.length - 1;
     var obj = msg.array[foundIndex];
@@ -434,26 +433,17 @@
       return;
     }
   }
-  // This complexity exists because we keep all extension fields in the
-  // extensionObject_ regardless of proto field number. Changing this would
-  // simplify the code here, but it would require changing the serialization
-  // format from the server, which is not backwards compatible.
-  // TODO(jshneier): Should we just treat extension fields the same as
-  // non-extension fields, and select whether they appear in the object or in
-  // the array purely based on tag number? This would allow simplifying all the
-  // get/setExtension logic, but it would require the breaking change described
-  // above.
+
   if (suggestedPivot > -1) {
     msg.pivot_ = suggestedPivot;
-    var pivotIndex = jspb.Message.getIndex_(msg, suggestedPivot);
-    if (!jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
-      msg.extensionObject_ = msg.array[pivotIndex] = {};
-    } else {
-      // Initialize to null to avoid changing the shape of the proto when it
-      // gets eventually set.
-      msg.extensionObject_ = null;
-    }
+    // Avoid changing the shape of the proto with an empty extension object by
+    // deferring the materialization of the extension object until the first
+    // time a field set into it (may be due to getting a repeated proto field
+    // from it, in which case a new empty array is set into it at first).
+    msg.extensionObject_ = null;
   } else {
+    // suggestedPivot is -1, which means that we don't have an extension object
+    // at all, in which case all fields are stored in the array.
     msg.pivot_ = Number.MAX_VALUE;
   }
 };
@@ -513,7 +503,7 @@
   for (var fieldNumber in extensions) {
     var fieldInfo = extensions[fieldNumber];
     var value = getExtensionFn.call(proto, fieldInfo);
-    if (goog.isDefAndNotNull(value)) {
+    if (value != null) {
       for (var name in fieldInfo.fieldName) {
         if (fieldInfo.fieldName.hasOwnProperty(name)) {
           break; // the compiled field name
@@ -557,7 +547,7 @@
                       'without binary serialization support');
     }
     var value = getExtensionFn.call(proto, fieldInfo);
-    if (goog.isDefAndNotNull(value)) {
+    if (value != null) {
       if (fieldInfo.isMessageType()) {
         // If the message type of the extension was generated without binary
         // support, there may not be a binary message serializer function, and
@@ -647,6 +637,9 @@
     }
     return val;
   } else {
+    if (!msg.extensionObject_) {
+      return undefined;
+    }
     var val = msg.extensionObject_[fieldNumber];
     if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
       return msg.extensionObject_[fieldNumber] = [];
@@ -657,6 +650,32 @@
 
 
 /**
+ * Gets the value of a non-extension repeated field.
+ * @param {!jspb.Message} msg A jspb proto.
+ * @param {number} fieldNumber The field number.
+ * @return {!Array}
+ * The field's value.
+ * @protected
+ */
+jspb.Message.getRepeatedField = function(msg, fieldNumber) {
+  if (fieldNumber < msg.pivot_) {
+    var index = jspb.Message.getIndex_(msg, fieldNumber);
+    var val = msg.array[index];
+    if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+      return msg.array[index] = [];
+    }
+    return val;
+  }
+
+  var val = msg.extensionObject_[fieldNumber];
+  if (val === jspb.Message.EMPTY_LIST_SENTINEL_) {
+    return msg.extensionObject_[fieldNumber] = [];
+  }
+  return val;
+};
+
+
+/**
  * Gets the value of an optional float or double field.
  * @param {!jspb.Message} msg A jspb proto.
  * @param {number} fieldNumber The field number.
@@ -678,7 +697,7 @@
  * @protected
  */
 jspb.Message.getRepeatedFloatingPointField = function(msg, fieldNumber) {
-  var values = jspb.Message.getField(msg, fieldNumber);
+  var values = jspb.Message.getRepeatedField(msg, fieldNumber);
   if (!msg.convertedFloatingPointFields_) {
     msg.convertedFloatingPointFields_ = {};
   }
@@ -864,6 +883,7 @@
   if (fieldNumber < msg.pivot_) {
     msg.array[jspb.Message.getIndex_(msg, fieldNumber)] = value;
   } else {
+    jspb.Message.maybeInitEmptyExtensionObject_(msg);
     msg.extensionObject_[fieldNumber] = value;
   }
 };
@@ -878,7 +898,7 @@
  * @protected
  */
 jspb.Message.addToRepeatedField = function(msg, fieldNumber, value, opt_index) {
-  var arr = jspb.Message.getField(msg, fieldNumber);
+  var arr = jspb.Message.getRepeatedField(msg, fieldNumber);
   if (opt_index != undefined) {
     arr.splice(opt_index, 0, value);
   } else {
@@ -1006,7 +1026,7 @@
     msg.wrappers_ = {};
   }
   if (!msg.wrappers_[fieldNumber]) {
-    var data = jspb.Message.getField(msg, fieldNumber);
+    var data = jspb.Message.getRepeatedField(msg, fieldNumber);
     for (var wrappers = [], i = 0; i < data.length; i++) {
       wrappers[i] = new ctor(data[i]);
     }
@@ -1101,7 +1121,7 @@
     wrapperArray = msg.wrappers_[fieldNumber] = [];
   }
   var insertedValue = value ? value : new ctor();
-  var array = jspb.Message.getField(msg, fieldNumber);
+  var array = jspb.Message.getRepeatedField(msg, fieldNumber);
   if (index != undefined) {
     wrapperArray.splice(index, 0, insertedValue);
     array.splice(index, 0, insertedValue.toArray());
diff --git a/js/message_test.js b/js/message_test.js
index dc0ae21..7d61dac 100644
--- a/js/message_test.js
+++ b/js/message_test.js
@@ -33,6 +33,7 @@
 goog.setTestOnly();
 
 goog.require('goog.json');
+goog.require('goog.string');
 goog.require('goog.testing.asserts');
 goog.require('goog.userAgent');
 
@@ -83,8 +84,6 @@
 goog.require('proto.jspb.test.TestExtensionsMessage');
 
 
-
-
 describe('Message test suite', function() {
   it('testEmptyProto', function() {
     var empty1 = new proto.jspb.test.Empty([]);
@@ -273,12 +272,6 @@
     assertFalse(response.hasEnumField());
   });
 
-  it('testMessageRegistration', /** @suppress {visibility} */ function() {
-    // goog.require(SomeResponse) will include its library, which will in
-    // turn add SomeResponse to the message registry.
-    assertEquals(jspb.Message.registry_['res'], proto.jspb.test.SomeResponse);
-  });
-
   it('testClearFields', function() {
     var data = ['str', true, [11], [[22], [33]], ['s1', 's2']];
     var foo = new proto.jspb.test.OptionalFields(data);
@@ -661,12 +654,7 @@
 
   it('testInitialization_emptyArray', function() {
     var msg = new proto.jspb.test.HasExtensions([]);
-    if (jspb.Message.MINIMIZE_MEMORY_ALLOCATIONS) {
-      assertArrayEquals([], msg.toArray());
-    } else {
-      // Extension object is created past all regular fields.
-      assertArrayEquals([,,, {}], msg.toArray());
-    }
+    assertArrayEquals([], msg.toArray());
   });
 
   it('testInitialization_justExtensionObject', function() {
diff --git a/js/package.json b/js/package.json
index 14f54b8..c8b7538 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
 {
   "name": "google-protobuf",
-  "version": "3.3.0",
+  "version": "3.4.0",
   "description": "Protocol Buffers for JavaScript",
   "main": "google-protobuf.js",
   "files": [
diff --git a/js/proto3_test.proto b/js/proto3_test.proto
index acb6716..0d073ea 100644
--- a/js/proto3_test.proto
+++ b/js/proto3_test.proto
@@ -86,4 +86,5 @@
   PROTO3_FOO = 0;
   PROTO3_BAR = 1;
   PROTO3_BAZ = 2;
+  MSG_PROTO3_BAH = 3;
 }
diff --git a/js/test.proto b/js/test.proto
index 2be5b8c..7c881c0 100644
--- a/js/test.proto
+++ b/js/test.proto
@@ -235,6 +235,13 @@
 }
 
 
+message Int64Types {
+  optional int64 int64_normal = 1 [jstype=JS_NORMAL];
+  optional sint64 int64_string = 2 [jstype=JS_STRING];
+  optional uint64 int64_number = 3 [jstype=JS_NUMBER];
+
+}
+
 message TestMapFieldsNoBinary {
 
   map<string, string> map_string_string = 1;
@@ -271,3 +278,4 @@
     }
   }
 }
+
diff --git a/kokoro/README.md b/kokoro/README.md
new file mode 100644
index 0000000..0791c92
--- /dev/null
+++ b/kokoro/README.md
@@ -0,0 +1,6 @@
+
+Kokoro Infrastructure
+----------------------
+
+The files in this directory serve as plumbing for running Protobuf
+tests under Kokoro, our internal CI.
\ No newline at end of file
diff --git a/kokoro/linux/cpp_distcheck/build.sh b/kokoro/linux/cpp_distcheck/build.sh
new file mode 100755
index 0000000..b8b57e3
--- /dev/null
+++ b/kokoro/linux/cpp_distcheck/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/linux/prepare_build_linux_rc
+
+./tests.sh cpp_distcheck
diff --git a/kokoro/linux/cpp_distcheck/continuous.cfg b/kokoro/linux/cpp_distcheck/continuous.cfg
new file mode 100644
index 0000000..4289f6a
--- /dev/null
+++ b/kokoro/linux/cpp_distcheck/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cpp_distcheck/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/cpp_distcheck/presubmit.cfg b/kokoro/linux/cpp_distcheck/presubmit.cfg
new file mode 100644
index 0000000..4289f6a
--- /dev/null
+++ b/kokoro/linux/cpp_distcheck/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cpp_distcheck/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/csharp/build.sh b/kokoro/linux/csharp/build.sh
new file mode 100755
index 0000000..de178b8
--- /dev/null
+++ b/kokoro/linux/csharp/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/linux/prepare_build_linux_rc
+
+./tests.sh csharp
diff --git a/kokoro/linux/csharp/continuous.cfg b/kokoro/linux/csharp/continuous.cfg
new file mode 100644
index 0000000..3d17767
--- /dev/null
+++ b/kokoro/linux/csharp/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/csharp/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/csharp/presubmit.cfg b/kokoro/linux/csharp/presubmit.cfg
new file mode 100644
index 0000000..3d17767
--- /dev/null
+++ b/kokoro/linux/csharp/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/csharp/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/java_compatibility/build.sh b/kokoro/linux/java_compatibility/build.sh
new file mode 100755
index 0000000..b1ef279
--- /dev/null
+++ b/kokoro/linux/java_compatibility/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/linux/prepare_build_linux_rc
+
+./tests.sh java_compatibility
diff --git a/kokoro/linux/java_compatibility/continuous.cfg b/kokoro/linux/java_compatibility/continuous.cfg
new file mode 100644
index 0000000..4897f5c
--- /dev/null
+++ b/kokoro/linux/java_compatibility/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/java_compatibility/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/java_compatibility/presubmit.cfg b/kokoro/linux/java_compatibility/presubmit.cfg
new file mode 100644
index 0000000..4897f5c
--- /dev/null
+++ b/kokoro/linux/java_compatibility/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/java_compatibility/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/prepare_build_linux_rc b/kokoro/linux/prepare_build_linux_rc
new file mode 100644
index 0000000..4c3f255
--- /dev/null
+++ b/kokoro/linux/prepare_build_linux_rc
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Source this rc script to prepare the environment for Linux builds
+
+# Set up dotnet
+sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list'
+sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893
+sudo apt-get update
+sudo apt-get install -y dotnet-dev-1.0.4
diff --git a/kokoro/linux/python_compatibility/build.sh b/kokoro/linux/python_compatibility/build.sh
new file mode 100755
index 0000000..041e65f
--- /dev/null
+++ b/kokoro/linux/python_compatibility/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/linux/prepare_build_linux_rc
+
+./tests.sh python_compatibility
diff --git a/kokoro/linux/python_compatibility/continuous.cfg b/kokoro/linux/python_compatibility/continuous.cfg
new file mode 100644
index 0000000..4cf6bb0
--- /dev/null
+++ b/kokoro/linux/python_compatibility/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/python_compatibility/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/linux/python_compatibility/presubmit.cfg b/kokoro/linux/python_compatibility/presubmit.cfg
new file mode 100644
index 0000000..4cf6bb0
--- /dev/null
+++ b/kokoro/linux/python_compatibility/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/python_compatibility/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/cpp/build.sh b/kokoro/macos/cpp/build.sh
new file mode 100755
index 0000000..bae2ebb
--- /dev/null
+++ b/kokoro/macos/cpp/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh cpp
diff --git a/kokoro/macos/cpp/continuous.cfg b/kokoro/macos/cpp/continuous.cfg
new file mode 100644
index 0000000..4bea1cb
--- /dev/null
+++ b/kokoro/macos/cpp/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/cpp/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/cpp/presubmit.cfg b/kokoro/macos/cpp/presubmit.cfg
new file mode 100644
index 0000000..4bea1cb
--- /dev/null
+++ b/kokoro/macos/cpp/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/cpp/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/cpp_distcheck/build.sh b/kokoro/macos/cpp_distcheck/build.sh
new file mode 100755
index 0000000..d729b63
--- /dev/null
+++ b/kokoro/macos/cpp_distcheck/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh cpp_distcheck
diff --git a/kokoro/macos/cpp_distcheck/continuous.cfg b/kokoro/macos/cpp_distcheck/continuous.cfg
new file mode 100644
index 0000000..89441bc
--- /dev/null
+++ b/kokoro/macos/cpp_distcheck/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/cpp_distcheck/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/cpp_distcheck/presubmit.cfg b/kokoro/macos/cpp_distcheck/presubmit.cfg
new file mode 100644
index 0000000..89441bc
--- /dev/null
+++ b/kokoro/macos/cpp_distcheck/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/cpp_distcheck/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/javascript/build.sh b/kokoro/macos/javascript/build.sh
new file mode 100755
index 0000000..016832a
--- /dev/null
+++ b/kokoro/macos/javascript/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh javascript
diff --git a/kokoro/macos/javascript/continuous.cfg b/kokoro/macos/javascript/continuous.cfg
new file mode 100644
index 0000000..b478cc1
--- /dev/null
+++ b/kokoro/macos/javascript/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/javascript/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/javascript/presubmit.cfg b/kokoro/macos/javascript/presubmit.cfg
new file mode 100644
index 0000000..b478cc1
--- /dev/null
+++ b/kokoro/macos/javascript/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/javascript/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/jruby/build.sh b/kokoro/macos/jruby/build.sh
new file mode 100755
index 0000000..c82eaeb
--- /dev/null
+++ b/kokoro/macos/jruby/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh jruby
diff --git a/kokoro/macos/jruby/continuous.cfg b/kokoro/macos/jruby/continuous.cfg
new file mode 100644
index 0000000..f1310fd
--- /dev/null
+++ b/kokoro/macos/jruby/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/jruby/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/jruby/presubmit.cfg b/kokoro/macos/jruby/presubmit.cfg
new file mode 100644
index 0000000..f1310fd
--- /dev/null
+++ b/kokoro/macos/jruby/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/jruby/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_cocoapods_integration/build.sh b/kokoro/macos/objectivec_cocoapods_integration/build.sh
new file mode 100755
index 0000000..f96d289
--- /dev/null
+++ b/kokoro/macos/objectivec_cocoapods_integration/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh objectivec_cocoapods_integration
diff --git a/kokoro/macos/objectivec_cocoapods_integration/continuous.cfg b/kokoro/macos/objectivec_cocoapods_integration/continuous.cfg
new file mode 100644
index 0000000..952874e
--- /dev/null
+++ b/kokoro/macos/objectivec_cocoapods_integration/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_cocoapods_integration/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_cocoapods_integration/presubmit.cfg b/kokoro/macos/objectivec_cocoapods_integration/presubmit.cfg
new file mode 100644
index 0000000..952874e
--- /dev/null
+++ b/kokoro/macos/objectivec_cocoapods_integration/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_cocoapods_integration/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_ios_debug/build.sh b/kokoro/macos/objectivec_ios_debug/build.sh
new file mode 100755
index 0000000..1055d72
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_debug/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh objectivec_ios_debug
diff --git a/kokoro/macos/objectivec_ios_debug/continuous.cfg b/kokoro/macos/objectivec_ios_debug/continuous.cfg
new file mode 100644
index 0000000..473d545
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_debug/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_ios_debug/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_ios_debug/presubmit.cfg b/kokoro/macos/objectivec_ios_debug/presubmit.cfg
new file mode 100644
index 0000000..473d545
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_debug/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_ios_debug/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_ios_release/build.sh b/kokoro/macos/objectivec_ios_release/build.sh
new file mode 100755
index 0000000..76ce3ba
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_release/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh objectivec_ios_release
diff --git a/kokoro/macos/objectivec_ios_release/continuous.cfg b/kokoro/macos/objectivec_ios_release/continuous.cfg
new file mode 100644
index 0000000..3cbfb68
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_release/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_ios_release/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_ios_release/presubmit.cfg b/kokoro/macos/objectivec_ios_release/presubmit.cfg
new file mode 100644
index 0000000..3cbfb68
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_release/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_ios_release/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_osx/build.sh b/kokoro/macos/objectivec_osx/build.sh
new file mode 100755
index 0000000..000be27
--- /dev/null
+++ b/kokoro/macos/objectivec_osx/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh objectivec_osx
diff --git a/kokoro/macos/objectivec_osx/continuous.cfg b/kokoro/macos/objectivec_osx/continuous.cfg
new file mode 100644
index 0000000..41bd46a
--- /dev/null
+++ b/kokoro/macos/objectivec_osx/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_osx/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_osx/presubmit.cfg b/kokoro/macos/objectivec_osx/presubmit.cfg
new file mode 100644
index 0000000..41bd46a
--- /dev/null
+++ b/kokoro/macos/objectivec_osx/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_osx/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/build.sh b/kokoro/macos/php5.6_mac/build.sh
new file mode 100755
index 0000000..7487889
--- /dev/null
+++ b/kokoro/macos/php5.6_mac/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh php5.6_mac
diff --git a/kokoro/macos/php5.6_mac/continuous.cfg b/kokoro/macos/php5.6_mac/continuous.cfg
new file mode 100644
index 0000000..ff345e9
--- /dev/null
+++ b/kokoro/macos/php5.6_mac/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/php5.6_mac/presubmit.cfg b/kokoro/macos/php5.6_mac/presubmit.cfg
new file mode 100644
index 0000000..ff345e9
--- /dev/null
+++ b/kokoro/macos/php5.6_mac/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php5.6_mac/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/php7.0_mac/build.sh b/kokoro/macos/php7.0_mac/build.sh
new file mode 100755
index 0000000..e5a37e3
--- /dev/null
+++ b/kokoro/macos/php7.0_mac/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh php7.0_mac
diff --git a/kokoro/macos/php7.0_mac/continuous.cfg b/kokoro/macos/php7.0_mac/continuous.cfg
new file mode 100644
index 0000000..c2c1811
--- /dev/null
+++ b/kokoro/macos/php7.0_mac/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php7.0_mac/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/php7.0_mac/presubmit.cfg b/kokoro/macos/php7.0_mac/presubmit.cfg
new file mode 100644
index 0000000..c2c1811
--- /dev/null
+++ b/kokoro/macos/php7.0_mac/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php7.0_mac/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/prepare_build_macos_rc b/kokoro/macos/prepare_build_macos_rc
new file mode 100755
index 0000000..dfe66ff
--- /dev/null
+++ b/kokoro/macos/prepare_build_macos_rc
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# This script sets up a Kokoro MacOS worker for running Protobuf tests
+
+##
+# Select Xcode version
+
+export DEVELOPER_DIR=/Applications/Xcode_8.1.app/Contents/Developer
+
+##
+# Select C/C++ compilers
+
+export CC=gcc
+export CXX=g++
+
+##
+# Install Brew and core softwares
+
+ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
+source $HOME/.rvm/scripts/rvm
+brew tap homebrew/homebrew-php
+brew uninstall node icu4c
+brew install gflags gpg gpg2 node pcre php56 ruby
+
+##
+# Install Tox
+
+sudo pip install tox==2.4.1
+
+##
+# Install RVM
+
+gpg2 --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
+command curl -sSL https://rvm.io/mpapis.asc | gpg2 --import -
+curl -sSL https://get.rvm.io | bash -s stable --ruby
diff --git a/kokoro/macos/python/build.sh b/kokoro/macos/python/build.sh
new file mode 100755
index 0000000..6b17b95
--- /dev/null
+++ b/kokoro/macos/python/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh python
diff --git a/kokoro/macos/python/continuous.cfg b/kokoro/macos/python/continuous.cfg
new file mode 100644
index 0000000..0fc8b50
--- /dev/null
+++ b/kokoro/macos/python/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/python/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/python/presubmit.cfg b/kokoro/macos/python/presubmit.cfg
new file mode 100644
index 0000000..0fc8b50
--- /dev/null
+++ b/kokoro/macos/python/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/python/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/python_cpp/build.sh b/kokoro/macos/python_cpp/build.sh
new file mode 100755
index 0000000..cb53def
--- /dev/null
+++ b/kokoro/macos/python_cpp/build.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+g++ --version
+
+./tests.sh python_cpp
diff --git a/kokoro/macos/python_cpp/continuous.cfg b/kokoro/macos/python_cpp/continuous.cfg
new file mode 100644
index 0000000..22f4a0e
--- /dev/null
+++ b/kokoro/macos/python_cpp/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/python_cpp/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/python_cpp/presubmit.cfg b/kokoro/macos/python_cpp/presubmit.cfg
new file mode 100644
index 0000000..22f4a0e
--- /dev/null
+++ b/kokoro/macos/python_cpp/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/python_cpp/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/ruby21/build.sh b/kokoro/macos/ruby21/build.sh
new file mode 100755
index 0000000..748ea65
--- /dev/null
+++ b/kokoro/macos/ruby21/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh ruby21
diff --git a/kokoro/macos/ruby21/continuous.cfg b/kokoro/macos/ruby21/continuous.cfg
new file mode 100644
index 0000000..489796d
--- /dev/null
+++ b/kokoro/macos/ruby21/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby21/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/ruby21/presubmit.cfg b/kokoro/macos/ruby21/presubmit.cfg
new file mode 100644
index 0000000..489796d
--- /dev/null
+++ b/kokoro/macos/ruby21/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby21/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/ruby22/build.sh b/kokoro/macos/ruby22/build.sh
new file mode 100755
index 0000000..5c4de42
--- /dev/null
+++ b/kokoro/macos/ruby22/build.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Build file to set up and run tests
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+# Prepare worker environment to run tests
+source kokoro/macos/prepare_build_macos_rc
+
+./tests.sh ruby22
diff --git a/kokoro/macos/ruby22/continuous.cfg b/kokoro/macos/ruby22/continuous.cfg
new file mode 100644
index 0000000..d270544
--- /dev/null
+++ b/kokoro/macos/ruby22/continuous.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby22/build.sh"
+timeout_mins: 1440
diff --git a/kokoro/macos/ruby22/presubmit.cfg b/kokoro/macos/ruby22/presubmit.cfg
new file mode 100644
index 0000000..d270544
--- /dev/null
+++ b/kokoro/macos/ruby22/presubmit.cfg
@@ -0,0 +1,5 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby22/build.sh"
+timeout_mins: 1440
diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
index b61fcb6..d3288e2 100644
--- a/m4/ax_cxx_compile_stdcxx.m4
+++ b/m4/ax_cxx_compile_stdcxx.m4
@@ -180,6 +180,8 @@
 
 #else
 
+#include <utility>
+
 namespace cxx11
 {
 
@@ -445,6 +447,23 @@
 
   }
 
+  namespace test_std_move_and_forward
+  {
+    struct message {};
+    char foo(message&) { return '\0'; }
+    int foo(message&&) { return 0; }
+
+    template<typename Arg, typename RT>
+    void check(Arg&& arg, RT rt) {
+      static_assert(sizeof(rt) == sizeof(foo(std::forward<Arg>(arg))), "");
+    }
+    void test() {
+      message a;
+      check(a, char());
+      check(std::move(a), int());
+    }
+  }
+
 }  // namespace cxx11
 
 #endif  // __cplusplus >= 201103L
diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh
index c3cc8e6..9ac24bb 100755
--- a/objectivec/DevTools/full_mac_build.sh
+++ b/objectivec/DevTools/full_mac_build.sh
@@ -276,9 +276,7 @@
     8.3* )
       XCODEBUILD_TEST_BASE_IOS+=(
           -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
-          -destination "platform=iOS Simulator,name=iPhone 7,OS=10.3" # 64bit
-          -destination "platform=iOS Simulator,name=iPad 2,OS=8.1" # 32bit
-          -destination "platform=iOS Simulator,name=iPad Pro (9.7 inch),OS=10.3" # 64bit
+          -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
       )
       ;;
     * )
diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py
index 9a11fec..0b5b7b4 100755
--- a/objectivec/DevTools/pddm.py
+++ b/objectivec/DevTools/pddm.py
@@ -124,6 +124,7 @@
   return re.compile(r'\b(?P<macro_ref>(?P<name>(%s))\((?P<args>.*?)\))' %
                     '|'.join(macro_names))
 
+
 def _MacroArgRefRe(macro_arg_names):
   # Takes in a list of macro arg names and makes a regex that will match
   # uses of those args.
@@ -318,25 +319,26 @@
       return macro.body
     assert len(arg_values) == len(macro.args)
     args = dict(zip(macro.args, arg_values))
+
     def _lookupArg(match):
       val = args[match.group('name')]
       opt = match.group('option')
       if opt:
-        if opt == 'S': # Spaces for the length
+        if opt == 'S':  # Spaces for the length
           return ' ' * len(val)
-        elif opt == 'l': # Lowercase first character
+        elif opt == 'l':  # Lowercase first character
           if val:
             return val[0].lower() + val[1:]
           else:
             return val
-        elif opt == 'L': # All Lowercase
+        elif opt == 'L':  # All Lowercase
           return val.lower()
-        elif opt == 'u': # Uppercase first character
+        elif opt == 'u':  # Uppercase first character
           if val:
             return val[0].upper() + val[1:]
           else:
             return val
-        elif opt == 'U': # All Uppercase
+        elif opt == 'U':  # All Uppercase
           return val.upper()
         else:
           raise PDDMError('Unknown arg option "%s$%s" while expanding "%s".%s'
@@ -350,6 +352,7 @@
 
   def _EvalMacrosRefs(self, text, macro_stack):
     macro_ref_re = _MacroRefRe(self._macros.keys())
+
     def _resolveMacro(match):
       return self._Expand(match, macro_stack)
     return macro_ref_re.sub(_resolveMacro, text)
@@ -496,9 +499,10 @@
       # Add the ending marker.
       if len(captured_lines) == 1:
         result.append('//%%PDDM-EXPAND-END %s' %
-                       captured_lines[0][directive_len:].strip())
+                      captured_lines[0][directive_len:].strip())
       else:
-        result.append('//%%PDDM-EXPAND-END (%s expansions)' % len(captured_lines))
+        result.append('//%%PDDM-EXPAND-END (%s expansions)' %
+                      len(captured_lines))
 
       return result
 
@@ -669,15 +673,15 @@
 
     if src_file.processed_content != src_file.original_content:
       if not opts.dry_run:
-        print 'Updating for "%s".' % a_path
+        print('Updating for "%s".' % a_path)
         with open(a_path, 'w') as f:
           f.write(src_file.processed_content)
       else:
         # Special result to indicate things need updating.
-        print 'Update needed for "%s".' % a_path
+        print('Update needed for "%s".' % a_path)
         result = 1
     elif opts.verbose:
-      print 'No update for "%s".' % a_path
+      print('No update for "%s".' % a_path)
 
   return result
 
diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m
index eef0535..22859e7 100644
--- a/objectivec/GPBCodedInputStream.m
+++ b/objectivec/GPBCodedInputStream.m
@@ -230,16 +230,16 @@
   }
 
   state->lastTag = ReadRawVarint32(state);
-  if (state->lastTag == 0) {
-    // If we actually read zero, that's not a valid tag.
-    RaiseException(GPBCodedInputStreamErrorInvalidTag,
-                   @"A zero tag on the wire is invalid.");
-  }
-  // Tags have to include a valid wireformat, check that also.
+  // Tags have to include a valid wireformat.
   if (!GPBWireFormatIsValidTag(state->lastTag)) {
     RaiseException(GPBCodedInputStreamErrorInvalidTag,
                    @"Invalid wireformat in tag.");
   }
+  // Zero is not a valid field number.
+  if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) {
+    RaiseException(GPBCodedInputStreamErrorInvalidTag,
+                   @"A zero field number on the wire is invalid.");
+  }
   return state->lastTag;
 }
 
diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h
index d6fff3d..23c404b 100644
--- a/objectivec/GPBCodedOutputStream.h
+++ b/objectivec/GPBCodedOutputStream.h
@@ -47,11 +47,20 @@
 NS_ASSUME_NONNULL_BEGIN
 
 /**
+ * @c GPBCodedOutputStream exception names.
+ **/
+extern NSString *const GPBCodedOutputStreamException_OutOfSpace;
+extern NSString *const GPBCodedOutputStreamException_WriteFailed;
+
+/**
  * Writes out protocol message fields.
  *
  * The common uses of protocol buffers shouldn't need to use this class.
  * GPBMessage's provide a -data method that will serialize the message for you.
  *
+ * @note Any -write* api can raise the GPBCodedOutputStreamException_*
+ *       exceptions.
+ *
  * @note Subclassing of GPBCodedOutputStream is NOT supported.
  **/
 @interface GPBCodedOutputStream : NSObject
diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m
index 7c3ab44..c299040 100644
--- a/objectivec/GPBCodedOutputStream.m
+++ b/objectivec/GPBCodedOutputStream.m
@@ -36,6 +36,11 @@
 #import "GPBUnknownFieldSet_PackagePrivate.h"
 #import "GPBUtilities_PackagePrivate.h"
 
+// These values are the existing values so as not to break any code that might
+// have already been inspecting them when they weren't documented/exposed.
+NSString *const GPBCodedOutputStreamException_OutOfSpace = @"OutOfSpace";
+NSString *const GPBCodedOutputStreamException_WriteFailed = @"WriteFailed";
+
 // Structure for containing state of a GPBCodedInputStream. Brought out into
 // a struct so that we can inline several common functions instead of dealing
 // with overhead of ObjC dispatch.
@@ -59,13 +64,13 @@
 static void GPBRefreshBuffer(GPBOutputBufferState *state) {
   if (state->output == nil) {
     // We're writing to a single buffer.
-    [NSException raise:@"OutOfSpace" format:@""];
+    [NSException raise:GPBCodedOutputStreamException_OutOfSpace format:@""];
   }
   if (state->position != 0) {
     NSInteger written =
         [state->output write:state->bytes maxLength:state->position];
     if (written != (NSInteger)state->position) {
-      [NSException raise:@"WriteFailed" format:@""];
+      [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""];
     }
     state->position = 0;
   }
diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h
index 9173e7a..452b3f8 100644
--- a/objectivec/GPBDescriptor_PackagePrivate.h
+++ b/objectivec/GPBDescriptor_PackagePrivate.h
@@ -286,10 +286,6 @@
 // would be the wire type for packed.
 uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
 
-GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) {
-  return syntax != GPBFileSyntaxProto3;
-}
-
 GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) {
   return syntax == GPBFileSyntaxProto3;
 }
diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m
index 1c67c68..7713376 100644
--- a/objectivec/GPBDictionary.m
+++ b/objectivec/GPBDictionary.m
@@ -329,13 +329,15 @@
 
 size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
   GPBDataType mapValueType = GPBGetFieldDataType(field);
-  __block size_t result = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSString *key;
+  NSEnumerator *keys = [dict keyEnumerator];
+  while ((key = [keys nextObject])) {
+    id obj = dict[key];
     size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key);
     msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * dict.count;
   return result;
@@ -347,8 +349,10 @@
   NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
   GPBDataType mapValueType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
-    #pragma unused(stop)
+  NSString *key;
+  NSEnumerator *keys = [dict keyEnumerator];
+  while ((key = [keys nextObject])) {
+    id obj = dict[key];
     // Write the tag.
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
@@ -359,14 +363,16 @@
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     [outputStream writeString:kMapKeyFieldNumber value:key];
     WriteDictObjectField(outputStream, obj, kMapValueFieldNumber, mapValueType);
-  }];
+  }
 }
 
 BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
   NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
   NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type");
   #pragma unused(field)  // For when asserts are off in release.
-  for (GPBMessage *msg in [dict objectEnumerator]) {
+  GPBMessage *msg;
+  NSEnumerator *objects = [dict objectEnumerator];
+  while ((msg = [objects nextObject])) {
     if (!msg.initialized) {
       return NO;
     }
@@ -406,7 +412,7 @@
       valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_);
       break;
     case GPBDataTypeInt64:
-      valueToFill->valueInt64 = GPBCodedInputStreamReadInt32(&stream->state_);
+      valueToFill->valueInt64 = GPBCodedInputStreamReadInt64(&stream->state_);
       break;
     case GPBDataTypeSInt32:
       valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_);
@@ -796,15 +802,20 @@
 //%- (void)enumerateKeysAndEnumsUsingBlock:
 //%    (void (^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block {
 //%  GPBEnumValidationFunc func = _validationFunc;
-//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
-//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
-//%                                                   BOOL *stop) {
+//%  BOOL stop = NO;
+//%  NSEnumerator *keys = [_dictionary keyEnumerator];
+//%  ENUM_TYPE##KHELPER(KEY_TYPE)##aKey;
+//%  while ((aKey = [keys nextObject])) {
+//%    ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue = _dictionary[aKey];
 //%      VALUE_TYPE unwrapped = UNWRAP##VALUE_NAME(aValue);
 //%      if (!func(unwrapped)) {
 //%        unwrapped = kGPBUnrecognizedEnumeratorValue;
 //%      }
-//%      block(UNWRAP##KEY_NAME(aKey), unwrapped, stop);
-//%  }];
+//%    block(UNWRAP##KEY_NAME(aKey), unwrapped, &stop);
+//%    if (stop) {
+//%      break;
+//%    }
+//%  }
 //%}
 //%
 //%DICTIONARY_MUTABLE_CORE2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Value, Enum, value, Raw)
@@ -863,30 +874,37 @@
 //%
 //%- (void)enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock:
 //%    (void (^)(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop))block {
-//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
-//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u,
-//%                                                   BOOL *stop) {
-//%      block(UNWRAP##KEY_NAME(aKey), UNWRAP##VALUE_NAME(a##VNAME_VAR$u), stop);
-//%  }];
+//%  BOOL stop = NO;
+//%  NSDictionary *internal = _dictionary;
+//%  NSEnumerator *keys = [internal keyEnumerator];
+//%  ENUM_TYPE##KHELPER(KEY_TYPE)##aKey;
+//%  while ((aKey = [keys nextObject])) {
+//%    ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey];
+//%    block(UNWRAP##KEY_NAME(aKey), UNWRAP##VALUE_NAME(a##VNAME_VAR$u), &stop);
+//%    if (stop) {
+//%      break;
+//%    }
+//%  }
 //%}
 //%
 //%EXTRA_METHODS_##VHELPER(KEY_NAME, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-//%  NSUInteger count = _dictionary.count;
+//%  NSDictionary *internal = _dictionary;
+//%  NSUInteger count = internal.count;
 //%  if (count == 0) {
 //%    return 0;
 //%  }
 //%
 //%  GPBDataType valueDataType = GPBGetFieldDataType(field);
 //%  GPBDataType keyDataType = field.mapKeyDataType;
-//%  __block size_t result = 0;
-//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
-//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u##,
-//%                                                   BOOL *stop) {
-//%    #pragma unused(stop)
+//%  size_t result = 0;
+//%  NSEnumerator *keys = [internal keyEnumerator];
+//%  ENUM_TYPE##KHELPER(KEY_TYPE)##aKey;
+//%  while ((aKey = [keys nextObject])) {
+//%    ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey];
 //%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
 //%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(a##VNAME_VAR$u), kMapValueFieldNumber, valueDataType);
 //%    result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-//%  }];
+//%  }
 //%  size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
 //%  result += tagSize * count;
 //%  return result;
@@ -897,20 +915,22 @@
 //%  GPBDataType valueDataType = GPBGetFieldDataType(field);
 //%  GPBDataType keyDataType = field.mapKeyDataType;
 //%  uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
-//%                                                   ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u,
-//%                                                   BOOL *stop) {
-//%    #pragma unused(stop)
-//%    // Write the tag.
+//%  NSDictionary *internal = _dictionary;
+//%  NSEnumerator *keys = [internal keyEnumerator];
+//%  ENUM_TYPE##KHELPER(KEY_TYPE)##aKey;
+//%  while ((aKey = [keys nextObject])) {
+//%    ENUM_TYPE##VHELPER(VALUE_TYPE)##a##VNAME_VAR$u = internal[aKey];
 //%    [outputStream writeInt32NoTag:tag];
 //%    // Write the size of the message.
-//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
-//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(a##VNAME_VAR$u), kMapValueFieldNumber, valueDataType);
+//%    KEY_TYPE KisP##unwrappedKey = UNWRAP##KEY_NAME(aKey);
+//%    VALUE_TYPE unwrappedValue = UNWRAP##VALUE_NAME(a##VNAME_VAR$u);
+//%    size_t msgSize = ComputeDict##KEY_NAME##FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+//%    msgSize += ComputeDict##VALUE_NAME##FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
 //%    [outputStream writeInt32NoTag:(int32_t)msgSize];
 //%    // Write the fields.
-//%    WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType);
-//%    WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(a##VNAME_VAR$u), kMapValueFieldNumber, valueDataType);
-//%  }];
+//%    WriteDict##KEY_NAME##Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+//%    WriteDict##VALUE_NAME##Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+//%  }
 //%}
 //%
 //%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -1366,14 +1386,15 @@
 //%- (instancetype)deepCopyWithZone:(NSZone *)zone {
 //%  GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict =
 //%      [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
-//%  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
-//%                                                   GPBMessage *msg,
-//%                                                   BOOL *stop) {
-//%    #pragma unused(stop)
+//%  NSEnumerator *keys = [_dictionary keyEnumerator];
+//%  id aKey;
+//%  NSMutableDictionary *internalDict = newDict->_dictionary;
+//%  while ((aKey = [keys nextObject])) {
+//%    GPBMessage *msg = _dictionary[aKey];
 //%    GPBMessage *copiedMsg = [msg copyWithZone:zone];
-//%    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+//%    [internalDict setObject:copiedMsg forKey:aKey];
 //%    [copiedMsg release];
-//%  }];
+//%  }
 //%  return newDict;
 //%}
 //%
@@ -1632,30 +1653,37 @@
 
 - (void)enumerateKeysAndUInt32sUsingBlock:
     (void (^)(uint32_t key, uint32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue unsignedIntValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue unsignedIntValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -1666,20 +1694,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    uint32_t unwrappedValue = [aValue unsignedIntValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -1839,30 +1869,37 @@
 
 - (void)enumerateKeysAndInt32sUsingBlock:
     (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -1873,20 +1910,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -2046,30 +2085,37 @@
 
 - (void)enumerateKeysAndUInt64sUsingBlock:
     (void (^)(uint32_t key, uint64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue unsignedLongLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue unsignedLongLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -2080,20 +2126,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    uint64_t unwrappedValue = [aValue unsignedLongLongValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -2253,30 +2301,37 @@
 
 - (void)enumerateKeysAndInt64sUsingBlock:
     (void (^)(uint32_t key, int64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue longLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue longLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -2287,20 +2342,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    int64_t unwrappedValue = [aValue longLongValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -2460,30 +2517,37 @@
 
 - (void)enumerateKeysAndBoolsUsingBlock:
     (void (^)(uint32_t key, BOOL value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue boolValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue boolValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -2494,20 +2558,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    BOOL unwrappedValue = [aValue boolValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -2667,30 +2733,37 @@
 
 - (void)enumerateKeysAndFloatsUsingBlock:
     (void (^)(uint32_t key, float value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue floatValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue floatValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -2701,20 +2774,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    float unwrappedValue = [aValue floatValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -2874,30 +2949,37 @@
 
 - (void)enumerateKeysAndDoublesUsingBlock:
     (void (^)(uint32_t key, double value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue doubleValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue doubleValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -2908,20 +2990,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    double unwrappedValue = [aValue doubleValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -3109,30 +3193,37 @@
 
 - (void)enumerateKeysAndRawValuesUsingBlock:
     (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedIntValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -3143,20 +3234,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
@@ -3206,15 +3299,20 @@
 - (void)enumerateKeysAndEnumsUsingBlock:
     (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
   GPBEnumValidationFunc func = _validationFunc;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
+  BOOL stop = NO;
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = _dictionary[aKey];
       int32_t unwrapped = [aValue intValue];
       if (!func(unwrapped)) {
         unwrapped = kGPBUnrecognizedEnumeratorValue;
       }
-      block([aKey unsignedIntValue], unwrapped, stop);
-  }];
+    block([aKey unsignedIntValue], unwrapped, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary {
@@ -3371,11 +3469,17 @@
 
 - (void)enumerateKeysAndObjectsUsingBlock:
     (void (^)(uint32_t key, id object, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-      block([aKey unsignedIntValue], aObject, stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
+    block([aKey unsignedIntValue], aObject, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (BOOL)isInitialized {
@@ -3390,34 +3494,36 @@
 - (instancetype)deepCopyWithZone:(NSZone *)zone {
   GPBUInt32ObjectDictionary *newDict =
       [[GPBUInt32ObjectDictionary alloc] init];
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
-                                                   GPBMessage *msg,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  id aKey;
+  NSMutableDictionary *internalDict = newDict->_dictionary;
+  while ((aKey = [keys nextObject])) {
+    GPBMessage *msg = _dictionary[aKey];
     GPBMessage *copiedMsg = [msg copyWithZone:zone];
-    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [internalDict setObject:copiedMsg forKey:aKey];
     [copiedMsg release];
-  }];
+  }
   return newDict;
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -3428,20 +3534,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    uint32_t unwrappedKey = [aKey unsignedIntValue];
+    id unwrappedValue = aObject;
+    size_t msgSize = ComputeDictUInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -3605,30 +3713,37 @@
 
 - (void)enumerateKeysAndUInt32sUsingBlock:
     (void (^)(int32_t key, uint32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue unsignedIntValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue unsignedIntValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -3639,20 +3754,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    uint32_t unwrappedValue = [aValue unsignedIntValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -3812,30 +3929,37 @@
 
 - (void)enumerateKeysAndInt32sUsingBlock:
     (void (^)(int32_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -3846,20 +3970,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -4019,30 +4145,37 @@
 
 - (void)enumerateKeysAndUInt64sUsingBlock:
     (void (^)(int32_t key, uint64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue unsignedLongLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue unsignedLongLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -4053,20 +4186,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    uint64_t unwrappedValue = [aValue unsignedLongLongValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -4226,30 +4361,37 @@
 
 - (void)enumerateKeysAndInt64sUsingBlock:
     (void (^)(int32_t key, int64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue longLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue longLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -4260,20 +4402,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    int64_t unwrappedValue = [aValue longLongValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -4433,30 +4577,37 @@
 
 - (void)enumerateKeysAndBoolsUsingBlock:
     (void (^)(int32_t key, BOOL value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue boolValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue boolValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -4467,20 +4618,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    BOOL unwrappedValue = [aValue boolValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -4640,30 +4793,37 @@
 
 - (void)enumerateKeysAndFloatsUsingBlock:
     (void (^)(int32_t key, float value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue floatValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue floatValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -4674,20 +4834,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    float unwrappedValue = [aValue floatValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -4847,30 +5009,37 @@
 
 - (void)enumerateKeysAndDoublesUsingBlock:
     (void (^)(int32_t key, double value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue doubleValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue doubleValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -4881,20 +5050,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    double unwrappedValue = [aValue doubleValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -5082,30 +5253,37 @@
 
 - (void)enumerateKeysAndRawValuesUsingBlock:
     (void (^)(int32_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey intValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey intValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -5116,20 +5294,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
@@ -5179,15 +5359,20 @@
 - (void)enumerateKeysAndEnumsUsingBlock:
     (void (^)(int32_t key, int32_t value, BOOL *stop))block {
   GPBEnumValidationFunc func = _validationFunc;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
+  BOOL stop = NO;
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = _dictionary[aKey];
       int32_t unwrapped = [aValue intValue];
       if (!func(unwrapped)) {
         unwrapped = kGPBUnrecognizedEnumeratorValue;
       }
-      block([aKey intValue], unwrapped, stop);
-  }];
+    block([aKey intValue], unwrapped, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary {
@@ -5344,11 +5529,17 @@
 
 - (void)enumerateKeysAndObjectsUsingBlock:
     (void (^)(int32_t key, id object, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-      block([aKey intValue], aObject, stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
+    block([aKey intValue], aObject, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (BOOL)isInitialized {
@@ -5363,34 +5554,36 @@
 - (instancetype)deepCopyWithZone:(NSZone *)zone {
   GPBInt32ObjectDictionary *newDict =
       [[GPBInt32ObjectDictionary alloc] init];
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
-                                                   GPBMessage *msg,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  id aKey;
+  NSMutableDictionary *internalDict = newDict->_dictionary;
+  while ((aKey = [keys nextObject])) {
+    GPBMessage *msg = _dictionary[aKey];
     GPBMessage *copiedMsg = [msg copyWithZone:zone];
-    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [internalDict setObject:copiedMsg forKey:aKey];
     [copiedMsg release];
-  }];
+  }
   return newDict;
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -5401,20 +5594,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    int32_t unwrappedKey = [aKey intValue];
+    id unwrappedValue = aObject;
+    size_t msgSize = ComputeDictInt32FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt32Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -5578,30 +5773,37 @@
 
 - (void)enumerateKeysAndUInt32sUsingBlock:
     (void (^)(uint64_t key, uint32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue unsignedIntValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue unsignedIntValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -5612,20 +5814,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    uint32_t unwrappedValue = [aValue unsignedIntValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -5785,30 +5989,37 @@
 
 - (void)enumerateKeysAndInt32sUsingBlock:
     (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -5819,20 +6030,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -5992,30 +6205,37 @@
 
 - (void)enumerateKeysAndUInt64sUsingBlock:
     (void (^)(uint64_t key, uint64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue unsignedLongLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue unsignedLongLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -6026,20 +6246,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    uint64_t unwrappedValue = [aValue unsignedLongLongValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -6199,30 +6421,37 @@
 
 - (void)enumerateKeysAndInt64sUsingBlock:
     (void (^)(uint64_t key, int64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue longLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue longLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -6233,20 +6462,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    int64_t unwrappedValue = [aValue longLongValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -6406,30 +6637,37 @@
 
 - (void)enumerateKeysAndBoolsUsingBlock:
     (void (^)(uint64_t key, BOOL value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue boolValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue boolValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -6440,20 +6678,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    BOOL unwrappedValue = [aValue boolValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -6613,30 +6853,37 @@
 
 - (void)enumerateKeysAndFloatsUsingBlock:
     (void (^)(uint64_t key, float value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue floatValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue floatValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -6647,20 +6894,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    float unwrappedValue = [aValue floatValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -6820,30 +7069,37 @@
 
 - (void)enumerateKeysAndDoublesUsingBlock:
     (void (^)(uint64_t key, double value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue doubleValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue doubleValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -6854,20 +7110,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    double unwrappedValue = [aValue doubleValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -7055,30 +7313,37 @@
 
 - (void)enumerateKeysAndRawValuesUsingBlock:
     (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey unsignedLongLongValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -7089,20 +7354,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
@@ -7152,15 +7419,20 @@
 - (void)enumerateKeysAndEnumsUsingBlock:
     (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
   GPBEnumValidationFunc func = _validationFunc;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
+  BOOL stop = NO;
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = _dictionary[aKey];
       int32_t unwrapped = [aValue intValue];
       if (!func(unwrapped)) {
         unwrapped = kGPBUnrecognizedEnumeratorValue;
       }
-      block([aKey unsignedLongLongValue], unwrapped, stop);
-  }];
+    block([aKey unsignedLongLongValue], unwrapped, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary {
@@ -7317,11 +7589,17 @@
 
 - (void)enumerateKeysAndObjectsUsingBlock:
     (void (^)(uint64_t key, id object, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-      block([aKey unsignedLongLongValue], aObject, stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
+    block([aKey unsignedLongLongValue], aObject, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (BOOL)isInitialized {
@@ -7336,34 +7614,36 @@
 - (instancetype)deepCopyWithZone:(NSZone *)zone {
   GPBUInt64ObjectDictionary *newDict =
       [[GPBUInt64ObjectDictionary alloc] init];
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
-                                                   GPBMessage *msg,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  id aKey;
+  NSMutableDictionary *internalDict = newDict->_dictionary;
+  while ((aKey = [keys nextObject])) {
+    GPBMessage *msg = _dictionary[aKey];
     GPBMessage *copiedMsg = [msg copyWithZone:zone];
-    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [internalDict setObject:copiedMsg forKey:aKey];
     [copiedMsg release];
-  }];
+  }
   return newDict;
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -7374,20 +7654,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    uint64_t unwrappedKey = [aKey unsignedLongLongValue];
+    id unwrappedValue = aObject;
+    size_t msgSize = ComputeDictUInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictUInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -7551,30 +7833,37 @@
 
 - (void)enumerateKeysAndUInt32sUsingBlock:
     (void (^)(int64_t key, uint32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue unsignedIntValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue unsignedIntValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -7585,20 +7874,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    uint32_t unwrappedValue = [aValue unsignedIntValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -7758,30 +8049,37 @@
 
 - (void)enumerateKeysAndInt32sUsingBlock:
     (void (^)(int64_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -7792,20 +8090,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -7965,30 +8265,37 @@
 
 - (void)enumerateKeysAndUInt64sUsingBlock:
     (void (^)(int64_t key, uint64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue unsignedLongLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue unsignedLongLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -7999,20 +8306,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    uint64_t unwrappedValue = [aValue unsignedLongLongValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -8172,30 +8481,37 @@
 
 - (void)enumerateKeysAndInt64sUsingBlock:
     (void (^)(int64_t key, int64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue longLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue longLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -8206,20 +8522,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    int64_t unwrappedValue = [aValue longLongValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -8379,30 +8697,37 @@
 
 - (void)enumerateKeysAndBoolsUsingBlock:
     (void (^)(int64_t key, BOOL value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue boolValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue boolValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -8413,20 +8738,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    BOOL unwrappedValue = [aValue boolValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -8586,30 +8913,37 @@
 
 - (void)enumerateKeysAndFloatsUsingBlock:
     (void (^)(int64_t key, float value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue floatValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue floatValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -8620,20 +8954,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    float unwrappedValue = [aValue floatValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -8793,30 +9129,37 @@
 
 - (void)enumerateKeysAndDoublesUsingBlock:
     (void (^)(int64_t key, double value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue doubleValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue doubleValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -8827,20 +9170,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    double unwrappedValue = [aValue doubleValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -9028,30 +9373,37 @@
 
 - (void)enumerateKeysAndRawValuesUsingBlock:
     (void (^)(int64_t key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block([aKey longLongValue], [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -9062,20 +9414,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
@@ -9125,15 +9479,20 @@
 - (void)enumerateKeysAndEnumsUsingBlock:
     (void (^)(int64_t key, int32_t value, BOOL *stop))block {
   GPBEnumValidationFunc func = _validationFunc;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
+  BOOL stop = NO;
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = _dictionary[aKey];
       int32_t unwrapped = [aValue intValue];
       if (!func(unwrapped)) {
         unwrapped = kGPBUnrecognizedEnumeratorValue;
       }
-      block([aKey longLongValue], unwrapped, stop);
-  }];
+    block([aKey longLongValue], unwrapped, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary {
@@ -9290,11 +9649,17 @@
 
 - (void)enumerateKeysAndObjectsUsingBlock:
     (void (^)(int64_t key, id object, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-      block([aKey longLongValue], aObject, stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
+    block([aKey longLongValue], aObject, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (BOOL)isInitialized {
@@ -9309,34 +9674,36 @@
 - (instancetype)deepCopyWithZone:(NSZone *)zone {
   GPBInt64ObjectDictionary *newDict =
       [[GPBInt64ObjectDictionary alloc] init];
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
-                                                   GPBMessage *msg,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  id aKey;
+  NSMutableDictionary *internalDict = newDict->_dictionary;
+  while ((aKey = [keys nextObject])) {
+    GPBMessage *msg = _dictionary[aKey];
     GPBMessage *copiedMsg = [msg copyWithZone:zone];
-    [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+    [internalDict setObject:copiedMsg forKey:aKey];
     [copiedMsg release];
-  }];
+  }
   return newDict;
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -9347,20 +9714,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
-                                                   id aObject,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSNumber *aKey;
+  while ((aKey = [keys nextObject])) {
+    id aObject = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictObjectFieldSize(aObject, kMapValueFieldNumber, valueDataType);
+    int64_t unwrappedKey = [aKey longLongValue];
+    id unwrappedValue = aObject;
+    size_t msgSize = ComputeDictInt64FieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictObjectFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType);
-    WriteDictObjectField(outputStream, aObject, kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictInt64Field(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictObjectField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -9528,30 +9897,37 @@
 
 - (void)enumerateKeysAndUInt32sUsingBlock:
     (void (^)(NSString *key, uint32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue unsignedIntValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue unsignedIntValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -9562,20 +9938,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    uint32_t unwrappedValue = [aValue unsignedIntValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -9743,30 +10121,37 @@
 
 - (void)enumerateKeysAndInt32sUsingBlock:
     (void (^)(NSString *key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -9777,20 +10162,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt32FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt32Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -9958,30 +10345,37 @@
 
 - (void)enumerateKeysAndUInt64sUsingBlock:
     (void (^)(NSString *key, uint64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue unsignedLongLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue unsignedLongLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -9992,20 +10386,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    uint64_t unwrappedValue = [aValue unsignedLongLongValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictUInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictUInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -10173,30 +10569,37 @@
 
 - (void)enumerateKeysAndInt64sUsingBlock:
     (void (^)(NSString *key, int64_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue longLongValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue longLongValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -10207,20 +10610,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    int64_t unwrappedValue = [aValue longLongValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictInt64FieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictInt64Field(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -10388,30 +10793,37 @@
 
 - (void)enumerateKeysAndBoolsUsingBlock:
     (void (^)(NSString *key, BOOL value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue boolValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue boolValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -10422,20 +10834,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    BOOL unwrappedValue = [aValue boolValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictBoolFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictBoolField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -10603,30 +11017,37 @@
 
 - (void)enumerateKeysAndFloatsUsingBlock:
     (void (^)(NSString *key, float value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue floatValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue floatValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -10637,20 +11058,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    float unwrappedValue = [aValue floatValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictFloatFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictFloatField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -10818,30 +11241,37 @@
 
 - (void)enumerateKeysAndDoublesUsingBlock:
     (void (^)(NSString *key, double value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue doubleValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue doubleValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -10852,20 +11282,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    double unwrappedValue = [aValue doubleValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictDoubleFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictDoubleField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (void)setGPBGenericValue:(GPBGenericValue *)value
@@ -11061,30 +11493,37 @@
 
 - (void)enumerateKeysAndRawValuesUsingBlock:
     (void (^)(NSString *key, int32_t value, BOOL *stop))block {
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-      block(aKey, [aValue intValue], stop);
-  }];
+  BOOL stop = NO;
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
+    block(aKey, [aValue intValue], &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
-  NSUInteger count = _dictionary.count;
+  NSDictionary *internal = _dictionary;
+  NSUInteger count = internal.count;
   if (count == 0) {
     return 0;
   }
 
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
-  __block size_t result = 0;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
+  size_t result = 0;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
     msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
     result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
-  }];
+  }
   size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage);
   result += tagSize * count;
   return result;
@@ -11095,20 +11534,22 @@
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   GPBDataType keyDataType = field.mapKeyDataType;
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
-    #pragma unused(stop)
-    // Write the tag.
+  NSDictionary *internal = _dictionary;
+  NSEnumerator *keys = [internal keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = internal[aKey];
     [outputStream writeInt32NoTag:tag];
     // Write the size of the message.
-    size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType);
-    msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType);
+    NSString *unwrappedKey = aKey;
+    int32_t unwrappedValue = [aValue intValue];
+    size_t msgSize = ComputeDictStringFieldSize(unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    msgSize += ComputeDictEnumFieldSize(unwrappedValue, kMapValueFieldNumber, valueDataType);
     [outputStream writeInt32NoTag:(int32_t)msgSize];
     // Write the fields.
-    WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType);
-    WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType);
-  }];
+    WriteDictStringField(outputStream, unwrappedKey, kMapKeyFieldNumber, keyDataType);
+    WriteDictEnumField(outputStream, unwrappedValue, kMapValueFieldNumber, valueDataType);
+  }
 }
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
@@ -11158,15 +11599,20 @@
 - (void)enumerateKeysAndEnumsUsingBlock:
     (void (^)(NSString *key, int32_t value, BOOL *stop))block {
   GPBEnumValidationFunc func = _validationFunc;
-  [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
-                                                   NSNumber *aValue,
-                                                   BOOL *stop) {
+  BOOL stop = NO;
+  NSEnumerator *keys = [_dictionary keyEnumerator];
+  NSString *aKey;
+  while ((aKey = [keys nextObject])) {
+    NSNumber *aValue = _dictionary[aKey];
       int32_t unwrapped = [aValue intValue];
       if (!func(unwrapped)) {
         unwrapped = kGPBUnrecognizedEnumeratorValue;
       }
-      block(aKey, unwrapped, stop);
-  }];
+    block(aKey, unwrapped, &stop);
+    if (stop) {
+      break;
+    }
+  }
 }
 
 - (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary {
diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h
index 2c325ba..276740d 100644
--- a/objectivec/GPBMessage.h
+++ b/objectivec/GPBMessage.h
@@ -292,6 +292,9 @@
  * Writes out the message to the given coded output stream.
  *
  * @param output The coded output stream into which to write the message.
+ *
+ * @note This can raise the GPBCodedOutputStreamException_* exceptions.
+ *
  **/
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output;
 
@@ -299,6 +302,8 @@
  * Writes out the message to the given output stream.
  *
  * @param output The output stream into which to write the message.
+ *
+ * @note This can raise the GPBCodedOutputStreamException_* exceptions.
  **/
 - (void)writeToOutputStream:(NSOutputStream *)output;
 
@@ -307,6 +312,8 @@
  * the given output stream.
  *
  * @param output The coded output stream into which to write the message.
+ *
+ * @note This can raise the GPBCodedOutputStreamException_* exceptions.
  **/
 - (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output;
 
@@ -315,6 +322,8 @@
  * the given output stream.
  *
  * @param output The output stream into which to write the message.
+ *
+ * @note This can raise the GPBCodedOutputStreamException_* exceptions.
  **/
 - (void)writeDelimitedToOutputStream:(NSOutputStream *)output;
 
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index 627a396..37cff6c 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -2372,17 +2372,11 @@
         // zero signals EOF / limit reached
         return;
       } else {
-        if (GPBPreserveUnknownFields(syntax)) {
-          if (![self parseUnknownField:input
-                     extensionRegistry:extensionRegistry
-                                   tag:tag]) {
-            // it's an endgroup tag
-            return;
-          }
-        } else {
-          if (![input skipField:tag]) {
-            return;
-          }
+        if (![self parseUnknownField:input
+                   extensionRegistry:extensionRegistry
+                                 tag:tag]) {
+          // it's an endgroup tag
+          return;
         }
       }
     }  // if(!merged)
@@ -3083,7 +3077,7 @@
 + (BOOL)resolveInstanceMethod:(SEL)sel {
   const GPBDescriptor *descriptor = [self descriptor];
   if (!descriptor) {
-    return NO;
+    return [super resolveInstanceMethod:sel];
   }
 
   // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given
diff --git a/objectivec/GPBUnknownField.h b/objectivec/GPBUnknownField.h
index a135cc2..5b96023 100644
--- a/objectivec/GPBUnknownField.h
+++ b/objectivec/GPBUnknownField.h
@@ -42,6 +42,9 @@
  **/
 @interface GPBUnknownField : NSObject<NSCopying>
 
+/** Initialize a field with the given number. */
+- (instancetype)initWithNumber:(int32_t)number;
+
 /** The field number the data is stored under. */
 @property(nonatomic, readonly, assign) int32_t number;
 
diff --git a/objectivec/GPBUnknownField_PackagePrivate.h b/objectivec/GPBUnknownField_PackagePrivate.h
index 1fbce0f..2b4c789 100644
--- a/objectivec/GPBUnknownField_PackagePrivate.h
+++ b/objectivec/GPBUnknownField_PackagePrivate.h
@@ -36,8 +36,6 @@
 
 @interface GPBUnknownField ()
 
-- (instancetype)initWithNumber:(int32_t)number;
-
 - (void)writeToOutput:(GPBCodedOutputStream *)output;
 - (size_t)serializedSize;
 
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
index 3c861fe..4a4c544 100644
--- a/objectivec/Tests/GPBMessageTests+Serialization.m
+++ b/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -113,35 +113,6 @@
   [msg release];
 }
 
-- (void)testProto3DroppingUnknownFields {
-  DropUnknownsFooWithExtraFields *fooWithExtras =
-      [[DropUnknownsFooWithExtraFields alloc] init];
-
-  fooWithExtras.int32Value = 1;
-  fooWithExtras.enumValue = DropUnknownsFooWithExtraFields_NestedEnum_Baz;
-  fooWithExtras.extraInt32Value = 2;
-
-  NSData *data = [fooWithExtras data];
-  XCTAssertNotNil(data);
-  DropUnknownsFoo *foo = [DropUnknownsFoo parseFromData:data error:NULL];
-
-  XCTAssertEqual(foo.int32Value, 1);
-  XCTAssertEqual(foo.enumValue, DropUnknownsFoo_NestedEnum_Baz);
-  // Nothing should end up in the unknowns.
-  XCTAssertEqual([foo.unknownFields countOfFields], 0U);
-
-  [fooWithExtras release];
-  data = [foo data];
-  fooWithExtras =
-      [DropUnknownsFooWithExtraFields parseFromData:data error:NULL];
-  XCTAssertEqual(fooWithExtras.int32Value, 1);
-  XCTAssertEqual(fooWithExtras.enumValue,
-                 DropUnknownsFooWithExtraFields_NestedEnum_Baz);
-  // And the extra value is gone (back to the default).
-  XCTAssertEqual(fooWithExtras.extraInt32Value, 0);
-  XCTAssertEqual([foo.unknownFields countOfFields], 0U);
-}
-
 - (void)testProto2UnknownEnumToUnknownField {
   Message3 *orig = [[Message3 alloc] init];
 
@@ -946,6 +917,41 @@
   XCTAssertEqual(error.code, GPBCodedInputStreamErrorInvalidTag);
 }
 
+- (void)testZeroFieldNum {
+  // These are ConformanceTestSuite::TestIllegalTags.
+
+  const char *tests[] = {
+    "\1DEADBEEF",
+    "\2\1\1",
+    "\3\4",
+    "\5DEAD"
+  };
+
+  for (size_t i = 0; i < GPBARRAYSIZE(tests); ++i) {
+    NSData *data = DataFromCStr(tests[i]);
+
+    {
+      // Message from proto2 syntax file
+      NSError *error = nil;
+      Message2 *msg = [Message2 parseFromData:data error:&error];
+      XCTAssertNil(msg, @"i = %zd", i);
+      XCTAssertNotNil(error, @"i = %zd", i);
+      XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain, @"i = %zd", i);
+      XCTAssertEqual(error.code, GPBCodedInputStreamErrorInvalidTag, @"i = %zd", i);
+    }
+
+    {
+      // Message from proto3 syntax file
+      NSError *error = nil;
+      Message3 *msg = [Message3 parseFromData:data error:&error];
+      XCTAssertNil(msg, @"i = %zd", i);
+      XCTAssertNotNil(error, @"i = %zd", i);
+      XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain, @"i = %zd", i);
+      XCTAssertEqual(error.code, GPBCodedInputStreamErrorInvalidTag, @"i = %zd", i);
+    }
+  }
+}
+
 - (void)testErrorRecursionDepthReached {
   NSData *data = DataFromCStr(
       "\x0A\xF2\x01\x0A\xEF\x01\x0A\xEC\x01\x0A\xE9\x01\x0A\xE6\x01"
@@ -1149,22 +1155,27 @@
   [msg.mapInt32Int32 setInt32:101 forKey:2001];
   [msg.mapInt64Int64 setInt64:1002 forKey:202];
   [msg.mapInt64Int64 setInt64:103 forKey:2003];
+  [msg.mapInt64Int64 setInt64:4294967296 forKey:4294967297];
   [msg.mapUint32Uint32 setUInt32:1004 forKey:204];
   [msg.mapUint32Uint32 setUInt32:105 forKey:2005];
   [msg.mapUint64Uint64 setUInt64:1006 forKey:206];
   [msg.mapUint64Uint64 setUInt64:107 forKey:2007];
+  [msg.mapUint64Uint64 setUInt64:4294967298 forKey:4294967299];
   [msg.mapSint32Sint32 setInt32:1008 forKey:208];
   [msg.mapSint32Sint32 setInt32:109 forKey:2009];
   [msg.mapSint64Sint64 setInt64:1010 forKey:210];
   [msg.mapSint64Sint64 setInt64:111 forKey:2011];
+  [msg.mapSint64Sint64 setInt64:4294967300 forKey:4294967301];
   [msg.mapFixed32Fixed32 setUInt32:1012 forKey:212];
   [msg.mapFixed32Fixed32 setUInt32:113 forKey:2013];
   [msg.mapFixed64Fixed64 setUInt64:1014 forKey:214];
   [msg.mapFixed64Fixed64 setUInt64:115 forKey:2015];
+  [msg.mapFixed64Fixed64 setUInt64:4294967302 forKey:4294967303];
   [msg.mapSfixed32Sfixed32 setInt32:1016 forKey:216];
   [msg.mapSfixed32Sfixed32 setInt32:117 forKey:2017];
   [msg.mapSfixed64Sfixed64 setInt64:1018 forKey:218];
   [msg.mapSfixed64Sfixed64 setInt64:119 forKey:2019];
+  [msg.mapSfixed64Sfixed64 setInt64:4294967304 forKey:4294967305];
   [msg.mapInt32Float setFloat:1020.f forKey:220];
   [msg.mapInt32Float setFloat:121.f forKey:2021];
   [msg.mapInt32Double setDouble:1022. forKey:222];
diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h
index d236e4b..b17e76f 100644
--- a/objectivec/google/protobuf/Any.pbobjc.h
+++ b/objectivec/google/protobuf/Any.pbobjc.h
@@ -87,6 +87,16 @@
  *       any.Unpack(foo)
  *       ...
  *
+ *  Example 4: Pack and unpack a message in Go
+ *
+ *      foo := &pb.Foo{...}
+ *      any, err := ptypes.MarshalAny(foo)
+ *      ...
+ *      foo := &pb.Foo{}
+ *      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+ *        ...
+ *      }
+ *
  * The pack methods provided by protobuf library will by default use
  * 'type.googleapis.com/full.type.name' as the type URL and the unpack
  * methods only use the fully qualified type name after the last '/'
diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h
index 742a812..095fc2c 100644
--- a/objectivec/google/protobuf/Api.pbobjc.h
+++ b/objectivec/google/protobuf/Api.pbobjc.h
@@ -63,34 +63,41 @@
 };
 
 /**
- * Api is a light-weight descriptor for a protocol buffer service.
+ * Api is a light-weight descriptor for an API Interface.
+ *
+ * Interfaces are also described as "protocol buffer services" in some contexts,
+ * such as by the "service" keyword in a .proto file, but they are different
+ * from API Services, which represent a concrete implementation of an interface
+ * as opposed to simply a description of methods and bindings. They are also
+ * sometimes simply referred to as "APIs" in other contexts, such as the name of
+ * this message itself. See https://cloud.google.com/apis/design/glossary for
+ * detailed terminology.
  **/
 @interface GPBApi : GPBMessage
 
 /**
- * The fully qualified name of this api, including package name
- * followed by the api's simple name.
+ * The fully qualified name of this interface, including package name
+ * followed by the interface's simple name.
  **/
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
-/** The methods of this api, in unspecified order. */
+/** The methods of this interface, in unspecified order. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMethod*> *methodsArray;
 /** The number of items in @c methodsArray without causing the array to be created. */
 @property(nonatomic, readonly) NSUInteger methodsArray_Count;
 
-/** Any metadata attached to the API. */
+/** Any metadata attached to the interface. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
 /** The number of items in @c optionsArray without causing the array to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 /**
- * A version string for this api. If specified, must have the form
- * `major-version.minor-version`, as in `1.10`. If the minor version
- * is omitted, it defaults to zero. If the entire version field is
- * empty, the major version is derived from the package name, as
- * outlined below. If the field is not empty, the version in the
- * package name will be verified to be consistent with what is
- * provided here.
+ * A version string for this interface. If specified, must have the form
+ * `major-version.minor-version`, as in `1.10`. If the minor version is
+ * omitted, it defaults to zero. If the entire version field is empty, the
+ * major version is derived from the package name, as outlined below. If the
+ * field is not empty, the version in the package name will be verified to be
+ * consistent with what is provided here.
  *
  * The versioning schema uses [semantic
  * versioning](http://semver.org) where the major version number
@@ -100,10 +107,10 @@
  * chosen based on the product plan.
  *
  * The major version is also reflected in the package name of the
- * API, which must end in `v<major-version>`, as in
+ * interface, which must end in `v<major-version>`, as in
  * `google.feature.v1`. For major versions 0 and 1, the suffix can
  * be omitted. Zero major versions must only be used for
- * experimental, none-GA apis.
+ * experimental, non-GA interfaces.
  **/
 @property(nonatomic, readwrite, copy, null_resettable) NSString *version;
 
@@ -115,7 +122,7 @@
 /** Test to see if @c sourceContext has been set. */
 @property(nonatomic, readwrite) BOOL hasSourceContext;
 
-/** Included APIs. See [Mixin][]. */
+/** Included interfaces. See [Mixin][]. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMixin*> *mixinsArray;
 /** The number of items in @c mixinsArray without causing the array to be created. */
 @property(nonatomic, readonly) NSUInteger mixinsArray_Count;
@@ -150,7 +157,7 @@
 };
 
 /**
- * Method represents a method of an api.
+ * Method represents a method of an API interface.
  **/
 @interface GPBMethod : GPBMessage
 
@@ -199,9 +206,9 @@
 };
 
 /**
- * Declares an API to be included in this API. The including API must
- * redeclare all the methods from the included API, but documentation
- * and options are inherited as follows:
+ * Declares an API Interface to be included in this interface. The including
+ * interface must redeclare all the methods from the included interface, but
+ * documentation and options are inherited as follows:
  *
  * - If after comment and whitespace stripping, the documentation
  *   string of the redeclared method is empty, it will be inherited
@@ -213,7 +220,8 @@
  *
  * - If an http annotation is inherited, the path pattern will be
  *   modified as follows. Any version prefix will be replaced by the
- *   version of the including API plus the [root][] path if specified.
+ *   version of the including interface plus the [root][] path if
+ *   specified.
  *
  * Example of a simple mixin:
  *
@@ -279,7 +287,7 @@
  **/
 @interface GPBMixin : GPBMessage
 
-/** The fully qualified name of the API which is included. */
+/** The fully qualified name of the interface which is included. */
 @property(nonatomic, readwrite, copy, null_resettable) NSString *name;
 
 /**
diff --git a/php/composer.json b/php/composer.json
index 32b0f44..34e0447 100644
--- a/php/composer.json
+++ b/php/composer.json
@@ -13,16 +13,9 @@
   },
   "autoload": {
     "psr-4": {
-      "Foo\\": "tests/generated/Foo",
-      "Bar\\": "tests/generated/Bar",
-      "Google\\Protobuf\\": "tests/generated/Google/Protobuf",
-      "Google\\Protobuf\\Internal\\": "src/Google/Protobuf/Internal",
-      "GPBMetadata\\": "tests/generated/GPBMetadata",
-      "GPBMetadata\\Google\\Protobuf\\Internal\\": "src/GPBMetadata/Google/Protobuf/Internal",
+      "Google\\Protobuf\\": "src/Google/Protobuf",
+      "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf",
       "": "tests/generated"
-    },
-    "files": [
-      "src/Google/Protobuf/descriptor.php"
-    ]
+    }
   }
 }
diff --git a/php/ext/google/protobuf/array.c b/php/ext/google/protobuf/array.c
index e9f5f15..e69bef4 100644
--- a/php/ext/google/protobuf/array.c
+++ b/php/ext/google/protobuf/array.c
@@ -142,12 +142,7 @@
   efree(ptr);
 }
 static inline void php_proto_array_object_release(zval *value) {
-  void* ptr = Z_PTR_P(value);
-  zend_object* object = *(zend_object**)ptr;
-  if(--GC_REFCOUNT(object) == 0) {
-    zend_objects_store_del(object);
-  }
-  efree(ptr);
+  zval_ptr_dtor(value);
 }
 static void php_proto_array_default_release(zval* value) {
   void* ptr = Z_PTR_P(value);
@@ -210,7 +205,11 @@
     }
   }
 
-  php_proto_zend_hash_index_update(ht, index, memory, size, NULL);
+  if (intern->type == UPB_TYPE_MESSAGE) {
+    php_proto_zend_hash_index_update_zval(ht, index, *(zval**)memory);
+  } else {
+    php_proto_zend_hash_index_update_mem(ht, index, memory, size, NULL);
+  }
 }
 
 #if PHP_MAJOR_VERSION < 7
@@ -233,9 +232,18 @@
   HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
   void *value;
 
-  if (php_proto_zend_hash_index_find(ht, index, (void **)&value) == FAILURE) {
-    zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
-    return NULL;
+  if (intern->type == UPB_TYPE_MESSAGE) {
+    if (php_proto_zend_hash_index_find_zval(ht, index, (void **)&value) ==
+        FAILURE) {
+      zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+      return NULL;
+    }
+  } else {
+    if (php_proto_zend_hash_index_find_mem(ht, index, (void **)&value) ==
+        FAILURE) {
+      zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+      return NULL;
+    }
   }
 
   return value;
@@ -244,7 +252,11 @@
 void repeated_field_push_native(RepeatedField *intern, void *value) {
   HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
   int size = native_slot_size(intern->type);
-  php_proto_zend_hash_next_index_insert(ht, (void **)value, size, NULL);
+  if (intern->type == UPB_TYPE_MESSAGE) {
+    php_proto_zend_hash_next_index_insert_zval(ht, value);
+  } else {
+    php_proto_zend_hash_next_index_insert_mem(ht, (void **)value, size, NULL);
+  }
 }
 
 void repeated_field_create_with_field(
@@ -367,11 +379,19 @@
   RepeatedField *intern = UNBOX(RepeatedField, getThis());
   HashTable *table = PHP_PROTO_HASH_OF(intern->array);
 
-  if (php_proto_zend_hash_index_find(table, index, (void **)&memory) == FAILURE) {
-    zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
-    return;
+  if (intern->type == UPB_TYPE_MESSAGE) {
+    if (php_proto_zend_hash_index_find_zval(table, index, (void **)&memory) ==
+        FAILURE) {
+      zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
+      return;
+    }
+  } else {
+    if (php_proto_zend_hash_index_find_mem(table, index, (void **)&memory) ==
+        FAILURE) {
+      zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
+      return;
+    }
   }
-
   native_slot_get_by_array(intern->type, memory,
                            ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
 }
@@ -491,10 +511,18 @@
 
   HashTable *table = PHP_PROTO_HASH_OF(repeated_field->array);
 
-  if (php_proto_zend_hash_index_find(table, intern->position, (void **)&memory) ==
-      FAILURE) {
-    zend_error(E_USER_ERROR, "Element at %ld doesn't exist.\n", index);
-    return;
+  if (repeated_field->type == UPB_TYPE_MESSAGE) {
+    if (php_proto_zend_hash_index_find_zval(table, intern->position,
+                                            (void **)&memory) == FAILURE) {
+      zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+      return;
+    }
+  } else {
+    if (php_proto_zend_hash_index_find_mem(table, intern->position,
+                                           (void **)&memory) == FAILURE) {
+      zend_error(E_USER_ERROR, "Element at %d doesn't exist.\n", index);
+      return;
+    }
   }
   native_slot_get_by_array(repeated_field->type, memory,
                            ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c
index 099ebd0..421b84e 100644
--- a/php/ext/google/protobuf/def.c
+++ b/php/ext/google/protobuf/def.c
@@ -37,12 +37,27 @@
 static void descriptor_init_c_instance(Descriptor* intern TSRMLS_DC);
 static void descriptor_free_c(Descriptor* object TSRMLS_DC);
 
+static void field_descriptor_init_c_instance(FieldDescriptor* intern TSRMLS_DC);
+static void field_descriptor_free_c(FieldDescriptor* object TSRMLS_DC);
+
 static void enum_descriptor_init_c_instance(EnumDescriptor* intern TSRMLS_DC);
 static void enum_descriptor_free_c(EnumDescriptor* object TSRMLS_DC);
 
+static void enum_value_descriptor_init_c_instance(
+    EnumValueDescriptor *intern TSRMLS_DC);
+static void enum_value_descriptor_free_c(EnumValueDescriptor *object TSRMLS_DC);
+
 static void descriptor_pool_free_c(DescriptorPool* object TSRMLS_DC);
 static void descriptor_pool_init_c_instance(DescriptorPool* pool TSRMLS_DC);
 
+static void internal_descriptor_pool_free_c(
+    InternalDescriptorPool *object TSRMLS_DC);
+static void internal_descriptor_pool_init_c_instance(
+    InternalDescriptorPool *pool TSRMLS_DC);
+
+static void oneof_descriptor_free_c(Oneof* object TSRMLS_DC);
+static void oneof_descriptor_init_c_instance(Oneof* pool TSRMLS_DC);
+
 // -----------------------------------------------------------------------------
 // Common Utilities
 // -----------------------------------------------------------------------------
@@ -100,33 +115,6 @@
     check_upb_status(&status, msg);      \
   } while (0)
 
-// Define PHP class
-#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
-  PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME)       \
-  PHP_PROTO_INIT_CLASS_END
-
-#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME)  \
-  PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
-  LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
-  PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
-
-#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME)  \
-  PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
-  LOWERNAME##_free_c(intern TSRMLS_CC);             \
-  PHP_PROTO_OBJECT_FREE_END
-
-#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME)  \
-  PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \
-  PHP_PROTO_OBJECT_DTOR_END
-
-#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
-  zend_class_entry *LOWERNAME##_type;              \
-  zend_object_handlers *LOWERNAME##_handlers;      \
-  DEFINE_PROTOBUF_FREE(NAME, LOWERNAME)            \
-  DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME)            \
-  DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME)          \
-  DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
-
 // -----------------------------------------------------------------------------
 // GPBType
 // -----------------------------------------------------------------------------
@@ -169,10 +157,16 @@
 // -----------------------------------------------------------------------------
 
 static zend_function_entry descriptor_methods[] = {
+  PHP_ME(Descriptor, getClass, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getFullName, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getField, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getFieldCount, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getOneofDecl, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Descriptor, getOneofDeclCount, NULL, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
-DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Internal\\Descriptor");
+DEFINE_CLASS(Descriptor, descriptor, "Google\\Protobuf\\Descriptor");
 
 static void descriptor_free_c(Descriptor *self TSRMLS_DC) {
   if (self->layout) {
@@ -203,7 +197,6 @@
 }
 
 static void descriptor_init_c_instance(Descriptor *desc TSRMLS_DC) {
-  // zend_object_std_init(&desc->std, descriptor_type TSRMLS_CC);
   desc->msgdef = NULL;
   desc->layout = NULL;
   desc->klass = NULL;
@@ -215,30 +208,217 @@
   desc->json_serialize_handlers_preserve = NULL;
 }
 
+PHP_METHOD(Descriptor, getClass) {
+  Descriptor *intern = UNBOX(Descriptor, getThis());
+#if PHP_MAJOR_VERSION < 7
+  const char* classname = intern->klass->name;
+#else
+  const char* classname = ZSTR_VAL(intern->klass->name);
+#endif
+  PHP_PROTO_RETVAL_STRINGL(classname, strlen(classname), 1);
+}
+
+PHP_METHOD(Descriptor, getFullName) {
+  Descriptor *intern = UNBOX(Descriptor, getThis());
+  const char* fullname = upb_msgdef_fullname(intern->msgdef);
+  PHP_PROTO_RETVAL_STRINGL(fullname, strlen(fullname), 1);
+}
+
+PHP_METHOD(Descriptor, getField) {
+  long index;
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+      FAILURE) {
+    zend_error(E_USER_ERROR, "Expect integer for index.\n");
+    return;
+  }
+
+  Descriptor *intern = UNBOX(Descriptor, getThis());
+  int field_num = upb_msgdef_numfields(intern->msgdef);
+  if (index < 0 || index >= field_num) {
+    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+    return;
+  }
+
+  upb_msg_field_iter iter;
+  int i;
+  for(upb_msg_field_begin(&iter, intern->msgdef), i = 0;
+      !upb_msg_field_done(&iter) && i < index;
+      upb_msg_field_next(&iter), i++);
+  const upb_fielddef *field = upb_msg_iter_field(&iter);
+
+  PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field);
+  if (field_hashtable_value == NULL) {
+#if PHP_MAJOR_VERSION < 7
+    MAKE_STD_ZVAL(field_hashtable_value);
+    ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
+                                        field_descriptor_type TSRMLS_CC));
+#else
+    field_hashtable_value =
+        field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
+#endif
+    FieldDescriptor *field_php =
+        UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
+    field_php->fielddef = field;
+    add_def_obj(field, field_hashtable_value);
+  }
+
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(field_hashtable_value, 1, 0);
+#else
+  ++GC_REFCOUNT(field_hashtable_value);
+  RETURN_OBJ(field_hashtable_value);
+#endif
+}
+
+PHP_METHOD(Descriptor, getFieldCount) {
+  Descriptor *intern = UNBOX(Descriptor, getThis());
+  RETURN_LONG(upb_msgdef_numfields(intern->msgdef));
+}
+
+PHP_METHOD(Descriptor, getOneofDecl) {
+  long index;
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+      FAILURE) {
+    zend_error(E_USER_ERROR, "Expect integer for index.\n");
+    return;
+  }
+
+  Descriptor *intern = UNBOX(Descriptor, getThis());
+  int field_num = upb_msgdef_numoneofs(intern->msgdef);
+  if (index < 0 || index >= field_num) {
+    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+    return;
+  }
+
+  upb_msg_oneof_iter iter;
+  int i;
+  for(upb_msg_oneof_begin(&iter, intern->msgdef), i = 0;
+      !upb_msg_oneof_done(&iter) && i < index;
+      upb_msg_oneof_next(&iter), i++);
+  upb_oneofdef *oneof = upb_msg_iter_oneof(&iter);
+
+  ZVAL_OBJ(return_value, oneof_descriptor_type->create_object(
+                             oneof_descriptor_type TSRMLS_CC));
+  Oneof *oneof_php = UNBOX(Oneof, return_value);
+  oneof_php->oneofdef = oneof;
+}
+
+PHP_METHOD(Descriptor, getOneofDeclCount) {
+  Descriptor *intern = UNBOX(Descriptor, getThis());
+  RETURN_LONG(upb_msgdef_numoneofs(intern->msgdef));
+}
+
 // -----------------------------------------------------------------------------
 // EnumDescriptor
 // -----------------------------------------------------------------------------
 
 static zend_function_entry enum_descriptor_methods[] = {
+  PHP_ME(EnumDescriptor, getValue, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(EnumDescriptor, getValueCount, NULL, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
 DEFINE_CLASS(EnumDescriptor, enum_descriptor,
-             "Google\\Protobuf\\Internal\\EnumDescriptor");
+             "Google\\Protobuf\\EnumDescriptor");
 
 static void enum_descriptor_free_c(EnumDescriptor *self TSRMLS_DC) {
 }
 
 static void enum_descriptor_init_c_instance(EnumDescriptor *self TSRMLS_DC) {
-  // zend_object_std_init(&self->std, enum_descriptor_type TSRMLS_CC);
   self->enumdef = NULL;
   self->klass = NULL;
 }
 
+PHP_METHOD(EnumDescriptor, getValue) {
+  long index;
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+      FAILURE) {
+    zend_error(E_USER_ERROR, "Expect integer for index.\n");
+    return;
+  }
+
+  EnumDescriptor *intern = UNBOX(EnumDescriptor, getThis());
+  int field_num = upb_enumdef_numvals(intern->enumdef);
+  if (index < 0 || index >= field_num) {
+    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+    return;
+  }
+
+  upb_enum_iter iter;
+  int i;
+  for(upb_enum_begin(&iter, intern->enumdef), i = 0;
+      !upb_enum_done(&iter) && i < index;
+      upb_enum_next(&iter), i++);
+
+  ZVAL_OBJ(return_value, enum_value_descriptor_type->create_object(
+                             enum_value_descriptor_type TSRMLS_CC));
+  EnumValueDescriptor *enum_value_php =
+      UNBOX(EnumValueDescriptor, return_value);
+  enum_value_php->name = upb_enum_iter_name(&iter);
+  enum_value_php->number = upb_enum_iter_number(&iter);
+}
+
+PHP_METHOD(EnumDescriptor, getValueCount) {
+  EnumDescriptor *intern = UNBOX(EnumDescriptor, getThis());
+  RETURN_LONG(upb_enumdef_numvals(intern->enumdef));
+}
+
+// -----------------------------------------------------------------------------
+// EnumValueDescriptor
+// -----------------------------------------------------------------------------
+
+static zend_function_entry enum_value_descriptor_methods[] = {
+  PHP_ME(EnumValueDescriptor, getName, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(EnumValueDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+DEFINE_CLASS(EnumValueDescriptor, enum_value_descriptor,
+             "Google\\Protobuf\\EnumValueDescriptor");
+
+static void enum_value_descriptor_free_c(EnumValueDescriptor *self TSRMLS_DC) {
+}
+
+static void enum_value_descriptor_init_c_instance(EnumValueDescriptor *self TSRMLS_DC) {
+  self->name = NULL;
+  self->number = 0;
+}
+
+PHP_METHOD(EnumValueDescriptor, getName) {
+  EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis());
+  PHP_PROTO_RETVAL_STRINGL(intern->name, strlen(intern->name), 1);
+}
+
+PHP_METHOD(EnumValueDescriptor, getNumber) {
+  EnumValueDescriptor *intern = UNBOX(EnumValueDescriptor, getThis());
+  RETURN_LONG(intern->number);
+}
+
 // -----------------------------------------------------------------------------
 // FieldDescriptor
 // -----------------------------------------------------------------------------
 
+static zend_function_entry field_descriptor_methods[] = {
+  PHP_ME(FieldDescriptor, getName,   NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getNumber, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getLabel,  NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getType,   NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, isMap,     NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getEnumType, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(FieldDescriptor, getMessageType, NULL, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+DEFINE_CLASS(FieldDescriptor, field_descriptor,
+             "Google\\Protobuf\\FieldDescriptor");
+
+static void field_descriptor_free_c(FieldDescriptor *self TSRMLS_DC) {
+}
+
+static void field_descriptor_init_c_instance(FieldDescriptor *self TSRMLS_DC) {
+  self->fielddef = NULL;
+}
+
 upb_fieldtype_t to_fieldtype(upb_descriptortype_t type) {
   switch (type) {
 #define CASE(descriptor_type, type)           \
@@ -272,6 +452,150 @@
   return 0;
 }
 
+PHP_METHOD(FieldDescriptor, getName) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  const char* name = upb_fielddef_name(intern->fielddef);
+  PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1);
+}
+
+PHP_METHOD(FieldDescriptor, getNumber) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  RETURN_LONG(upb_fielddef_number(intern->fielddef));
+}
+
+PHP_METHOD(FieldDescriptor, getLabel) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  RETURN_LONG(upb_fielddef_label(intern->fielddef));
+}
+
+PHP_METHOD(FieldDescriptor, getType) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  RETURN_LONG(upb_fielddef_descriptortype(intern->fielddef));
+}
+
+PHP_METHOD(FieldDescriptor, isMap) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  RETURN_BOOL(upb_fielddef_ismap(intern->fielddef));
+}
+
+PHP_METHOD(FieldDescriptor, getEnumType) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  const upb_enumdef *enumdef = upb_fielddef_enumsubdef(intern->fielddef);
+  if (enumdef == NULL) {
+    char error_msg[100];
+    sprintf(error_msg, "Cannot get enum type for non-enum field '%s'",
+            upb_fielddef_name(intern->fielddef));
+    zend_throw_exception(NULL, error_msg, 0 TSRMLS_CC);
+    return;
+  }
+  PHP_PROTO_HASHTABLE_VALUE desc = get_def_obj(enumdef);
+
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(desc, 1, 0);
+#else
+  ++GC_REFCOUNT(desc);
+  RETURN_OBJ(desc);
+#endif
+}
+
+PHP_METHOD(FieldDescriptor, getMessageType) {
+  FieldDescriptor *intern = UNBOX(FieldDescriptor, getThis());
+  const upb_msgdef *msgdef = upb_fielddef_msgsubdef(intern->fielddef);
+  if (msgdef == NULL) {
+    char error_msg[100];
+    sprintf(error_msg, "Cannot get message type for non-message field '%s'",
+            upb_fielddef_name(intern->fielddef));
+    zend_throw_exception(NULL, error_msg, 0 TSRMLS_CC);
+    return;
+  }
+  PHP_PROTO_HASHTABLE_VALUE desc = get_def_obj(msgdef);
+
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(desc, 1, 0);
+#else
+  ++GC_REFCOUNT(desc);
+  RETURN_OBJ(desc);
+#endif
+}
+
+// -----------------------------------------------------------------------------
+// Oneof
+// -----------------------------------------------------------------------------
+
+static zend_function_entry oneof_descriptor_methods[] = {
+  PHP_ME(Oneof, getName,  NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Oneof, getField, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Oneof, getFieldCount, NULL, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+DEFINE_CLASS(Oneof, oneof_descriptor,
+             "Google\\Protobuf\\OneofDescriptor");
+
+static void oneof_descriptor_free_c(Oneof *self TSRMLS_DC) {
+}
+
+static void oneof_descriptor_init_c_instance(Oneof *self TSRMLS_DC) {
+  self->oneofdef = NULL;
+}
+
+PHP_METHOD(Oneof, getName) {
+  Oneof *intern = UNBOX(Oneof, getThis());
+  const char *name = upb_oneofdef_name(intern->oneofdef);
+  PHP_PROTO_RETVAL_STRINGL(name, strlen(name), 1);
+}
+
+PHP_METHOD(Oneof, getField) {
+  long index;
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) ==
+      FAILURE) {
+    zend_error(E_USER_ERROR, "Expect integer for index.\n");
+    return;
+  }
+
+  Oneof *intern = UNBOX(Oneof, getThis());
+  int field_num = upb_oneofdef_numfields(intern->oneofdef);
+  if (index < 0 || index >= field_num) {
+    zend_error(E_USER_ERROR, "Cannot get element at %ld.\n", index);
+    return;
+  }
+
+  upb_oneof_iter iter;
+  int i;
+  for(upb_oneof_begin(&iter, intern->oneofdef), i = 0;
+      !upb_oneof_done(&iter) && i < index;
+      upb_oneof_next(&iter), i++);
+  const upb_fielddef *field = upb_oneof_iter_field(&iter);
+
+  PHP_PROTO_HASHTABLE_VALUE field_hashtable_value = get_def_obj(field);
+  if (field_hashtable_value == NULL) {
+#if PHP_MAJOR_VERSION < 7
+    MAKE_STD_ZVAL(field_hashtable_value);
+    ZVAL_OBJ(field_hashtable_value, field_descriptor_type->create_object(
+                                        field_descriptor_type TSRMLS_CC));
+#else
+    field_hashtable_value =
+        field_descriptor_type->create_object(field_descriptor_type TSRMLS_CC);
+#endif
+    FieldDescriptor *field_php =
+        UNBOX_HASHTABLE_VALUE(FieldDescriptor, field_hashtable_value);
+    field_php->fielddef = field;
+    add_def_obj(field, field_hashtable_value);
+  }
+
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(field_hashtable_value, 1, 0);
+#else
+  ++GC_REFCOUNT(field_hashtable_value);
+  RETURN_OBJ(field_hashtable_value);
+#endif
+}
+
+PHP_METHOD(Oneof, getFieldCount) {
+  Oneof *intern = UNBOX(Oneof, getThis());
+  RETURN_LONG(upb_oneofdef_numfields(intern->oneofdef));
+}
+
 // -----------------------------------------------------------------------------
 // DescriptorPool
 // -----------------------------------------------------------------------------
@@ -279,52 +603,79 @@
 static zend_function_entry descriptor_pool_methods[] = {
   PHP_ME(DescriptorPool, getGeneratedPool, NULL,
          ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
-  PHP_ME(DescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(DescriptorPool, getDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(DescriptorPool, getEnumDescriptorByClassName, NULL, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+static zend_function_entry internal_descriptor_pool_methods[] = {
+  PHP_ME(InternalDescriptorPool, getGeneratedPool, NULL,
+         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+  PHP_ME(InternalDescriptorPool, internalAddGeneratedFile, NULL, ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
 DEFINE_CLASS(DescriptorPool, descriptor_pool,
+             "Google\\Protobuf\\DescriptorPool");
+DEFINE_CLASS(InternalDescriptorPool, internal_descriptor_pool,
              "Google\\Protobuf\\Internal\\DescriptorPool");
 
 // wrapper of generated pool
 #if PHP_MAJOR_VERSION < 7
 zval* generated_pool_php;
+zval* internal_generated_pool_php;
 #else
 zend_object *generated_pool_php;
+zend_object *internal_generated_pool_php;
 #endif
-DescriptorPool *generated_pool;  // The actual generated pool
+InternalDescriptorPool *generated_pool;  // The actual generated pool
 
-static void init_generated_pool_once(TSRMLS_D) {
-  if (generated_pool_php == NULL) {
+void init_generated_pool_once(TSRMLS_D) {
+  if (generated_pool == NULL) {
 #if PHP_MAJOR_VERSION < 7
     MAKE_STD_ZVAL(generated_pool_php);
+    MAKE_STD_ZVAL(internal_generated_pool_php);
+    ZVAL_OBJ(internal_generated_pool_php,
+             internal_descriptor_pool_type->create_object(
+                 internal_descriptor_pool_type TSRMLS_CC));
+    generated_pool = UNBOX(InternalDescriptorPool, internal_generated_pool_php);
     ZVAL_OBJ(generated_pool_php, descriptor_pool_type->create_object(
                                      descriptor_pool_type TSRMLS_CC));
-    generated_pool = UNBOX(DescriptorPool, generated_pool_php);
 #else
+    internal_generated_pool_php = internal_descriptor_pool_type->create_object(
+        internal_descriptor_pool_type TSRMLS_CC);
+    generated_pool = (InternalDescriptorPool *)((char *)internal_generated_pool_php -
+                                        XtOffsetOf(InternalDescriptorPool, std));
     generated_pool_php =
         descriptor_pool_type->create_object(descriptor_pool_type TSRMLS_CC);
-    generated_pool = (DescriptorPool *)((char *)generated_pool_php -
-                                        XtOffsetOf(DescriptorPool, std));
 #endif
   }
 }
 
-static void descriptor_pool_init_c_instance(DescriptorPool *pool TSRMLS_DC) {
-  // zend_object_std_init(&pool->std, descriptor_pool_type TSRMLS_CC);
+static void internal_descriptor_pool_init_c_instance(
+    InternalDescriptorPool *pool TSRMLS_DC) {
   pool->symtab = upb_symtab_new();
 
   ALLOC_HASHTABLE(pool->pending_list);
   zend_hash_init(pool->pending_list, 1, NULL, ZVAL_PTR_DTOR, 0);
 }
 
-static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
+static void internal_descriptor_pool_free_c(
+    InternalDescriptorPool *pool TSRMLS_DC) {
   upb_symtab_free(pool->symtab);
 
   zend_hash_destroy(pool->pending_list);
   FREE_HASHTABLE(pool->pending_list);
 }
 
+static void descriptor_pool_init_c_instance(DescriptorPool *pool TSRMLS_DC) {
+  assert(generated_pool != NULL);
+  pool->intern = generated_pool;
+}
+
+static void descriptor_pool_free_c(DescriptorPool *pool TSRMLS_DC) {
+}
+
 static void validate_enumdef(const upb_enumdef *enumdef) {
   // Verify that an entry exists with integer value 0. (This is the default
   // value.)
@@ -358,6 +709,16 @@
 #endif
 }
 
+PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
+  init_generated_pool_once(TSRMLS_C);
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(internal_generated_pool_php, 1, 0);
+#else
+  ++GC_REFCOUNT(internal_generated_pool_php);
+  RETURN_OBJ(internal_generated_pool_php);
+#endif
+}
+
 static void classname_no_prefix(const char *fullname, const char *package_name,
                                 char *class_name) {
   size_t i = 0, j;
@@ -405,23 +766,34 @@
 }
 
 static void convert_to_class_name_inplace(const char *package,
+                                          const char *namespace_given,
                                           const char *prefix, char *classname) {
-  size_t package_len = package == NULL ? 0 : strlen(package);
   size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
   size_t classname_len = strlen(classname);
   int i = 0, j;
   bool first_char = true;
 
-  int offset = package_len != 0 ? 2 : 0;
+  size_t package_len = package == NULL ? 0 : strlen(package);
+  size_t namespace_given_len =
+      namespace_given == NULL ? 0 : strlen(namespace_given);
+  bool use_namespace_given = namespace_given != NULL;
+  size_t namespace_len =
+      use_namespace_given ? namespace_given_len : package_len;
+
+  int offset = namespace_len != 0 ? 2 : 0;
 
   for (j = 0; j < classname_len; j++) {
-    classname[package_len + prefix_len + classname_len + offset - 1 - j] =
+    classname[namespace_len + prefix_len + classname_len + offset - 1 - j] =
         classname[classname_len - j - 1];
   }
 
-  if (package_len != 0) {
+  if (namespace_len != 0) {
     classname[i++] = '\\';
-    for (j = 0; j < package_len; j++) {
+    for (j = 0; j < namespace_len; j++) {
+      if (use_namespace_given) {
+        classname[i++] = namespace_given[j];
+        continue;
+      }
       // php packages are divided by '\'.
       if (package[j] == '.') {
         classname[i++] = '\\';
@@ -444,18 +816,11 @@
   memcpy(classname + i, prefix, prefix_len);
 }
 
-PHP_METHOD(DescriptorPool, internalAddGeneratedFile) {
-  char *data = NULL;
-  PHP_PROTO_SIZE data_len;
+void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
+                                 InternalDescriptorPool *pool TSRMLS_DC) {
   upb_filedef **files;
   size_t i;
 
-  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
-      FAILURE) {
-    return;
-  }
-
-  DescriptorPool *pool = UNBOX(DescriptorPool, getThis());
   CHECK_UPB(files = upb_loaddescriptor(data, data_len, &pool, &status),
             "Parse binary descriptors to internal descriptors failed");
 
@@ -490,16 +855,20 @@
      * bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if    \
      * given message is google.protobuf.Empty.*/                               \
     const char *fullname = upb_##def_type_lower##_fullname(def_type_lower);    \
+    const char *php_namespace = upb_filedef_phpnamespace(files[0]);            \
     const char *prefix_given = upb_filedef_phpprefix(files[0]);                \
     size_t classname_len = strlen(fullname) + 5;                               \
     if (prefix_given != NULL) {                                                \
       classname_len += strlen(prefix_given);                                   \
     }                                                                          \
+    if (php_namespace != NULL) {                                               \
+      classname_len += strlen(php_namespace);                                  \
+    }                                                                          \
     char *classname = ecalloc(sizeof(char), classname_len);                    \
     const char *package = upb_filedef_package(files[0]);                       \
     classname_no_prefix(fullname, package, classname);                         \
     const char *prefix = classname_prefix(classname, prefix_given, package);   \
-    convert_to_class_name_inplace(package, prefix, classname);                 \
+    convert_to_class_name_inplace(package, php_namespace, prefix, classname);  \
     PHP_PROTO_CE_DECLARE pce;                                                  \
     if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) ==     \
         FAILURE) {                                                             \
@@ -510,6 +879,8 @@
       desc->klass = PHP_PROTO_CE_UNREF(pce);                                   \
     }                                                                          \
     add_ce_obj(desc->klass, desc_php);                                         \
+    add_proto_obj(upb_##def_type_lower##_fullname(desc->def_type_lower),       \
+                  desc_php);                                                   \
     efree(classname);                                                          \
     break;                                                                     \
   }
@@ -535,3 +906,92 @@
   upb_filedef_unref(files[0], &pool);
   upb_gfree(files);
 }
+
+PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile) {
+  char *data = NULL;
+  PHP_PROTO_SIZE data_len;
+  upb_filedef **files;
+  size_t i;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
+      FAILURE) {
+    return;
+  }
+
+  InternalDescriptorPool *pool = UNBOX(InternalDescriptorPool, getThis());
+  internal_add_generated_file(data, data_len, pool TSRMLS_CC);
+}
+
+PHP_METHOD(DescriptorPool, getDescriptorByClassName) {
+  DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis());
+  InternalDescriptorPool *pool = public_pool->intern;
+
+  char *classname = NULL;
+  PHP_PROTO_SIZE classname_len;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
+                            &classname_len) == FAILURE) {
+    return;
+  }
+
+  PHP_PROTO_CE_DECLARE pce;
+  if (php_proto_zend_lookup_class(classname, classname_len, &pce) ==
+      FAILURE) {
+    RETURN_NULL();
+  }
+
+  PHP_PROTO_HASHTABLE_VALUE desc = get_ce_obj(PHP_PROTO_CE_UNREF(pce));
+  if (desc == NULL) {
+    RETURN_NULL();
+  }
+
+  zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc);
+
+  if (!instanceof_function(instance_ce, descriptor_type TSRMLS_CC)) {
+    RETURN_NULL();
+  }
+
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(desc, 1, 0);
+#else
+  ++GC_REFCOUNT(desc);
+  RETURN_OBJ(desc);
+#endif
+}
+
+PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName) {
+  DescriptorPool *public_pool = UNBOX(DescriptorPool, getThis());
+  InternalDescriptorPool *pool = public_pool->intern;
+
+  char *classname = NULL;
+  PHP_PROTO_SIZE classname_len;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &classname,
+                            &classname_len) == FAILURE) {
+    return;
+  }
+
+  PHP_PROTO_CE_DECLARE pce;
+  if (php_proto_zend_lookup_class(classname, classname_len, &pce) ==
+      FAILURE) {
+    RETURN_NULL();
+  }
+
+  PHP_PROTO_HASHTABLE_VALUE desc = get_ce_obj(PHP_PROTO_CE_UNREF(pce));
+  if (desc == NULL) {
+    RETURN_NULL();
+  }
+
+  zend_class_entry* instance_ce = HASHTABLE_VALUE_CE(desc);
+
+  if (!instanceof_function(instance_ce, enum_descriptor_type TSRMLS_CC)) {
+    RETURN_NULL();
+  }
+
+#if PHP_MAJOR_VERSION < 7
+  RETURN_ZVAL(desc, 1, 0);
+#else
+  ++GC_REFCOUNT(desc);
+  RETURN_OBJ(desc);
+#endif
+}
diff --git a/php/ext/google/protobuf/encode_decode.c b/php/ext/google/protobuf/encode_decode.c
index 6e3c606..93a5e9c 100644
--- a/php/ext/google/protobuf/encode_decode.c
+++ b/php/ext/google/protobuf/encode_decode.c
@@ -164,18 +164,21 @@
   int property_ofs;        // properties table cache
   uint32_t oneof_case_num; // oneof-case number to place in oneof_case field
   const upb_msgdef *md;    // msgdef, for oneof submessage handler
+  const upb_msgdef *parent_md;  // msgdef, for parent submessage
 } oneof_handlerdata_t;
 
 static const void *newoneofhandlerdata(upb_handlers *h,
                                        uint32_t ofs,
                                        uint32_t case_ofs,
                                        int property_ofs,
+                                       const upb_msgdef *m,
                                        const upb_fielddef *f) {
   oneof_handlerdata_t* hd =
       (oneof_handlerdata_t*)malloc(sizeof(oneof_handlerdata_t));
   hd->ofs = ofs;
   hd->case_ofs = case_ofs;
   hd->property_ofs = property_ofs;
+  hd->parent_md = m;
   // We reuse the field tag number as a oneof union discriminant tag. Note that
   // we don't expose these numbers to the user, so the only requirement is that
   // we have some unique ID for each union case/possibility. The field tag
@@ -284,10 +287,19 @@
 #if PHP_MAJOR_VERSION < 7
 static void *empty_php_string(zval** value_ptr) {
   SEPARATE_ZVAL_IF_NOT_REF(value_ptr);
+  if (Z_TYPE_PP(value_ptr) == IS_STRING &&
+      !IS_INTERNED(Z_STRVAL_PP(value_ptr))) {
+    FREE(Z_STRVAL_PP(value_ptr));
+  }
+  ZVAL_EMPTY_STRING(*value_ptr);
   return (void*)(*value_ptr);
 }
 #else
 static void *empty_php_string(zval* value_ptr) {
+  if (Z_TYPE_P(value_ptr) == IS_STRING) {
+    zend_string_release(Z_STR_P(value_ptr));
+  }
+  ZVAL_EMPTY_STRING(value_ptr);
   return value_ptr;
 }
 #endif
@@ -342,7 +354,7 @@
 
   HashTable *ht = PHP_PROTO_HASH_OF(intern->array);
   int index = zend_hash_num_elements(ht) - 1;
-  php_proto_zend_hash_index_update(
+  php_proto_zend_hash_index_update_mem(
       ht, index, memory, sizeof(zend_string*), NULL);
 
   return len;
@@ -654,6 +666,44 @@
 
 #undef DEFINE_ONEOF_HANDLER
 
+static void oneof_cleanup(MessageHeader* msg,
+                          const oneof_handlerdata_t* oneofdata) {
+  uint32_t old_case_num =
+      DEREF(message_data(msg), oneofdata->case_ofs, uint32_t);
+  if (old_case_num == 0) {
+    return;
+  }
+
+  const upb_fielddef* old_field =
+      upb_msgdef_itof(oneofdata->parent_md, old_case_num);
+  bool need_clean = false;
+
+  switch (upb_fielddef_type(old_field)) {
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES:
+      need_clean = true;
+      break;
+    case UPB_TYPE_MESSAGE:
+      if (oneofdata->oneof_case_num != old_case_num) {
+        need_clean = true;
+      }
+      break;
+    default:
+      break;
+  }
+
+  if (need_clean) {
+#if PHP_MAJOR_VERSION < 7
+    SEPARATE_ZVAL_IF_NOT_REF(
+        DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
+    php_proto_zval_ptr_dtor(
+        *DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
+    MAKE_STD_ZVAL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
+    ZVAL_NULL(*DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*));
+#endif
+  }
+}
+
 // Handlers for string/bytes in a oneof.
 static void *oneofbytes_handler(void *closure,
                                 const void *hd,
@@ -661,10 +711,12 @@
   MessageHeader* msg = closure;
   const oneof_handlerdata_t *oneofdata = hd;
 
+  oneof_cleanup(msg, oneofdata);
+
   DEREF(message_data(msg), oneofdata->case_ofs, uint32_t) =
       oneofdata->oneof_case_num;
   DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
-      &(msg->std.properties_table)[oneofdata->property_ofs];
+      OBJ_PROP(&msg->std, oneofdata->property_ofs);
 
    return empty_php_string(DEREF(
        message_data(msg), oneofdata->ofs, CACHED_VALUE*));
@@ -691,22 +743,11 @@
   MessageHeader* submsg;
 
   if (oldcase != oneofdata->oneof_case_num) {
-    // Ideally, we should clean up the old data. However, we don't even know the
-    // type of the old data. So, we will defer the desctruction of the old data
-    // to the time that containing message's destroyed or the same oneof field
-    // is accessed again and find that the old data hasn't been cleaned.
-    DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
-        &(msg->std.properties_table)[oneofdata->property_ofs];
-
-    // Old data was't cleaned when the oneof was accessed from another field.
-    if (Z_TYPE_P(CACHED_PTR_TO_ZVAL_PTR(DEREF(
-        message_data(msg), oneofdata->ofs, CACHED_VALUE*))) != IS_NULL) {
-          php_proto_zval_ptr_dtor(
-              CACHED_PTR_TO_ZVAL_PTR(
-                  DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)));
-    }
+    oneof_cleanup(msg, oneofdata);
 
     // Create new message.
+    DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*) =
+        OBJ_PROP(&msg->std, oneofdata->property_ofs);
     ZVAL_OBJ(CACHED_PTR_TO_ZVAL_PTR(
         DEREF(message_data(msg), oneofdata->ofs, CACHED_VALUE*)),
         subklass->create_object(subklass TSRMLS_CC));
@@ -856,6 +897,7 @@
 
 // Set up handlers for a oneof field.
 static void add_handlers_for_oneof_field(upb_handlers *h,
+                                         const upb_msgdef *m,
                                          const upb_fielddef *f,
                                          size_t offset,
                                          size_t oneof_case_offset,
@@ -864,7 +906,7 @@
   upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
   upb_handlerattr_sethandlerdata(
       &attr, newoneofhandlerdata(h, offset, oneof_case_offset,
-                                 property_cache_offset, f));
+                                 property_cache_offset, m, f));
 
   switch (upb_fielddef_type(f)) {
 
@@ -936,8 +978,8 @@
           desc->layout->fields[upb_fielddef_index(f)].case_offset;
       int property_cache_index =
           desc->layout->fields[upb_fielddef_index(f)].cache_index;
-      add_handlers_for_oneof_field(h, f, offset, oneof_case_offset,
-                                   property_cache_index);
+      add_handlers_for_oneof_field(h, desc->msgdef, f, offset,
+                                   oneof_case_offset, property_cache_index);
     } else if (is_map_field(f)) {
       add_handlers_for_mapfield(h, f, offset, desc);
     } else if (upb_fielddef_isseq(f)) {
@@ -1198,7 +1240,7 @@
     } else if (upb_fielddef_isstring(f)) {
       zval* str = CACHED_PTR_TO_ZVAL_PTR(
           DEREF(message_data(msg), offset, CACHED_VALUE*));
-      if (Z_STRLEN_P(str) > 0) {
+      if (containing_oneof || Z_STRLEN_P(str) > 0) {
         putstr(str, f, sink);
       }
     } else if (upb_fielddef_issubmsg(f)) {
@@ -1221,10 +1263,10 @@
         T(UPB_TYPE_DOUBLE, double, double, 0.0)
         T(UPB_TYPE_BOOL, bool, uint8_t, 0)
         case UPB_TYPE_ENUM:
-          T(UPB_TYPE_INT32, int32, int32_t, 0)
-          T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
-          T(UPB_TYPE_INT64, int64, int64_t, 0)
-          T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
+        T(UPB_TYPE_INT32, int32, int32_t, 0)
+        T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
+        T(UPB_TYPE_INT64, int64, int64_t, 0)
+        T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
 
         case UPB_TYPE_STRING:
         case UPB_TYPE_BYTES:
@@ -1246,18 +1288,23 @@
 
   assert(Z_TYPE_P(str) == IS_STRING);
 
-  // Ensure that the string has the correct encoding. We also check at field-set
-  // time, but the user may have mutated the string object since then.
-  if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
-      !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) {
-    zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
-    return;
-  }
-
   upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), Z_STRLEN_P(str),
                     &subsink);
-  upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str),
-                     Z_STRLEN_P(str), NULL);
+
+  // For oneof string field, we may get here with string length is zero.
+  if (Z_STRLEN_P(str) > 0) {
+    // Ensure that the string has the correct encoding. We also check at
+    // field-set time, but the user may have mutated the string object since
+    // then.
+    if (upb_fielddef_type(f) == UPB_TYPE_STRING &&
+        !is_structurally_valid_utf8(Z_STRVAL_P(str), Z_STRLEN_P(str))) {
+      zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
+      return;
+    }
+    upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), Z_STRVAL_P(str),
+                       Z_STRLEN_P(str), NULL);
+  }
+
   upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
 }
 
@@ -1354,7 +1401,7 @@
         MessageHeader *submsg = UNBOX(MessageHeader, *(zval**)memory);
 #else
         MessageHeader *submsg =
-            (MessageHeader*)((char*)(*(zend_object**)memory) -
+            (MessageHeader*)((char*)(Z_OBJ_P((zval*)memory)) -
                 XtOffsetOf(MessageHeader, std));
 #endif
         putrawsubmsg(submsg, f, &subsink, depth TSRMLS_CC);
@@ -1398,9 +1445,9 @@
 // PHP encode/decode methods
 // -----------------------------------------------------------------------------
 
-PHP_METHOD(Message, serializeToString) {
+void serialize_to_string(zval* val, zval* return_value TSRMLS_DC) {
   Descriptor* desc =
-      UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
+      UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
 
   stringsink sink;
   stringsink_init(&sink);
@@ -1414,7 +1461,7 @@
     stackenv_init(&se, "Error occurred during encoding: %s");
     encoder = upb_pb_encoder_create(&se.env, serialize_handlers, &sink.sink);
 
-    putmsg(getThis(), desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC);
+    putmsg(val, desc, upb_pb_encoder_input(encoder), 0 TSRMLS_CC);
 
     PHP_PROTO_RETVAL_STRINGL(sink.ptr, sink.len, 1);
 
@@ -1423,6 +1470,26 @@
   }
 }
 
+PHP_METHOD(Message, serializeToString) {
+  serialize_to_string(getThis(), return_value TSRMLS_CC);
+}
+
+void merge_from_string(const char* data, int data_len, const Descriptor* desc,
+                       MessageHeader* msg) {
+  const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
+  const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
+  stackenv se;
+  upb_sink sink;
+  upb_pbdecoder* decoder;
+  stackenv_init(&se, "Error occurred during parsing: %s");
+
+  upb_sink_reset(&sink, h, msg);
+  decoder = upb_pbdecoder_create(&se.env, method, &sink);
+  upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
+
+  stackenv_uninit(&se);
+}
+
 PHP_METHOD(Message, mergeFromString) {
   Descriptor* desc =
       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
@@ -1436,23 +1503,10 @@
     return;
   }
 
-  {
-    const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
-    const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
-    stackenv se;
-    upb_sink sink;
-    upb_pbdecoder* decoder;
-    stackenv_init(&se, "Error occurred during parsing: %s");
-
-    upb_sink_reset(&sink, h, msg);
-    decoder = upb_pbdecoder_create(&se.env, method, &sink);
-    upb_bufsrc_putbuf(data, data_len, upb_pbdecoder_input(decoder));
-
-    stackenv_uninit(&se);
-  }
+  merge_from_string(data, data_len, desc, msg);
 }
 
-PHP_METHOD(Message, jsonEncode) {
+PHP_METHOD(Message, serializeToJsonString) {
   Descriptor* desc =
       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
 
@@ -1483,13 +1537,14 @@
   }
 }
 
-PHP_METHOD(Message, jsonDecode) {
+PHP_METHOD(Message, mergeFromJsonString) {
   Descriptor* desc =
       UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(getThis())));
   MessageHeader* msg = UNBOX(MessageHeader, getThis());
 
   char *data = NULL;
-  int data_len;
+  PHP_PROTO_SIZE data_len;
+
   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) ==
       FAILURE) {
     return;
diff --git a/php/ext/google/protobuf/map.c b/php/ext/google/protobuf/map.c
index a5d4844..2680b54 100644
--- a/php/ext/google/protobuf/map.c
+++ b/php/ext/google/protobuf/map.c
@@ -143,6 +143,7 @@
   PHP_ME(MapField, offsetSet,    arginfo_offsetSet, ZEND_ACC_PUBLIC)
   PHP_ME(MapField, offsetUnset,  arginfo_offsetGet, ZEND_ACC_PUBLIC)
   PHP_ME(MapField, count,        arginfo_void,      ZEND_ACC_PUBLIC)
+  PHP_ME(MapField, getIterator,  arginfo_void,      ZEND_ACC_PUBLIC)
   ZEND_FE_END
 };
 
@@ -156,7 +157,10 @@
 // -----------------------------------------------------------------------------
 
 zend_class_entry* map_field_type;
+zend_class_entry* map_field_iter_type;
+
 zend_object_handlers* map_field_handlers;
+zend_object_handlers* map_field_iter_handlers;
 
 static void map_begin_internal(Map *map, MapIter *iter) {
   iter->self = map;
@@ -231,8 +235,8 @@
 // Init class entry.
 PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapField", Map,
                            map_field)
-zend_class_implements(map_field_type TSRMLS_CC, 2, spl_ce_ArrayAccess,
-                      spl_ce_Countable);
+zend_class_implements(map_field_type TSRMLS_CC, 3, spl_ce_ArrayAccess,
+                      zend_ce_aggregate, spl_ce_Countable);
 map_field_handlers->write_dimension = map_field_write_dimension;
 map_field_handlers->get_gc = map_field_get_gc;
 PHP_PROTO_INIT_CLASS_END
@@ -281,7 +285,7 @@
 
   if (upb_strtable_lookup2(&intern->table, keyval, length, &v)) {
     void* mem = upb_value_memory(&v);
-    native_slot_get_by_array(intern->value_type, mem, retval TSRMLS_CC);
+    native_slot_get_by_map_value(intern->value_type, mem, retval TSRMLS_CC);
     return true;
   } else {
     zend_error(E_USER_ERROR, "Given key doesn't exist.");
@@ -314,7 +318,7 @@
 
   mem = upb_value_memory(&v);
   memset(mem, 0, native_slot_size(intern->value_type));
-  if (!native_slot_set_by_array(intern->value_type, intern->msg_ce, mem,
+  if (!native_slot_set_by_map(intern->value_type, intern->msg_ce, mem,
                                 value TSRMLS_CC)) {
     return;
   }
@@ -444,6 +448,15 @@
   RETURN_LONG(upb_strtable_count(&intern->table));
 }
 
+PHP_METHOD(MapField, getIterator) {
+  CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(return_value,
+                                   map_field_iter_type);
+
+  Map *intern = UNBOX(Map, getThis());
+  MapIter *iter = UNBOX(MapIter, return_value);
+  map_begin(getThis(), iter TSRMLS_CC);
+}
+
 // -----------------------------------------------------------------------------
 // Map Iterator
 // -----------------------------------------------------------------------------
@@ -470,3 +483,79 @@
   *len = native_slot_size(iter->self->value_type);
   return upb_strtable_iter_value(&iter->it);
 }
+
+// -----------------------------------------------------------------------------
+// MapFieldIter methods
+// -----------------------------------------------------------------------------
+static zend_function_entry map_field_iter_methods[] = {
+  PHP_ME(MapFieldIter, rewind,      arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(MapFieldIter, current,     arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(MapFieldIter, key,         arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(MapFieldIter, next,        arginfo_void, ZEND_ACC_PUBLIC)
+  PHP_ME(MapFieldIter, valid,       arginfo_void, ZEND_ACC_PUBLIC)
+  ZEND_FE_END
+};
+
+// -----------------------------------------------------------------------------
+// MapFieldIter creation/desctruction
+// -----------------------------------------------------------------------------
+
+// Define object free method.
+PHP_PROTO_OBJECT_FREE_START(MapIter, map_field_iter)
+PHP_PROTO_OBJECT_FREE_END
+
+PHP_PROTO_OBJECT_DTOR_START(MapIter, map_field_iter)
+PHP_PROTO_OBJECT_DTOR_END
+
+// Define object create method.
+PHP_PROTO_OBJECT_CREATE_START(MapIter, map_field_iter)
+intern->self = NULL;
+PHP_PROTO_OBJECT_CREATE_END(MapIter, map_field_iter)
+
+// Init class entry.
+PHP_PROTO_INIT_CLASS_START("Google\\Protobuf\\Internal\\MapFieldIter",
+                           MapIter, map_field_iter)
+zend_class_implements(map_field_iter_type TSRMLS_CC, 1, zend_ce_iterator);
+PHP_PROTO_INIT_CLASS_END
+
+// -----------------------------------------------------------------------------
+// PHP MapFieldIter Methods
+// -----------------------------------------------------------------------------
+
+PHP_METHOD(MapFieldIter, rewind) {
+  MapIter *intern = UNBOX(MapIter, getThis());
+  map_begin_internal(intern->self, intern);
+}
+
+PHP_METHOD(MapFieldIter, current) {
+  MapIter *intern = UNBOX(MapIter, getThis());
+  Map *map_field = intern->self;
+
+  int value_length = 0;
+  upb_value value = map_iter_value(intern, &value_length);
+
+  void* mem = upb_value_memory(&value);
+  native_slot_get_by_map_value(map_field->value_type, mem,
+                               ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
+}
+
+PHP_METHOD(MapFieldIter, key) {
+  MapIter *intern = UNBOX(MapIter, getThis());
+  Map *map_field = intern->self;
+
+  int key_length = 0;
+  const char* key = map_iter_key(intern, &key_length);
+
+  native_slot_get_by_map_key(map_field->key_type, key, key_length,
+                             ZVAL_PTR_TO_CACHED_PTR(return_value) TSRMLS_CC);
+}
+
+PHP_METHOD(MapFieldIter, next) {
+  MapIter *intern = UNBOX(MapIter, getThis());
+  map_next(intern);
+}
+
+PHP_METHOD(MapFieldIter, valid) {
+  MapIter *intern = UNBOX(MapIter, getThis());
+  RETURN_BOOL(!map_done(intern));
+}
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index cabc398..50a0430 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -29,20 +29,22 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <php.h>
+#include <ext/date/php_date.h>
 #include <stdlib.h>
-#include <ext/json/php_json.h>
 
 #include "protobuf.h"
+#include "utf8.h"
 
-static zend_class_entry* message_type;
+zend_class_entry* message_type;
 zend_object_handlers* message_handlers;
+static const char TYPE_URL_PREFIX[] = "type.googleapis.com/";
 
 static  zend_function_entry message_methods[] = {
   PHP_ME(Message, clear, NULL, ZEND_ACC_PUBLIC)
   PHP_ME(Message, serializeToString, NULL, ZEND_ACC_PUBLIC)
   PHP_ME(Message, mergeFromString, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, jsonEncode, NULL, ZEND_ACC_PUBLIC)
-  PHP_ME(Message, jsonDecode, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, serializeToJsonString, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Message, mergeFromJsonString, NULL, ZEND_ACC_PUBLIC)
   PHP_ME(Message, mergeFrom, NULL, ZEND_ACC_PUBLIC)
   PHP_ME(Message, readOneof, NULL, ZEND_ACC_PROTECTED)
   PHP_ME(Message, writeOneof, NULL, ZEND_ACC_PROTECTED)
@@ -104,6 +106,20 @@
   message_handlers->get_gc = message_get_gc;
 PHP_PROTO_INIT_CLASS_END
 
+static void message_set_property_internal(zval* object, zval* member,
+                                          zval* value TSRMLS_DC) {
+  const upb_fielddef* field;
+
+  MessageHeader* self = UNBOX(MessageHeader, object);
+
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
+  if (field == NULL) {
+    zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member));
+  }
+
+  layout_set(self->descriptor->layout, self, field, value TSRMLS_CC);
+}
+
 #if PHP_MAJOR_VERSION < 7
 static void message_set_property(zval* object, zval* member, zval* value,
                                  php_proto_zend_literal key TSRMLS_DC) {
@@ -116,22 +132,42 @@
     return;
   }
 
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
   if (Z_OBJCE_P(object) != EG(scope)) {
+#else
+  if (Z_OBJCE_P(object) != zend_get_executed_scope()) {
+#endif
     // User cannot set property directly (e.g., $m->a = 1)
     zend_error(E_USER_ERROR, "Cannot access private property.");
     return;
   }
 
-  const upb_fielddef* field;
+  message_set_property_internal(object, member, value TSRMLS_CC);
+}
 
+static zval* message_get_property_internal(zval* object,
+                                           zval* member TSRMLS_DC) {
   MessageHeader* self = UNBOX(MessageHeader, object);
-
+  const upb_fielddef* field;
   field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
   if (field == NULL) {
-    zend_error(E_USER_ERROR, "Unknown field: %s", Z_STRVAL_P(member));
+    return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
   }
 
-  layout_set(self->descriptor->layout, self, field, value TSRMLS_CC);
+  zend_property_info* property_info;
+#if PHP_MAJOR_VERSION < 7
+  property_info =
+      zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC);
+  return layout_get(
+      self->descriptor->layout, message_data(self), field,
+      OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
+#else
+  property_info =
+      zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true);
+  return layout_get(
+      self->descriptor->layout, message_data(self), field,
+      OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
+#endif
 }
 
 #if PHP_MAJOR_VERSION < 7
@@ -146,33 +182,17 @@
     return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
   }
 
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
   if (Z_OBJCE_P(object) != EG(scope)) {
+#else
+  if (Z_OBJCE_P(object) != zend_get_executed_scope()) {
+#endif
     // User cannot get property directly (e.g., $a = $m->a)
     zend_error(E_USER_ERROR, "Cannot access private property.");
     return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
   }
 
-  MessageHeader* self = UNBOX(MessageHeader, object);
-  const upb_fielddef* field;
-  field = upb_msgdef_ntofz(self->descriptor->msgdef, Z_STRVAL_P(member));
-  if (field == NULL) {
-    return PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL;
-  }
-
-  zend_property_info* property_info;
-#if PHP_MAJOR_VERSION < 7
-  property_info =
-      zend_get_property_info(Z_OBJCE_P(object), member, true TSRMLS_CC);
-  return layout_get(
-      self->descriptor->layout, message_data(self), field,
-      &Z_OBJ_P(object)->properties_table[property_info->offset] TSRMLS_CC);
-#else
-  property_info =
-      zend_get_property_info(Z_OBJCE_P(object), Z_STR_P(member), true);
-  return layout_get(
-      self->descriptor->layout, message_data(self), field,
-      OBJ_PROP(Z_OBJ_P(object), property_info->offset) TSRMLS_CC);
-#endif
+  return message_get_property_internal(object, member TSRMLS_CC);
 }
 
 #if PHP_MAJOR_VERSION < 7
@@ -215,7 +235,7 @@
   // case a collection happens during object creation in layout_init().
   intern->descriptor = desc;
   layout_init(desc->layout, message_data(intern),
-              intern->std.properties_table PHP_PROTO_TSRMLS_CC);
+              &intern->std PHP_PROTO_TSRMLS_CC);
 }
 
 void build_class_from_descriptor(
@@ -258,8 +278,7 @@
   zend_class_entry* ce = desc->klass;
 
   object_properties_init(&msg->std, ce);
-  layout_init(desc->layout, message_data(msg),
-              msg->std.properties_table TSRMLS_CC);
+  layout_init(desc->layout, message_data(msg), &msg->std TSRMLS_CC);
 }
 
 PHP_METHOD(Message, mergeFrom) {
@@ -294,7 +313,8 @@
 
   int property_cache_index =
       msg->descriptor->layout->fields[upb_fielddef_index(field)].cache_index;
-  zval* property_ptr = OBJ_PROP(Z_OBJ_P(getThis()), property_cache_index);
+  zval* property_ptr = CACHED_PTR_TO_ZVAL_PTR(
+      OBJ_PROP(Z_OBJ_P(getThis()), property_cache_index));
 
   // Unlike singular fields, oneof fields share cached property. So we cannot
   // let lay_get modify the cached property. Instead, we pass in the return
@@ -335,3 +355,406 @@
       msg->descriptor->layout, message_data(msg), oneof TSRMLS_CC);
   PHP_PROTO_RETURN_STRING(oneof_case_name, 1);
 }
+
+// -----------------------------------------------------------------------------
+// Well Known Types Support
+// -----------------------------------------------------------------------------
+
+#define PHP_PROTO_FIELD_ACCESSORS(UPPER_CLASS, LOWER_CLASS, UPPER_FIELD,       \
+                                  LOWER_FIELD)                                 \
+  PHP_METHOD(UPPER_CLASS, get##UPPER_FIELD) {                                  \
+    zval member;                                                               \
+    PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1);                            \
+    PHP_PROTO_FAKE_SCOPE_BEGIN(LOWER_CLASS##_type);                            \
+    zval* value = message_get_property_internal(getThis(), &member TSRMLS_CC); \
+    PHP_PROTO_FAKE_SCOPE_END;                                                  \
+    PHP_PROTO_RETVAL_ZVAL(value);                                              \
+  }                                                                            \
+  PHP_METHOD(UPPER_CLASS, set##UPPER_FIELD) {                                  \
+    zval* value = NULL;                                                        \
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) ==       \
+        FAILURE) {                                                             \
+      return;                                                                  \
+    }                                                                          \
+    zval member;                                                               \
+    PHP_PROTO_ZVAL_STRING(&member, LOWER_FIELD, 1);                            \
+    message_set_property_internal(getThis(), &member, value TSRMLS_CC);        \
+    PHP_PROTO_RETVAL_ZVAL(getThis());                                          \
+  }
+
+// -----------------------------------------------------------------------------
+// Any
+// -----------------------------------------------------------------------------
+
+static  zend_function_entry any_methods[] = {
+  PHP_ME(Any, __construct, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, getTypeUrl, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, setTypeUrl, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, getValue, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, setValue, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, pack,     NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, unpack,   NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Any, is,       NULL, ZEND_ACC_PUBLIC)
+  {NULL, NULL, NULL}
+};
+
+zend_class_entry* any_type;
+
+// Init class entry.
+PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Any", Any, any)
+  zend_class_implements(any_type TSRMLS_CC, 1, message_type);
+  zend_declare_property_string(any_type, "type_url", strlen("type_url"),
+                               "" ,ZEND_ACC_PRIVATE TSRMLS_CC);
+  zend_declare_property_string(any_type, "value", strlen("value"),
+                               "" ,ZEND_ACC_PRIVATE TSRMLS_CC);
+PHP_PROTO_INIT_SUBMSGCLASS_END
+
+void hex_to_binary(const char* hex, char** binary, int* binary_len) {
+  int i;
+  int hex_len = strlen(hex);
+  *binary_len = hex_len / 2;
+  *binary = ALLOC_N(char, *binary_len);
+  for (i = 0; i < *binary_len; i++) {
+    char value = 0;
+    if (hex[i * 2] >= '0' && hex[i * 2] <= '9') {
+      value += (hex[i * 2] - '0') * 16;
+    } else {
+      value += (hex[i * 2] - 'a' + 10) * 16;
+    }
+    if (hex[i * 2 + 1] >= '0' && hex[i * 2 + 1] <= '9') {
+      value += hex[i * 2 + 1] - '0';
+    } else {
+      value += hex[i * 2 + 1] - 'a' + 10;
+    }
+    (*binary)[i] = value;
+  }
+}
+
+PHP_METHOD(Any, __construct) {
+  PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(any_type);
+  if (desc_php == NULL) {
+    init_generated_pool_once(TSRMLS_C);
+    const char* generated_file =
+      "0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f"
+      "120f676f6f676c652e70726f746f62756622260a03416e7912100a087479"
+      "70655f75726c180120012809120d0a0576616c756518022001280c426f0a"
+      "13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f"
+      "50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566"
+      "2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f"
+      "746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33";
+    char* binary;
+    int binary_len;
+    hex_to_binary(generated_file, &binary, &binary_len);
+
+    internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
+    FREE(binary);
+  }
+
+  MessageHeader* intern = UNBOX(MessageHeader, getThis());
+  custom_data_init(any_type, intern PHP_PROTO_TSRMLS_CC);
+}
+
+PHP_PROTO_FIELD_ACCESSORS(Any, any, TypeUrl, "type_url")
+PHP_PROTO_FIELD_ACCESSORS(Any, any, Value,   "value")
+
+PHP_METHOD(Any, unpack) {
+  // Get type url.
+  zval type_url_member;
+  PHP_PROTO_ZVAL_STRING(&type_url_member, "type_url", 1);
+  PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
+  zval* type_url_php = php_proto_message_read_property(
+      getThis(), &type_url_member PHP_PROTO_TSRMLS_CC);
+  PHP_PROTO_FAKE_SCOPE_END;
+
+  // Get fully-qualified name from type url.
+  size_t url_prefix_len = strlen(TYPE_URL_PREFIX);
+  const char* type_url = Z_STRVAL_P(type_url_php);
+  size_t type_url_len = Z_STRLEN_P(type_url_php);
+
+  if (url_prefix_len > type_url_len ||
+      strncmp(TYPE_URL_PREFIX, type_url, url_prefix_len) != 0) {
+    zend_throw_exception(
+        NULL, "Type url needs to be type.googleapis.com/fully-qulified",
+        0 TSRMLS_CC);
+    return;
+  }
+
+  const char* fully_qualified_name = type_url + url_prefix_len;
+  PHP_PROTO_HASHTABLE_VALUE desc_php = get_proto_obj(fully_qualified_name);
+  if (desc_php == NULL) {
+    zend_throw_exception(
+        NULL, "Specified message in any hasn't been added to descriptor pool",
+        0 TSRMLS_CC);
+    return;
+  }
+  Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, desc_php);
+  zend_class_entry* klass = desc->klass;
+  ZVAL_OBJ(return_value, klass->create_object(klass TSRMLS_CC));
+  MessageHeader* msg = UNBOX(MessageHeader, return_value);
+  custom_data_init(klass, msg PHP_PROTO_TSRMLS_CC);
+
+  // Get value.
+  zval value_member;
+  PHP_PROTO_ZVAL_STRING(&value_member, "value", 1);
+  PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
+  zval* value = php_proto_message_read_property(
+      getThis(), &value_member PHP_PROTO_TSRMLS_CC);
+  PHP_PROTO_FAKE_SCOPE_END;
+
+  merge_from_string(Z_STRVAL_P(value), Z_STRLEN_P(value), desc, msg);
+}
+
+PHP_METHOD(Any, pack) {
+  zval* val;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &val) ==
+      FAILURE) {
+    return;
+  }
+
+  if (!instanceof_function(Z_OBJCE_P(val), message_type TSRMLS_CC)) {
+    zend_error(E_USER_ERROR, "Given value is not an instance of Message.");
+    return;
+  }
+
+  // Set value by serialized data.
+  zval data;
+  serialize_to_string(val, &data TSRMLS_CC);
+
+  zval member;
+  PHP_PROTO_ZVAL_STRING(&member, "value", 1);
+
+  PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
+  message_handlers->write_property(getThis(), &member, &data,
+                                   NULL PHP_PROTO_TSRMLS_CC);
+  PHP_PROTO_FAKE_SCOPE_END;
+
+  // Set type url.
+  Descriptor* desc =
+      UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(Z_OBJCE_P(val)));
+  const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
+  size_t type_url_len =
+      strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
+  char* type_url = ALLOC_N(char, type_url_len);
+  sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
+  zval type_url_php;
+  PHP_PROTO_ZVAL_STRING(&type_url_php, type_url, 1);
+  PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
+
+  PHP_PROTO_FAKE_SCOPE_RESTART(any_type);
+  message_handlers->write_property(getThis(), &member, &type_url_php,
+                                   NULL PHP_PROTO_TSRMLS_CC);
+  PHP_PROTO_FAKE_SCOPE_END;
+  FREE(type_url);
+}
+
+PHP_METHOD(Any, is) {
+  zend_class_entry *klass = NULL;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &klass) ==
+      FAILURE) {
+    return;
+  }
+
+  PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(klass);
+  if (desc_php == NULL) {
+    RETURN_BOOL(false);
+  }
+
+  // Create corresponded type url.
+  Descriptor* desc =
+      UNBOX_HASHTABLE_VALUE(Descriptor, get_ce_obj(klass));
+  const char* fully_qualified_name = upb_msgdef_fullname(desc->msgdef);
+  size_t type_url_len =
+      strlen(TYPE_URL_PREFIX) + strlen(fully_qualified_name) + 1;
+  char* type_url = ALLOC_N(char, type_url_len);
+  sprintf(type_url, "%s%s", TYPE_URL_PREFIX, fully_qualified_name);
+
+  // Fetch stored type url.
+  zval member;
+  PHP_PROTO_ZVAL_STRING(&member, "type_url", 1);
+  PHP_PROTO_FAKE_SCOPE_BEGIN(any_type);
+  zval* value =
+      php_proto_message_read_property(getThis(), &member PHP_PROTO_TSRMLS_CC);
+  PHP_PROTO_FAKE_SCOPE_END;
+
+  // Compare two type url.
+  bool is = strcmp(type_url, Z_STRVAL_P(value)) == 0;
+  FREE(type_url);
+
+  RETURN_BOOL(is);
+}
+
+// -----------------------------------------------------------------------------
+// Duration
+// -----------------------------------------------------------------------------
+
+static  zend_function_entry duration_methods[] = {
+  PHP_ME(Duration, __construct, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Duration, getSeconds, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Duration, setSeconds, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Duration, getNanos, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Duration, setNanos, NULL, ZEND_ACC_PUBLIC)
+  {NULL, NULL, NULL}
+};
+
+zend_class_entry* duration_type;
+
+// Init class entry.
+PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Duration",
+                                 Duration, duration)
+  zend_class_implements(duration_type TSRMLS_CC, 1, message_type);
+  zend_declare_property_long(duration_type, "seconds", strlen("seconds"),
+                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
+  zend_declare_property_long(duration_type, "nanos", strlen("nanos"),
+                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
+PHP_PROTO_INIT_SUBMSGCLASS_END
+
+PHP_METHOD(Duration, __construct) {
+  PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(duration_type);
+  if (desc_php == NULL) {
+    init_generated_pool_once(TSRMLS_C);
+    const char* generated_file =
+      "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e"
+      "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261"
+      "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73"
+      "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642"
+      "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67"
+      "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e"
+      "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765"
+      "6c6c4b6e6f776e5479706573620670726f746f33";
+    char* binary;
+    int binary_len;
+    hex_to_binary(generated_file, &binary, &binary_len);
+
+    internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
+    FREE(binary);
+  }
+
+  MessageHeader* intern = UNBOX(MessageHeader, getThis());
+  custom_data_init(duration_type, intern PHP_PROTO_TSRMLS_CC);
+}
+
+PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Seconds, "seconds")
+PHP_PROTO_FIELD_ACCESSORS(Duration, duration, Nanos,   "nanos")
+
+// -----------------------------------------------------------------------------
+// Timestamp
+// -----------------------------------------------------------------------------
+
+static  zend_function_entry timestamp_methods[] = {
+  PHP_ME(Timestamp, __construct, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Timestamp, fromDateTime, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Timestamp, toDateTime, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Timestamp, getSeconds, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Timestamp, setSeconds, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Timestamp, getNanos, NULL, ZEND_ACC_PUBLIC)
+  PHP_ME(Timestamp, setNanos, NULL, ZEND_ACC_PUBLIC)
+  {NULL, NULL, NULL}
+};
+
+zend_class_entry* timestamp_type;
+
+// Init class entry.
+PHP_PROTO_INIT_SUBMSGCLASS_START("Google\\Protobuf\\Timestamp",
+                                 Timestamp, timestamp)
+  zend_class_implements(timestamp_type TSRMLS_CC, 1, message_type);
+  zend_declare_property_long(timestamp_type, "seconds", strlen("seconds"),
+                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
+  zend_declare_property_long(timestamp_type, "nanos", strlen("nanos"),
+                             0 ,ZEND_ACC_PRIVATE TSRMLS_CC);
+PHP_PROTO_INIT_SUBMSGCLASS_END
+
+PHP_METHOD(Timestamp, __construct) {
+  PHP_PROTO_HASHTABLE_VALUE desc_php = get_ce_obj(timestamp_type);
+  if (desc_php == NULL) {
+    init_generated_pool_once(TSRMLS_C);
+    const char* generated_file =
+      "0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70"
+      "2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d"
+      "657374616d70120f0a077365636f6e6473180120012803120d0a056e616e"
+      "6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275"
+      "66420e54696d657374616d7050726f746f50015a2b6769746875622e636f"
+      "6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573"
+      "74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275"
+      "662e57656c6c4b6e6f776e5479706573620670726f746f33";
+    char* binary;
+    int binary_len;
+    hex_to_binary(generated_file, &binary, &binary_len);
+
+    internal_add_generated_file(binary, binary_len, generated_pool TSRMLS_CC);
+    FREE(binary);
+  }
+
+  MessageHeader* intern = UNBOX(MessageHeader, getThis());
+  custom_data_init(timestamp_type, intern PHP_PROTO_TSRMLS_CC);
+}
+
+PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Seconds, "seconds")
+PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Nanos,   "nanos")
+
+PHP_METHOD(Timestamp, fromDateTime) {
+  zval* datetime;
+  zval member;
+
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &datetime,
+                            php_date_get_date_ce()) == FAILURE) {
+    return;
+  }
+
+  php_date_obj* dateobj = UNBOX(php_date_obj, datetime);
+  if (!dateobj->time->sse_uptodate) {
+    timelib_update_ts(dateobj->time, NULL);
+  }
+
+  int64_t timestamp = dateobj->time->sse;
+
+  // Set seconds
+  MessageHeader* self = UNBOX(MessageHeader, getThis());
+  const upb_fielddef* field =
+      upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
+  void* storage = message_data(self);
+  void* memory = slot_memory(self->descriptor->layout, storage, field);
+  *(int64_t*)memory = dateobj->time->sse;
+
+  // Set nanos
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
+  storage = message_data(self);
+  memory = slot_memory(self->descriptor->layout, storage, field);
+  *(int32_t*)memory = 0;
+}
+
+PHP_METHOD(Timestamp, toDateTime) {
+  zval datetime;
+  php_date_instantiate(php_date_get_date_ce(), &datetime TSRMLS_CC);
+  php_date_obj* dateobj = UNBOX(php_date_obj, &datetime);
+
+  // Get seconds
+  MessageHeader* self = UNBOX(MessageHeader, getThis());
+  const upb_fielddef* field =
+      upb_msgdef_ntofz(self->descriptor->msgdef, "seconds");
+  void* storage = message_data(self);
+  void* memory = slot_memory(self->descriptor->layout, storage, field);
+  int64_t seconds = *(int64_t*)memory;
+
+  // Get nanos
+  field = upb_msgdef_ntofz(self->descriptor->msgdef, "nanos");
+  memory = slot_memory(self->descriptor->layout, storage, field);
+  int32_t nanos = *(int32_t*)memory;
+
+  // Get formated time string.
+  char formated_time[50];
+  time_t raw_time = seconds;
+  struct tm *utc_time = gmtime(&raw_time);
+  strftime(formated_time, sizeof(formated_time), "%Y-%m-%dT%H:%M:%SUTC",
+           utc_time);
+
+  if (!php_date_initialize(dateobj, formated_time, strlen(formated_time), NULL,
+                           NULL, 0 TSRMLS_CC)) {
+    zval_dtor(&datetime);
+    RETURN_NULL();
+  }
+
+  zval* datetime_ptr = &datetime;
+  PHP_PROTO_RETVAL_ZVAL(datetime_ptr);
+}
diff --git a/php/ext/google/protobuf/package.xml b/php/ext/google/protobuf/package.xml
index a2a8e06..2d31851 100644
--- a/php/ext/google/protobuf/package.xml
+++ b/php/ext/google/protobuf/package.xml
@@ -13,8 +13,8 @@
  <date>2017-01-13</date>
  <time>16:06:07</time>
  <version>
-  <release>3.3.0</release>
-  <api>3.3.0</api>
+  <release>3.4.0</release>
+  <api>3.4.0</api>
  </version>
  <stability>
   <release>stable</release>
@@ -40,6 +40,7 @@
     <file baseinstalldir="/" name="upb.h" role="src" />
     <file baseinstalldir="/" name="utf8.c" role="src" />
     <file baseinstalldir="/" name="utf8.h" role="src" />
+    <file baseinstalldir="/" name="LICENSE" role="doc" />
   </dir>
  </contents>
  <dependencies>
@@ -103,5 +104,53 @@
 GA release.
    </notes>
   </release>
+  <release>
+   <version>
+    <release>3.3.1</release>
+    <api>3.3.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2017-05-08</date>
+   <time>15:33:07</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+GA release.
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.3.2</release>
+    <api>3.3.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2017-06-21</date>
+   <time>15:33:07</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+GA release.
+   </notes>
+  </release>
+  <release>
+   <version>
+    <release>3.4.0</release>
+    <api>3.4.0</api>
+   </version>
+   <stability>
+    <release>stable</release>
+    <api>stable</api>
+   </stability>
+   <date>2017-08-16</date>
+   <time>15:33:07</time>
+   <license uri="https://opensource.org/licenses/BSD-3-Clause">3-Clause BSD License</license>
+   <notes>
+GA release.
+   </notes>
+  </release>
  </changelog>
 </package>
diff --git a/php/ext/google/protobuf/protobuf.c b/php/ext/google/protobuf/protobuf.c
index 6a848b2..42bc31c 100644
--- a/php/ext/google/protobuf/protobuf.c
+++ b/php/ext/google/protobuf/protobuf.c
@@ -46,6 +46,9 @@
 // Global map from message/enum's php class entry to corresponding wrapper
 // Descriptor/EnumDescriptor instances.
 static HashTable* ce_to_php_obj_map;
+// Global map from message/enum's proto fully-qualified name to corresponding
+// wrapper Descriptor/EnumDescriptor instances.
+static HashTable* proto_to_php_obj_map;
 
 // -----------------------------------------------------------------------------
 // Global maps.
@@ -55,15 +58,14 @@
   uint nIndex = (ulong)def & t->nTableMask;
 
   zval* pDest = NULL;
-  php_proto_zend_hash_index_update(t, (zend_ulong)def, &value, sizeof(zval*),
-                                   (void**)&pDest);
+  php_proto_zend_hash_index_update_mem(t, (zend_ulong)def, &value,
+                                       sizeof(zval*), (void**)&pDest);
 }
 
 static void* get_from_table(const HashTable* t, const void* def) {
   void** value;
-  if (php_proto_zend_hash_index_find(t, (zend_ulong)def, (void**)&value) ==
+  if (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def, (void**)&value) ==
       FAILURE) {
-    zend_error(E_ERROR, "PHP object not found for given definition.\n");
     return NULL;
   }
   return *value;
@@ -71,16 +73,32 @@
 
 static bool exist_in_table(const HashTable* t, const void* def) {
   void** value;
-  return (php_proto_zend_hash_index_find(t, (zend_ulong)def, (void**)&value) ==
-          SUCCESS);
+  return (php_proto_zend_hash_index_find_mem(t, (zend_ulong)def,
+                                             (void**)&value) == SUCCESS);
 }
 
 static void add_to_list(HashTable* t, void* value) {
   zval* pDest = NULL;
-  php_proto_zend_hash_next_index_insert(t, &value, sizeof(void*),
+  php_proto_zend_hash_next_index_insert_mem(t, &value, sizeof(void*),
                                         (void**)&pDest);
 }
 
+static void add_to_strtable(HashTable* t, const char* key, int key_size,
+                            void* value) {
+  zval* pDest = NULL;
+  php_proto_zend_hash_update_mem(t, key, key_size, &value, sizeof(void*),
+                                 (void**)&pDest);
+}
+
+static void* get_from_strtable(const HashTable* t, const char* key, int key_size) {
+  void** value;
+  if (php_proto_zend_hash_find_mem(t, key, key_size, (void**)&value) ==
+      FAILURE) {
+    return NULL;
+  }
+  return *value;
+}
+
 void add_def_obj(const void* def, PHP_PROTO_HASHTABLE_VALUE value) {
 #if PHP_MAJOR_VERSION < 7
   Z_ADDREF_P(value);
@@ -111,6 +129,20 @@
   return exist_in_table(ce_to_php_obj_map, ce);
 }
 
+void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value) {
+#if PHP_MAJOR_VERSION < 7
+  Z_ADDREF_P(value);
+#else
+  ++GC_REFCOUNT(value);
+#endif
+  add_to_strtable(proto_to_php_obj_map, proto, strlen(proto), value);
+}
+
+PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto) {
+  return (PHP_PROTO_HASHTABLE_VALUE)get_from_strtable(proto_to_php_obj_map,
+                                                      proto, strlen(proto));
+}
+
 // -----------------------------------------------------------------------------
 // Utilities.
 // -----------------------------------------------------------------------------
@@ -164,8 +196,12 @@
   ALLOC_HASHTABLE(ce_to_php_obj_map);
   zend_hash_init(ce_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
 
+  ALLOC_HASHTABLE(proto_to_php_obj_map);
+  zend_hash_init(proto_to_php_obj_map, 16, NULL, HASHTABLE_VALUE_DTOR, 0);
+
   generated_pool = NULL;
   generated_pool_php = NULL;
+  internal_generated_pool_php = NULL;
 
   return 0;
 }
@@ -177,26 +213,52 @@
   zend_hash_destroy(ce_to_php_obj_map);
   FREE_HASHTABLE(ce_to_php_obj_map);
 
+  zend_hash_destroy(proto_to_php_obj_map);
+  FREE_HASHTABLE(proto_to_php_obj_map);
+
 #if PHP_MAJOR_VERSION < 7
   if (generated_pool_php != NULL) {
     zval_dtor(generated_pool_php);
     FREE_ZVAL(generated_pool_php);
   }
+  if (internal_generated_pool_php != NULL) {
+    zval_dtor(internal_generated_pool_php);
+    FREE_ZVAL(internal_generated_pool_php);
+  }
+#else
+  if (generated_pool_php != NULL) {
+    zval tmp;
+    ZVAL_OBJ(&tmp, generated_pool_php);
+    zval_dtor(&tmp);
+  }
+  if (internal_generated_pool_php != NULL) {
+    zval tmp;
+    ZVAL_OBJ(&tmp, internal_generated_pool_php);
+    zval_dtor(&tmp);
+  }
 #endif
 
   return 0;
 }
 
 static PHP_MINIT_FUNCTION(protobuf) {
-  map_field_init(TSRMLS_C);
-  repeated_field_init(TSRMLS_C);
-  repeated_field_iter_init(TSRMLS_C);
-  gpb_type_init(TSRMLS_C);
-  message_init(TSRMLS_C);
   descriptor_pool_init(TSRMLS_C);
   descriptor_init(TSRMLS_C);
   enum_descriptor_init(TSRMLS_C);
+  enum_value_descriptor_init(TSRMLS_C);
+  field_descriptor_init(TSRMLS_C);
+  gpb_type_init(TSRMLS_C);
+  internal_descriptor_pool_init(TSRMLS_C);
+  map_field_init(TSRMLS_C);
+  map_field_iter_init(TSRMLS_C);
+  message_init(TSRMLS_C);
+  oneof_descriptor_init(TSRMLS_C);
+  repeated_field_init(TSRMLS_C);
+  repeated_field_iter_init(TSRMLS_C);
   util_init(TSRMLS_C);
+  any_init(TSRMLS_C);
+  duration_init(TSRMLS_C);
+  timestamp_init(TSRMLS_C);
 
   return 0;
 }
@@ -206,6 +268,7 @@
   PEFREE(repeated_field_handlers);
   PEFREE(repeated_field_iter_handlers);
   PEFREE(map_field_handlers);
+  PEFREE(map_field_iter_handlers);
 
   return 0;
 }
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index e6d42eb..d4ab2ce 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -37,7 +37,7 @@
 #include "upb.h"
 
 #define PHP_PROTOBUF_EXTNAME "protobuf"
-#define PHP_PROTOBUF_VERSION "3.3.0"
+#define PHP_PROTOBUF_VERSION "3.4.0"
 
 #define MAX_LENGTH_OF_INT64 20
 #define SIZEOF_INT64 8
@@ -74,13 +74,35 @@
 
 #define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(array)
 
-#define php_proto_zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
+#define php_proto_zend_hash_index_update_zval(ht, h, pData) \
+  zend_hash_index_update(ht, h, &(pData), sizeof(void*), NULL)
+
+#define php_proto_zend_hash_update_zval(ht, key, key_len, value) \
+  zend_hash_update(ht, key, key_len, value, sizeof(void*), NULL)
+
+#define php_proto_zend_hash_index_update_mem(ht, h, pData, nDataSize, pDest) \
   zend_hash_index_update(ht, h, pData, nDataSize, pDest)
 
-#define php_proto_zend_hash_index_find(ht, h, pDest) \
+#define php_proto_zend_hash_update_mem(ht, key, key_len, pData, nDataSize, \
+                                       pDest)                              \
+  zend_hash_update(ht, key, key_len, pData, nDataSize, pDest)
+
+#define php_proto_zend_hash_index_find_zval(ht, h, pDest) \
   zend_hash_index_find(ht, h, pDest)
 
-#define php_proto_zend_hash_next_index_insert(ht, pData, nDataSize, pDest) \
+#define php_proto_zend_hash_index_find_mem(ht, h, pDest) \
+  zend_hash_index_find(ht, h, pDest)
+
+#define php_proto_zend_hash_find_zval(ht, key, key_len, pDest) \
+  zend_hash_find(ht, key, key_len, pDest)
+
+#define php_proto_zend_hash_find_mem(ht, key, key_len, pDest) \
+  zend_hash_find(ht, key, key_len, pDest)
+
+#define php_proto_zend_hash_next_index_insert_zval(ht, pData) \
+  zend_hash_next_index_insert(ht, pData, sizeof(void*), NULL)
+
+#define php_proto_zend_hash_next_index_insert_mem(ht, pData, nDataSize, pDest) \
   zend_hash_next_index_insert(ht, pData, nDataSize, pDest)
 
 #define php_proto_zend_hash_get_current_data_ex(ht, pDest, pos) \
@@ -94,6 +116,17 @@
 #define PHP_PROTO_WRAP_OBJECT_END \
   };
 
+#define PHP_PROTO_INIT_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)   \
+  void LOWWERNAME##_init(TSRMLS_D) {                                         \
+    zend_class_entry class_type;                                             \
+    const char* class_name = CLASSNAME;                                      \
+    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
+                        LOWWERNAME##_methods);                               \
+    LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
+    LOWWERNAME##_type->create_object = message_create;
+#define PHP_PROTO_INIT_SUBMSGCLASS_END \
+  }
+
 #define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)         \
   void LOWWERNAME##_init(TSRMLS_D) {                                         \
     zend_class_entry class_type;                                             \
@@ -142,7 +175,7 @@
 
 #define PHP_PROTO_GLOBAL_UNINITIALIZED_ZVAL EG(uninitialized_zval_ptr)
 
-#define OBJ_PROP(PROPERTIES, OFFSET) (PROPERTIES)->properties_table[OFFSET]
+#define OBJ_PROP(OBJECT, OFFSET) &((OBJECT)->properties_table[OFFSET])
 
 #define php_proto_zval_ptr_dtor(zval_ptr) \
   zval_ptr_dtor(&(zval_ptr))
@@ -176,6 +209,7 @@
 #define HASHTABLE_VALUE_DTOR ZVAL_PTR_DTOR
 
 #define PHP_PROTO_HASHTABLE_VALUE zval*
+#define HASHTABLE_VALUE_CE(val) Z_OBJCE_P(val)
 
 #define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
   OBJ_TYPE* OBJ;                                                            \
@@ -192,6 +226,8 @@
 #define php_proto_zend_lookup_class(name, name_length, ce) \
   zend_lookup_class(name, name_length, ce TSRMLS_CC)
 
+#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_ZVAL(return_value, value, 1, 0)
+
 #else  // PHP_MAJOR_VERSION >= 7
 
 #define php_proto_zend_literal void**
@@ -217,7 +253,14 @@
 
 #define PHP_PROTO_HASH_OF(array) Z_ARRVAL_P(&array)
 
-static inline int php_proto_zend_hash_index_update(HashTable* ht, ulong h,
+static inline int php_proto_zend_hash_index_update_zval(HashTable* ht, ulong h,
+                                                        zval* pData) {
+  void* result = NULL;
+  result = zend_hash_index_update(ht, h, pData);
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
+static inline int php_proto_zend_hash_index_update_mem(HashTable* ht, ulong h,
                                                    void* pData, uint nDataSize,
                                                    void** pDest) {
   void* result = NULL;
@@ -226,18 +269,69 @@
   return result != NULL ? SUCCESS : FAILURE;
 }
 
-static inline int php_proto_zend_hash_index_find(const HashTable* ht, ulong h,
-                                                 void** pDest) {
+static inline int php_proto_zend_hash_update_zval(HashTable* ht,
+                                                  const char* key, uint key_len,
+                                                  zval* pData) {
+  zend_string* internal_key = zend_string_init(key, key_len, 0);
+  zend_hash_update(ht, internal_key, pData);
+}
+
+static inline int php_proto_zend_hash_update_mem(HashTable* ht, const char* key,
+                                                 uint key_len, void* pData,
+                                                 uint nDataSize, void** pDest) {
+  zend_string* internal_key = zend_string_init(key, key_len, 0);
+  void* result = zend_hash_update_mem(ht, internal_key, pData, nDataSize);
+  zend_string_release(internal_key);
+  if (pDest != NULL) *pDest = result;
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
+static inline int php_proto_zend_hash_index_find_zval(const HashTable* ht,
+                                                      ulong h, void** pDest) {
+  zval* result = zend_hash_index_find(ht, h);
+  if (pDest != NULL) *pDest = result;
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
+static inline int php_proto_zend_hash_index_find_mem(const HashTable* ht,
+                                                     ulong h, void** pDest) {
   void* result = NULL;
   result = zend_hash_index_find_ptr(ht, h);
   if (pDest != NULL) *pDest = result;
   return result != NULL ? SUCCESS : FAILURE;
 }
 
-static inline int php_proto_zend_hash_next_index_insert(HashTable* ht,
-                                                        void* pData,
-                                                        uint nDataSize,
-                                                        void** pDest) {
+static inline int php_proto_zend_hash_find_zval(const HashTable* ht,
+                                                const char* key, uint key_len,
+                                                void** pDest) {
+  zend_string* internal_key = zend_string_init(key, key_len, 1);
+  zval* result = zend_hash_find(ht, internal_key);
+  if (pDest != NULL) *pDest = result;
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
+static inline int php_proto_zend_hash_find_mem(const HashTable* ht,
+                                                const char* key, uint key_len,
+                                                void** pDest) {
+  zend_string* internal_key = zend_string_init(key, key_len, 1);
+  void* result = zend_hash_find_ptr(ht, internal_key);
+  zend_string_release(internal_key);
+  if (pDest != NULL) *pDest = result;
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
+static inline int php_proto_zend_hash_next_index_insert_zval(HashTable* ht,
+                                                             void* pData) {
+  zval tmp;
+  ZVAL_OBJ(&tmp, *(zend_object**)pData);
+  zval* result = zend_hash_next_index_insert(ht, &tmp);
+  return result != NULL ? SUCCESS : FAILURE;
+}
+
+static inline int php_proto_zend_hash_next_index_insert_mem(HashTable* ht,
+                                                            void* pData,
+                                                            uint nDataSize,
+                                                            void** pDest) {
   void* result = NULL;
   result = zend_hash_next_index_insert_mem(ht, pData, nDataSize);
   if (pDest != NULL) *pDest = result;
@@ -260,6 +354,17 @@
   zend_object std;                \
   };
 
+#define PHP_PROTO_INIT_SUBMSGCLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)   \
+  void LOWWERNAME##_init(TSRMLS_D) {                                         \
+    zend_class_entry class_type;                                             \
+    const char* class_name = CLASSNAME;                                      \
+    INIT_CLASS_ENTRY_EX(class_type, CLASSNAME, strlen(CLASSNAME),            \
+                        LOWWERNAME##_methods);                               \
+    LOWWERNAME##_type = zend_register_internal_class(&class_type TSRMLS_CC); \
+    LOWWERNAME##_type->create_object = message_create;
+#define PHP_PROTO_INIT_SUBMSGCLASS_END \
+  }
+
 #define PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWWERNAME)         \
   void LOWWERNAME##_init(TSRMLS_D) {                                         \
     zend_class_entry class_type;                                             \
@@ -338,6 +443,7 @@
 #define HASHTABLE_VALUE_DTOR php_proto_hashtable_descriptor_release
 
 #define PHP_PROTO_HASHTABLE_VALUE zend_object*
+#define HASHTABLE_VALUE_CE(val) val->ce
 
 #define CREATE_HASHTABLE_VALUE(OBJ, WRAPPED_OBJ, OBJ_TYPE, OBJ_CLASS_ENTRY) \
   OBJ_TYPE* OBJ;                                                            \
@@ -357,35 +463,94 @@
   return *ce != NULL ? SUCCESS : FAILURE;
 }
 
+#define PHP_PROTO_RETVAL_ZVAL(value) ZVAL_COPY(return_value, value)
+
 #endif  // PHP_MAJOR_VERSION >= 7
 
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
+#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass)  \
+  zend_class_entry* old_scope = EG(scope); \
+  EG(scope) = klass;
+#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \
+  old_scope = EG(scope);                    \
+  EG(scope) = klass;
+#define PHP_PROTO_FAKE_SCOPE_END EG(scope) = old_scope;
+#else
+#define PHP_PROTO_FAKE_SCOPE_BEGIN(klass)       \
+  zend_class_entry* old_scope = EG(fake_scope); \
+  EG(fake_scope) = klass;
+#define PHP_PROTO_FAKE_SCOPE_RESTART(klass) \
+  old_scope = EG(fake_scope);               \
+  EG(fake_scope) = klass;
+#define PHP_PROTO_FAKE_SCOPE_END EG(fake_scope) = old_scope;
+#endif
+
+// Define PHP class
+#define DEFINE_PROTOBUF_INIT_CLASS(CLASSNAME, CAMELNAME, LOWERNAME) \
+  PHP_PROTO_INIT_CLASS_START(CLASSNAME, CAMELNAME, LOWERNAME)       \
+  PHP_PROTO_INIT_CLASS_END
+
+#define DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME)  \
+  PHP_PROTO_OBJECT_CREATE_START(NAME, LOWERNAME) \
+  LOWERNAME##_init_c_instance(intern TSRMLS_CC); \
+  PHP_PROTO_OBJECT_CREATE_END(NAME, LOWERNAME)
+
+#define DEFINE_PROTOBUF_FREE(CAMELNAME, LOWERNAME)  \
+  PHP_PROTO_OBJECT_FREE_START(CAMELNAME, LOWERNAME) \
+  LOWERNAME##_free_c(intern TSRMLS_CC);             \
+  PHP_PROTO_OBJECT_FREE_END
+
+#define DEFINE_PROTOBUF_DTOR(CAMELNAME, LOWERNAME)  \
+  PHP_PROTO_OBJECT_DTOR_START(CAMELNAME, LOWERNAME) \
+  PHP_PROTO_OBJECT_DTOR_END
+
+#define DEFINE_CLASS(NAME, LOWERNAME, string_name) \
+  zend_class_entry *LOWERNAME##_type;              \
+  zend_object_handlers *LOWERNAME##_handlers;      \
+  DEFINE_PROTOBUF_FREE(NAME, LOWERNAME)            \
+  DEFINE_PROTOBUF_DTOR(NAME, LOWERNAME)            \
+  DEFINE_PROTOBUF_CREATE(NAME, LOWERNAME)          \
+  DEFINE_PROTOBUF_INIT_CLASS(string_name, NAME, LOWERNAME)
+
 // -----------------------------------------------------------------------------
 // Forward Declaration
 // ----------------------------------------------------------------------------
 
+struct Any;
 struct DescriptorPool;
 struct Descriptor;
+struct Duration;
 struct EnumDescriptor;
+struct EnumValueDescriptor;
 struct FieldDescriptor;
+struct InternalDescriptorPool;
 struct MessageField;
 struct MessageHeader;
 struct MessageLayout;
 struct RepeatedField;
 struct RepeatedFieldIter;
 struct Map;
+struct MapIter;
 struct Oneof;
+struct Timestamp;
 
+typedef struct Any Any;
 typedef struct DescriptorPool DescriptorPool;
 typedef struct Descriptor Descriptor;
+typedef struct Duration Duration;
 typedef struct EnumDescriptor EnumDescriptor;
+typedef struct EnumValueDescriptor EnumValueDescriptor;
 typedef struct FieldDescriptor FieldDescriptor;
+typedef struct InternalDescriptorPool InternalDescriptorPool;
 typedef struct MessageField MessageField;
 typedef struct MessageHeader MessageHeader;
 typedef struct MessageLayout MessageLayout;
 typedef struct RepeatedField RepeatedField;
 typedef struct RepeatedFieldIter RepeatedFieldIter;
 typedef struct Map Map;
+typedef struct MapIter MapIter;
 typedef struct Oneof Oneof;
+typedef struct Timestamp Timestamp;
 
 // -----------------------------------------------------------------------------
 // Globals.
@@ -395,15 +560,22 @@
 ZEND_END_MODULE_GLOBALS(protobuf)
 
 // Init module and PHP classes.
+void any_init(TSRMLS_D);
 void descriptor_init(TSRMLS_D);
+void duration_init(TSRMLS_D);
 void enum_descriptor_init(TSRMLS_D);
 void descriptor_pool_init(TSRMLS_D);
+void internal_descriptor_pool_init(TSRMLS_D);
+void field_descriptor_init(TSRMLS_D);
 void gpb_type_init(TSRMLS_D);
 void map_field_init(TSRMLS_D);
+void map_field_iter_init(TSRMLS_D);
+void message_init(TSRMLS_D);
+void oneof_descriptor_init(TSRMLS_D);
 void repeated_field_init(TSRMLS_D);
 void repeated_field_iter_init(TSRMLS_D);
+void timestamp_init(TSRMLS_D);
 void util_init(TSRMLS_D);
-void message_init(TSRMLS_D);
 
 // Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
 // instances.
@@ -416,6 +588,11 @@
 PHP_PROTO_HASHTABLE_VALUE get_ce_obj(const void* ce);
 bool class_added(const void* ce);
 
+// Global map from message/enum's proto fully-qualified name to corresponding
+// wrapper Descriptor/EnumDescriptor instances.
+void add_proto_obj(const char* proto, PHP_PROTO_HASHTABLE_VALUE value);
+PHP_PROTO_HASHTABLE_VALUE get_proto_obj(const char* proto);
+
 extern zend_class_entry* map_field_type;
 extern zend_class_entry* repeated_field_type;
 
@@ -424,22 +601,38 @@
 // -----------------------------------------------------------------------------
 
 PHP_PROTO_WRAP_OBJECT_START(DescriptorPool)
+  InternalDescriptorPool* intern;
+PHP_PROTO_WRAP_OBJECT_END
+
+PHP_METHOD(DescriptorPool, getGeneratedPool);
+PHP_METHOD(DescriptorPool, getDescriptorByClassName);
+PHP_METHOD(DescriptorPool, getEnumDescriptorByClassName);
+
+PHP_PROTO_WRAP_OBJECT_START(InternalDescriptorPool)
   upb_symtab* symtab;
   HashTable* pending_list;
 PHP_PROTO_WRAP_OBJECT_END
 
-PHP_METHOD(DescriptorPool, getGeneratedPool);
-PHP_METHOD(DescriptorPool, internalAddGeneratedFile);
+PHP_METHOD(InternalDescriptorPool, getGeneratedPool);
+PHP_METHOD(InternalDescriptorPool, internalAddGeneratedFile);
+
+void internal_add_generated_file(const char* data, PHP_PROTO_SIZE data_len,
+                                 InternalDescriptorPool* pool TSRMLS_DC);
+void init_generated_pool_once(TSRMLS_D);
 
 // wrapper of generated pool
 #if PHP_MAJOR_VERSION < 7
 extern zval* generated_pool_php;
+extern zval* internal_generated_pool_php;
 void descriptor_pool_free(void* object TSRMLS_DC);
+void internal_descriptor_pool_free(void* object TSRMLS_DC);
 #else
 extern zend_object *generated_pool_php;
+extern zend_object *internal_generated_pool_php;
 void descriptor_pool_free(zend_object* object);
+void internal_descriptor_pool_free(zend_object* object);
 #endif
-extern DescriptorPool* generated_pool;  // The actual generated pool
+extern InternalDescriptorPool* generated_pool;  // The actual generated pool
 
 PHP_PROTO_WRAP_OBJECT_START(Descriptor)
   const upb_msgdef* msgdef;
@@ -453,6 +646,13 @@
   const upb_handlers* json_serialize_handlers_preserve;
 PHP_PROTO_WRAP_OBJECT_END
 
+PHP_METHOD(Descriptor, getClass);
+PHP_METHOD(Descriptor, getFullName);
+PHP_METHOD(Descriptor, getField);
+PHP_METHOD(Descriptor, getFieldCount);
+PHP_METHOD(Descriptor, getOneofDecl);
+PHP_METHOD(Descriptor, getOneofDeclCount);
+
 extern zend_class_entry* descriptor_type;
 
 void descriptor_name_set(Descriptor *desc, const char *name);
@@ -461,14 +661,36 @@
   const upb_fielddef* fielddef;
 PHP_PROTO_WRAP_OBJECT_END
 
+PHP_METHOD(FieldDescriptor, getName);
+PHP_METHOD(FieldDescriptor, getNumber);
+PHP_METHOD(FieldDescriptor, getLabel);
+PHP_METHOD(FieldDescriptor, getType);
+PHP_METHOD(FieldDescriptor, isMap);
+PHP_METHOD(FieldDescriptor, getEnumType);
+PHP_METHOD(FieldDescriptor, getMessageType);
+
+extern zend_class_entry* field_descriptor_type;
+
 PHP_PROTO_WRAP_OBJECT_START(EnumDescriptor)
   const upb_enumdef* enumdef;
   zend_class_entry* klass;  // begins as NULL
-  // VALUE module;  // begins as nil
 PHP_PROTO_WRAP_OBJECT_END
 
+PHP_METHOD(EnumDescriptor, getValue);
+PHP_METHOD(EnumDescriptor, getValueCount);
+
 extern zend_class_entry* enum_descriptor_type;
 
+PHP_PROTO_WRAP_OBJECT_START(EnumValueDescriptor)
+  const char* name;
+  int32_t number;
+PHP_PROTO_WRAP_OBJECT_END
+
+PHP_METHOD(EnumValueDescriptor, getName);
+PHP_METHOD(EnumValueDescriptor, getNumber);
+
+extern zend_class_entry* enum_value_descriptor_type;
+
 // -----------------------------------------------------------------------------
 // Message class creation.
 // -----------------------------------------------------------------------------
@@ -483,6 +705,7 @@
 void build_class_from_descriptor(
     PHP_PROTO_HASHTABLE_VALUE php_descriptor TSRMLS_DC);
 
+extern zend_class_entry* message_type;
 extern zend_object_handlers* message_handlers;
 
 // -----------------------------------------------------------------------------
@@ -560,7 +783,7 @@
 
 MessageLayout* create_layout(const upb_msgdef* msgdef);
 void layout_init(MessageLayout* layout, void* storage,
-                 CACHED_VALUE* properties_table PHP_PROTO_TSRMLS_DC);
+                 zend_object* object PHP_PROTO_TSRMLS_DC);
 zval* layout_get(MessageLayout* layout, const void* storage,
                  const upb_fielddef* field, CACHED_VALUE* cache TSRMLS_DC);
 void layout_set(MessageLayout* layout, MessageHeader* header,
@@ -570,6 +793,8 @@
 const char* layout_get_oneof_case(MessageLayout* layout, const void* storage,
                                   const upb_oneofdef* oneof TSRMLS_DC);
 void free_layout(MessageLayout* layout);
+void* slot_memory(MessageLayout* layout, const void* storage,
+                  const upb_fielddef* field);
 
 PHP_METHOD(Message, clear);
 PHP_METHOD(Message, mergeFrom);
@@ -590,11 +815,14 @@
 // This is called from the message class creation code.
 const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor *desc,
                                                      const void *owner);
+void serialize_to_string(zval* val, zval* return_value TSRMLS_DC);
+void merge_from_string(const char* data, int data_len, const Descriptor* desc,
+                       MessageHeader* msg);
 
 PHP_METHOD(Message, serializeToString);
 PHP_METHOD(Message, mergeFromString);
-PHP_METHOD(Message, jsonEncode);
-PHP_METHOD(Message, jsonDecode);
+PHP_METHOD(Message, serializeToJsonString);
+PHP_METHOD(Message, mergeFromJsonString);
 
 // -----------------------------------------------------------------------------
 // Type check / conversion.
@@ -637,7 +865,9 @@
 bool native_slot_set_by_array(upb_fieldtype_t type,
                               const zend_class_entry* klass, void* memory,
                               zval* value TSRMLS_DC);
-void native_slot_init(upb_fieldtype_t type, void* memory, void* cache);
+bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
+                            void* memory, zval* value TSRMLS_DC);
+void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache);
 // For each property, in order to avoid conversion between the zval object and
 // the actual data type during parsing/serialization, the containing message
 // object use the custom memory layout to store the actual data type for each
@@ -651,6 +881,10 @@
 // So we need to make a special method to handle that.
 void native_slot_get_by_array(upb_fieldtype_t type, const void* memory,
                      CACHED_VALUE* cache TSRMLS_DC);
+void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
+                                int length, CACHED_VALUE* cache TSRMLS_DC);
+void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
+                                  CACHED_VALUE* cache TSRMLS_DC);
 void native_slot_get_default(upb_fieldtype_t type,
                              CACHED_VALUE* cache TSRMLS_DC);
 
@@ -659,6 +893,7 @@
 // -----------------------------------------------------------------------------
 
 extern zend_object_handlers* map_field_handlers;
+extern zend_object_handlers* map_field_iter_handlers;
 
 PHP_PROTO_WRAP_OBJECT_START(Map)
   upb_fieldtype_t key_type;
@@ -667,10 +902,10 @@
   upb_strtable table;
 PHP_PROTO_WRAP_OBJECT_END
 
-typedef struct {
+PHP_PROTO_WRAP_OBJECT_START(MapIter)
   Map* self;
   upb_strtable_iter it;
-} MapIter;
+PHP_PROTO_WRAP_OBJECT_END
 
 void map_begin(zval* self, MapIter* iter TSRMLS_DC);
 void map_next(MapIter* iter);
@@ -709,6 +944,13 @@
 PHP_METHOD(MapField, offsetSet);
 PHP_METHOD(MapField, offsetUnset);
 PHP_METHOD(MapField, count);
+PHP_METHOD(MapField, getIterator);
+
+PHP_METHOD(MapFieldIter, rewind);
+PHP_METHOD(MapFieldIter, current);
+PHP_METHOD(MapFieldIter, key);
+PHP_METHOD(MapFieldIter, next);
+PHP_METHOD(MapFieldIter, valid);
 
 // -----------------------------------------------------------------------------
 // Repeated Field.
@@ -771,12 +1013,49 @@
   char value[NATIVE_SLOT_MAX_SIZE];
 PHP_PROTO_WRAP_OBJECT_END
 
+PHP_METHOD(Oneof, getName);
+PHP_METHOD(Oneof, getField);
+PHP_METHOD(Oneof, getFieldCount);
+
+extern zend_class_entry* oneof_descriptor_type;
+
 // Oneof case slot value to indicate that no oneof case is set. The value `0` is
 // safe because field numbers are used as case identifiers, and no field can
 // have a number of 0.
 #define ONEOF_CASE_NONE 0
 
 // -----------------------------------------------------------------------------
+// Well Known Type.
+// -----------------------------------------------------------------------------
+
+PHP_METHOD(Any, __construct);
+PHP_METHOD(Any, getTypeUrl);
+PHP_METHOD(Any, setTypeUrl);
+PHP_METHOD(Any, getValue);
+PHP_METHOD(Any, setValue);
+PHP_METHOD(Any, unpack);
+PHP_METHOD(Any, pack);
+PHP_METHOD(Any, is);
+
+PHP_METHOD(Duration, __construct);
+PHP_METHOD(Duration, getSeconds);
+PHP_METHOD(Duration, setSeconds);
+PHP_METHOD(Duration, getNanos);
+PHP_METHOD(Duration, setNanos);
+
+PHP_METHOD(Timestamp, __construct);
+PHP_METHOD(Timestamp, fromDateTime);
+PHP_METHOD(Timestamp, toDateTime);
+PHP_METHOD(Timestamp, getSeconds);
+PHP_METHOD(Timestamp, setSeconds);
+PHP_METHOD(Timestamp, getNanos);
+PHP_METHOD(Timestamp, setNanos);
+
+extern zend_class_entry* any_type;
+extern zend_class_entry* duration_type;
+extern zend_class_entry* timestamp_type;
+
+// -----------------------------------------------------------------------------
 // Upb.
 // -----------------------------------------------------------------------------
 
@@ -806,4 +1085,16 @@
                       .bucket.obj.object))
 #endif
 
+// Message handler
+static inline zval* php_proto_message_read_property(
+    zval* msg, zval* member PHP_PROTO_TSRMLS_DC) {
+#if PHP_MAJOR_VERSION < 7
+  return message_handlers->read_property(msg, member, BP_VAR_R,
+                                         NULL PHP_PROTO_TSRMLS_CC);
+#else
+  return message_handlers->read_property(msg, member, BP_VAR_R, NULL,
+                                         NULL PHP_PROTO_TSRMLS_CC);
+#endif
+}
+
 #endif  // __GOOGLE_PROTOBUF_PHP_PROTOBUF_H__
diff --git a/php/ext/google/protobuf/storage.c b/php/ext/google/protobuf/storage.c
index 6318f88..cc34dcf 100644
--- a/php/ext/google/protobuf/storage.c
+++ b/php/ext/google/protobuf/storage.c
@@ -199,6 +199,57 @@
         Z_ADDREF_P(value);
       }
 #else
+      DEREF(memory, zval*) = value;
+      ++GC_REFCOUNT(Z_OBJ_P(value));
+#endif
+      break;
+    }
+    default:
+      return native_slot_set(type, klass, memory, value TSRMLS_CC);
+  }
+  return true;
+}
+
+bool native_slot_set_by_map(upb_fieldtype_t type, const zend_class_entry* klass,
+                            void* memory, zval* value TSRMLS_DC) {
+  switch (type) {
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      if (!protobuf_convert_to_string(value)) {
+        return false;
+      }
+      if (type == UPB_TYPE_STRING &&
+          !is_structurally_valid_utf8(Z_STRVAL_P(value), Z_STRLEN_P(value))) {
+        zend_error(E_USER_ERROR, "Given string is not UTF8 encoded.");
+        return false;
+      }
+
+      // Handles repeated/map string field. Memory provided by
+      // RepeatedField/Map is not initialized.
+#if PHP_MAJOR_VERSION < 7
+      MAKE_STD_ZVAL(DEREF(memory, zval*));
+      PHP_PROTO_ZVAL_STRINGL(DEREF(memory, zval*), Z_STRVAL_P(value),
+                             Z_STRLEN_P(value), 1);
+#else
+      *(zend_string**)memory = zend_string_dup(Z_STR_P(value), 0);
+#endif
+      break;
+    }
+    case UPB_TYPE_MESSAGE: {
+      if (Z_TYPE_P(value) != IS_OBJECT) {
+        zend_error(E_USER_ERROR, "Given value is not message.");
+        return false;
+      }
+      if (Z_TYPE_P(value) == IS_OBJECT && klass != Z_OBJCE_P(value)) {
+        zend_error(E_USER_ERROR, "Given message does not have correct class.");
+        return false;
+      }
+#if PHP_MAJOR_VERSION < 7
+      if (EXPECTED(DEREF(memory, zval*) != value)) {
+        DEREF(memory, zval*) = value;
+        Z_ADDREF_P(value);
+      }
+#else
       DEREF(memory, zend_object*) = Z_OBJ_P(value);
       ++GC_REFCOUNT(Z_OBJ_P(value));
 #endif
@@ -210,7 +261,7 @@
   return true;
 }
 
-void native_slot_init(upb_fieldtype_t type, void* memory, void* cache) {
+void native_slot_init(upb_fieldtype_t type, void* memory, CACHED_VALUE* cache) {
   zval* tmp = NULL;
   switch (type) {
     case UPB_TYPE_FLOAT:
@@ -345,13 +396,45 @@
         ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
       }
 #else
+      ZVAL_COPY(CACHED_PTR_TO_ZVAL_PTR(cache), memory);
+#endif
+      return;
+    }
+    default:
+      native_slot_get(type, memory, cache TSRMLS_CC);
+  }
+}
+
+void native_slot_get_by_map_key(upb_fieldtype_t type, const void* memory,
+                                int length, CACHED_VALUE* cache TSRMLS_DC) {
+  switch (type) {
+    case UPB_TYPE_STRING:
+    case UPB_TYPE_BYTES: {
+      PHP_PROTO_ZVAL_STRINGL(CACHED_PTR_TO_ZVAL_PTR(cache), memory, length, 1);
+      return;
+    }
+    default:
+      native_slot_get(type, memory, cache TSRMLS_CC);
+  }
+}
+
+void native_slot_get_by_map_value(upb_fieldtype_t type, const void* memory,
+                              CACHED_VALUE* cache TSRMLS_DC) {
+  switch (type) {
+    case UPB_TYPE_MESSAGE: {
+#if PHP_MAJOR_VERSION < 7
+      zval* value = CACHED_PTR_TO_ZVAL_PTR((CACHED_VALUE*)memory);
+      if (EXPECTED(CACHED_PTR_TO_ZVAL_PTR(cache) != value)) {
+        ZVAL_ZVAL(CACHED_PTR_TO_ZVAL_PTR(cache), value, 1, 0);
+      }
+#else
       ++GC_REFCOUNT(*(zend_object**)memory);
       ZVAL_OBJ(cache, *(zend_object**)memory);
 #endif
       return;
     }
     default:
-      native_slot_get(type, memory, cache TSRMLS_CC);
+      native_slot_get_by_array(type, memory, cache TSRMLS_CC);
   }
 }
 
@@ -477,11 +560,6 @@
   return (offset + granularity - 1) & ~(granularity - 1);
 }
 
-static void* slot_memory(MessageLayout* layout, const void* storage,
-                         const upb_fielddef* field) {
-  return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
-}
-
 static uint32_t* slot_oneof_case(MessageLayout* layout, const void* storage,
                                  const upb_fielddef* field) {
   return (uint32_t*)(((uint8_t*)storage) +
@@ -493,6 +571,11 @@
   return layout->fields[upb_fielddef_index(field)].cache_index;
 }
 
+void* slot_memory(MessageLayout* layout, const void* storage,
+                         const upb_fielddef* field) {
+  return ((uint8_t*)storage) + layout->fields[upb_fielddef_index(field)].offset;
+}
+
 MessageLayout* create_layout(const upb_msgdef* msgdef) {
   MessageLayout* layout = ALLOC(MessageLayout);
   int nfields = upb_msgdef_numfields(msgdef);
@@ -500,6 +583,8 @@
   upb_msg_oneof_iter oit;
   size_t off = 0;
   int i = 0;
+  TSRMLS_FETCH();
+  Descriptor* desc = UNBOX_HASHTABLE_VALUE(Descriptor, get_def_obj(msgdef));
 
   layout->fields = ALLOC_N(MessageField, nfields);
 
@@ -526,7 +611,37 @@
     layout->fields[upb_fielddef_index(field)].offset = off;
     layout->fields[upb_fielddef_index(field)].case_offset =
         MESSAGE_FIELD_NO_CASE;
-    layout->fields[upb_fielddef_index(field)].cache_index = i++;
+
+    const char* fieldname = upb_fielddef_name(field);
+
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
+    zend_class_entry* old_scope = EG(scope);
+    EG(scope) = desc->klass;
+#else
+    zend_class_entry* old_scope = EG(fake_scope);
+    EG(fake_scope) = desc->klass;
+#endif
+
+#if PHP_MAJOR_VERSION < 7
+    zval member;
+    ZVAL_STRINGL(&member, fieldname, strlen(fieldname), 0);
+    zend_property_info* property_info =
+        zend_get_property_info(desc->klass, &member, true TSRMLS_CC);
+#else
+    zend_string* member = zend_string_init(fieldname, strlen(fieldname), 1);
+    zend_property_info* property_info =
+        zend_get_property_info(desc->klass, member, true);
+    zend_string_release(member);
+#endif
+
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
+    EG(scope) = old_scope;
+#else
+    EG(fake_scope) = old_scope;
+#endif
+
+    layout->fields[upb_fielddef_index(field)].cache_index =
+        property_info->offset;
     off += field_size;
   }
 
@@ -554,11 +669,40 @@
     // Align the offset .
     off = align_up_to( off, field_size);
     // Assign all fields in the oneof this same offset.
+    const char* oneofname = upb_oneofdef_name(oneof);
     for (upb_oneof_begin(&fit, oneof); !upb_oneof_done(&fit);
          upb_oneof_next(&fit)) {
       const upb_fielddef* field = upb_oneof_iter_field(&fit);
       layout->fields[upb_fielddef_index(field)].offset = off;
-      layout->fields[upb_fielddef_index(field)].cache_index = i;
+
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
+      zend_class_entry* old_scope = EG(scope);
+      EG(scope) = desc->klass;
+#else
+      zend_class_entry* old_scope = EG(fake_scope);
+      EG(fake_scope) = desc->klass;
+#endif
+
+#if PHP_MAJOR_VERSION < 7
+      zval member;
+      ZVAL_STRINGL(&member, oneofname, strlen(oneofname), 0);
+      zend_property_info* property_info =
+          zend_get_property_info(desc->klass, &member, true TSRMLS_CC);
+#else
+      zend_string* member = zend_string_init(oneofname, strlen(oneofname), 1);
+      zend_property_info* property_info =
+          zend_get_property_info(desc->klass, member, true);
+      zend_string_release(member);
+#endif
+
+#if PHP_MAJOR_VERSION < 7 || (PHP_MAJOR_VERSION == 7 && PHP_MINOR_VERSION == 0)
+      EG(scope) = old_scope;
+#else
+      EG(fake_scope) = old_scope;
+#endif
+
+      layout->fields[upb_fielddef_index(field)].cache_index =
+          property_info->offset;
     }
     i++;
     off += field_size;
@@ -597,7 +741,7 @@
 }
 
 void layout_init(MessageLayout* layout, void* storage,
-                 CACHED_VALUE* properties_table PHP_PROTO_TSRMLS_DC) {
+                 zend_object* object PHP_PROTO_TSRMLS_DC) {
   int i;
   upb_msg_field_iter it;
   for (upb_msg_field_begin(&it, layout->msgdef), i = 0; !upb_msg_field_done(&it);
@@ -606,7 +750,7 @@
     void* memory = slot_memory(layout, storage, field);
     uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
     int cache_index = slot_property_cache(layout, storage, field);
-    CACHED_VALUE* property_ptr = &properties_table[cache_index];
+    CACHED_VALUE* property_ptr = OBJ_PROP(object, cache_index);
 
     if (upb_fielddef_containingoneof(field)) {
       memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
@@ -696,7 +840,7 @@
             header->descriptor->layout->fields[upb_fielddef_index(field)]
                 .cache_index;
         DEREF(memory, CACHED_VALUE*) =
-            &(header->std.properties_table)[property_cache_index];
+            OBJ_PROP(&header->std, property_cache_index);
         memory = DEREF(memory, CACHED_VALUE*);
         break;
       }
@@ -731,7 +875,7 @@
   }
 }
 
-static native_slot_merge(const upb_fielddef* field, const void* from_memory,
+static void native_slot_merge(const upb_fielddef* field, const void* from_memory,
                          void* to_memory PHP_PROTO_TSRMLS_DC) {
   upb_fieldtype_t type = upb_fielddef_type(field);
   zend_class_entry* ce = NULL;
@@ -788,7 +932,7 @@
   }
 }
 
-static native_slot_merge_by_array(const upb_fielddef* field, const void* from_memory,
+static void native_slot_merge_by_array(const upb_fielddef* field, const void* from_memory,
                          void* to_memory PHP_PROTO_TSRMLS_DC) {
   upb_fieldtype_t type = upb_fielddef_type(field);
   switch (type) {
@@ -863,7 +1007,7 @@
           int property_cache_index =
               layout->fields[upb_fielddef_index(field)].cache_index;
           DEREF(to_memory, CACHED_VALUE*) =
-              &(to->std.properties_table)[property_cache_index];
+              OBJ_PROP(&to->std, property_cache_index);
           break;
         }
         default:
@@ -921,8 +1065,18 @@
           void* to_memory =
               ALLOC_N(char, native_slot_size(upb_fielddef_type(field)));
           memset(to_memory, 0, native_slot_size(upb_fielddef_type(field)));
-          php_proto_zend_hash_index_find(PHP_PROTO_HASH_OF(from_array->array),
-                                         j, (void**)&from_memory);
+
+          if (to_array->type == UPB_TYPE_MESSAGE) {
+            php_proto_zend_hash_index_find_zval(
+                PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
+#if PHP_MAJOR_VERSION >= 7
+            from_memory = &Z_OBJ_P((zval*)from_memory);
+#endif
+          } else {
+            php_proto_zend_hash_index_find_mem(
+                PHP_PROTO_HASH_OF(from_array->array), j, (void**)&from_memory);
+          }
+
           native_slot_merge_by_array(field, from_memory,
                                      to_memory PHP_PROTO_TSRMLS_CC);
           repeated_field_push_native(to_array, to_memory);
diff --git a/php/ext/google/protobuf/upb.c b/php/ext/google/protobuf/upb.c
index 7098301..d701dcb 100644
--- a/php/ext/google/protobuf/upb.c
+++ b/php/ext/google/protobuf/upb.c
@@ -1859,6 +1859,7 @@
   upb_gfree((void*)f->name);
   upb_gfree((void*)f->package);
   upb_gfree((void*)f->phpprefix);
+  upb_gfree((void*)f->phpnamespace);
   upb_gfree(f);
 }
 
@@ -1874,6 +1875,7 @@
   f->package = NULL;
   f->name = NULL;
   f->phpprefix = NULL;
+  f->phpnamespace = NULL;
   f->syntax = UPB_SYNTAX_PROTO2;
 
   if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl,
@@ -1912,6 +1914,10 @@
   return f->phpprefix;
 }
 
+const char *upb_filedef_phpnamespace(const upb_filedef *f) {
+  return f->phpnamespace;
+}
+
 upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
   return f->syntax;
 }
@@ -1980,6 +1986,18 @@
   return true;
 }
 
+bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace,
+                                 upb_status *s) {
+  phpnamespace = upb_gstrdup(phpnamespace);
+  if (!phpnamespace) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+  upb_gfree((void*)f->phpnamespace);
+  f->phpnamespace = phpnamespace;
+  return true;
+}
+
 bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax,
                            upb_status *s) {
   UPB_UNUSED(s);
@@ -2290,6 +2308,9 @@
   bool ret;
 
   n = upb_filedef_defcount(file);
+  if (n == 0) {
+    return true;
+  }
   defs = upb_gmalloc(sizeof(*defs) * n);
 
   if (defs == NULL) {
@@ -6419,14 +6440,14 @@
 
 
 static const upb_msgdef msgs[22];
-static const upb_fielddef fields[106];
+static const upb_fielddef fields[107];
 static const upb_enumdef enums[5];
 static const upb_tabent strentries[236];
 static const upb_tabent intentries[18];
-static const upb_tabval arrays[186];
+static const upb_tabval arrays[187];
 
 #ifdef UPB_DEBUG_REFS
-static upb_inttable reftables[266];
+static upb_inttable reftables[268];
 #endif
 
 static const upb_msgdef msgs[22] = {
@@ -6441,20 +6462,20 @@
   UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]),
   UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]),
   UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]),
-  UPB_MSGDEF_INIT("google.protobuf.FileOptions", 34, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 41, 16), UPB_STRTABLE_INIT(17, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]),
-  UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[109], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]),
-  UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[117], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]),
-  UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[124], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]),
-  UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[125], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]),
-  UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[127], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]),
-  UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[131], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]),
-  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[132], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]),
-  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[134], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]),
-  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[141], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]),
-  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[150], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]),
+  UPB_MSGDEF_INIT("google.protobuf.FileOptions", 37, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]),
+  UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]),
+  UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]),
 };
 
-static const upb_fielddef fields[106] = {
+static const upb_fielddef fields[107] = {
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]),
@@ -6505,77 +6526,78 @@
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[142], &reftables[143]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[144], &reftables[145]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[146], &reftables[147]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[148], &reftables[149]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[144], &reftables[145]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[146], &reftables[147]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[148], &reftables[149]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[150], &reftables[151]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[152], &reftables[153]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[154], &reftables[155]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[152], &reftables[153]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[154], &reftables[155]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[156], &reftables[157]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[158], &reftables[159]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[158], &reftables[159]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[168], &reftables[169]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[170], &reftables[171]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[168], &reftables[169]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[170], &reftables[171]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[180], &reftables[181]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[182], &reftables[183]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[184], &reftables[185]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[186], &reftables[187]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[188], &reftables[189]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[190], &reftables[191]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[192], &reftables[193]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[184], &reftables[185]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[186], &reftables[187]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[190], &reftables[191]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[192], &reftables[193]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_class_prefix", 40, &msgs[11], NULL, 31, 16, {0},&reftables[202], &reftables[203]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[204], &reftables[205]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[206], &reftables[207]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[208], &reftables[209]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[210], &reftables[211]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[212], &reftables[213]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[214], &reftables[215]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[216], &reftables[217]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[218], &reftables[219]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[220], &reftables[221]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[222], &reftables[223]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[224], &reftables[225]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[226], &reftables[227]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[228], &reftables[229]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[230], &reftables[231]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[232], &reftables[233]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[234], &reftables[235]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[236], &reftables[237]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_namespace", 41, &msgs[11], NULL, 34, 17, {0},&reftables[204], &reftables[205]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[206], &reftables[207]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[208], &reftables[209]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[210], &reftables[211]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[212], &reftables[213]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[214], &reftables[215]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[216], &reftables[217]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[218], &reftables[219]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[220], &reftables[221]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[222], &reftables[223]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[224], &reftables[225]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[226], &reftables[227]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[228], &reftables[229]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[230], &reftables[231]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[232], &reftables[233]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[234], &reftables[235]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[236], &reftables[237]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[248], &reftables[249]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[250], &reftables[251]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[252], &reftables[253]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[254], &reftables[255]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[248], &reftables[249]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[250], &reftables[251]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[252], &reftables[253]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[254], &reftables[255]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[256], &reftables[257]),
 };
 
 static const upb_enumdef enums[5] = {
-  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[153], 4, 3), 0, &reftables[256], &reftables[257]),
-  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[157], 19, 18), 0, &reftables[258], &reftables[259]),
-  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[176], 3, 3), 0, &reftables[260], &reftables[261]),
-  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[179], 3, 3), 0, &reftables[262], &reftables[263]),
-  UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[182], 4, 3), 0, &reftables[264], &reftables[265]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[154], 4, 3), 0, &reftables[258], &reftables[259]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[158], 19, 18), 0, &reftables[260], &reftables[261]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[262], &reftables[263]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 3, 3), 0, &reftables[264], &reftables[265]),
+  UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[183], 4, 3), 0, &reftables[266], &reftables[267]),
 };
 
 static const upb_tabent strentries[236] = {
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6584,31 +6606,31 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), &strentries[13]},
-  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[90]), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
   {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[90]), NULL},
   {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), &strentries[26]},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), &strentries[26]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), &strentries[34]},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), &strentries[34]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6620,17 +6642,17 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &strentries[53]},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), &strentries[53]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
-  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[94]), &strentries[50]},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[95]), &strentries[50]},
   {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[105]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6645,21 +6667,21 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL},
-  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[105]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[106]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[87]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[87]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[92]), NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[93]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
   {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), &strentries[86]},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL},
-  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[81]), &strentries[85]},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[82]), &strentries[85]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6680,17 +6702,17 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "php_namespace"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[113]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]},
-  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
   {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]},
   {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "php_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
   {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]},
-  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[82]), NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL},
   {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]},
@@ -6706,22 +6728,22 @@
   {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
-  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), &strentries[150]},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]},
   {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
   {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[149]},
   {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
@@ -6735,9 +6757,9 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[88]), &strentries[167]},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[89]), &strentries[167]},
   {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]},
-  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[93]), NULL},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]},
   {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
@@ -6753,9 +6775,9 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[80]), NULL},
+  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
-  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[91]), &strentries[182]},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[92]), &strentries[182]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
@@ -6812,66 +6834,66 @@
 
 static const upb_tabent intentries[18] = {
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
-  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
 };
 
-static const upb_tabval arrays[186] = {
+static const upb_tabval arrays[187] = {
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[50]),
+  UPB_TABVALUE_PTR_INIT(&fields[57]),
   UPB_TABVALUE_PTR_INIT(&fields[25]),
   UPB_TABVALUE_PTR_INIT(&fields[60]),
   UPB_TABVALUE_PTR_INIT(&fields[20]),
   UPB_TABVALUE_PTR_INIT(&fields[24]),
   UPB_TABVALUE_PTR_INIT(&fields[22]),
-  UPB_TABVALUE_PTR_INIT(&fields[69]),
+  UPB_TABVALUE_PTR_INIT(&fields[68]),
   UPB_TABVALUE_PTR_INIT(&fields[65]),
+  UPB_TABVALUE_PTR_INIT(&fields[85]),
   UPB_TABVALUE_PTR_INIT(&fields[84]),
-  UPB_TABVALUE_PTR_INIT(&fields[83]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[90]),
+  UPB_TABVALUE_PTR_INIT(&fields[91]),
   UPB_TABVALUE_PTR_INIT(&fields[18]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[89]),
+  UPB_TABVALUE_PTR_INIT(&fields[90]),
   UPB_TABVALUE_PTR_INIT(&fields[17]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[54]),
-  UPB_TABVALUE_PTR_INIT(&fields[103]),
-  UPB_TABVALUE_PTR_INIT(&fields[74]),
+  UPB_TABVALUE_PTR_INIT(&fields[52]),
+  UPB_TABVALUE_PTR_INIT(&fields[104]),
+  UPB_TABVALUE_PTR_INIT(&fields[73]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[1]),
   UPB_TABVALUE_PTR_INIT(&fields[14]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[51]),
-  UPB_TABVALUE_PTR_INIT(&fields[62]),
-  UPB_TABVALUE_PTR_INIT(&fields[72]),
+  UPB_TABVALUE_PTR_INIT(&fields[50]),
+  UPB_TABVALUE_PTR_INIT(&fields[63]),
+  UPB_TABVALUE_PTR_INIT(&fields[74]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[13]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[56]),
   UPB_TABVALUE_PTR_INIT(&fields[21]),
-  UPB_TABVALUE_PTR_INIT(&fields[63]),
+  UPB_TABVALUE_PTR_INIT(&fields[62]),
   UPB_TABVALUE_PTR_INIT(&fields[40]),
-  UPB_TABVALUE_PTR_INIT(&fields[94]),
   UPB_TABVALUE_PTR_INIT(&fields[95]),
+  UPB_TABVALUE_PTR_INIT(&fields[96]),
   UPB_TABVALUE_PTR_INIT(&fields[7]),
-  UPB_TABVALUE_PTR_INIT(&fields[71]),
+  UPB_TABVALUE_PTR_INIT(&fields[70]),
   UPB_TABVALUE_PTR_INIT(&fields[66]),
   UPB_TABVALUE_PTR_INIT(&fields[38]),
   UPB_TABVALUE_EMPTY_INIT,
@@ -6884,20 +6906,20 @@
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[104]),
+  UPB_TABVALUE_PTR_INIT(&fields[105]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[57]),
+  UPB_TABVALUE_PTR_INIT(&fields[51]),
   UPB_TABVALUE_PTR_INIT(&fields[76]),
   UPB_TABVALUE_PTR_INIT(&fields[8]),
   UPB_TABVALUE_PTR_INIT(&fields[47]),
   UPB_TABVALUE_PTR_INIT(&fields[19]),
-  UPB_TABVALUE_PTR_INIT(&fields[86]),
-  UPB_TABVALUE_PTR_INIT(&fields[23]),
-  UPB_TABVALUE_PTR_INIT(&fields[68]),
   UPB_TABVALUE_PTR_INIT(&fields[87]),
-  UPB_TABVALUE_PTR_INIT(&fields[81]),
-  UPB_TABVALUE_PTR_INIT(&fields[105]),
-  UPB_TABVALUE_PTR_INIT(&fields[92]),
+  UPB_TABVALUE_PTR_INIT(&fields[23]),
+  UPB_TABVALUE_PTR_INIT(&fields[69]),
+  UPB_TABVALUE_PTR_INIT(&fields[88]),
+  UPB_TABVALUE_PTR_INIT(&fields[82]),
+  UPB_TABVALUE_PTR_INIT(&fields[106]),
+  UPB_TABVALUE_PTR_INIT(&fields[93]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[26]),
   UPB_TABVALUE_EMPTY_INIT,
@@ -6918,7 +6940,7 @@
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[3]),
   UPB_TABVALUE_PTR_INIT(&fields[32]),
-  UPB_TABVALUE_PTR_INIT(&fields[82]),
+  UPB_TABVALUE_PTR_INIT(&fields[83]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[31]),
   UPB_TABVALUE_EMPTY_INIT,
@@ -6941,6 +6963,7 @@
   UPB_TABVALUE_PTR_INIT(&fields[37]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[79]),
+  UPB_TABVALUE_PTR_INIT(&fields[80]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[46]),
   UPB_TABVALUE_PTR_INIT(&fields[61]),
@@ -6950,37 +6973,37 @@
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[45]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[52]),
+  UPB_TABVALUE_PTR_INIT(&fields[55]),
   UPB_TABVALUE_PTR_INIT(&fields[29]),
   UPB_TABVALUE_PTR_INIT(&fields[75]),
-  UPB_TABVALUE_PTR_INIT(&fields[70]),
+  UPB_TABVALUE_PTR_INIT(&fields[71]),
   UPB_TABVALUE_PTR_INIT(&fields[4]),
-  UPB_TABVALUE_PTR_INIT(&fields[85]),
+  UPB_TABVALUE_PTR_INIT(&fields[86]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[55]),
+  UPB_TABVALUE_PTR_INIT(&fields[54]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[53]),
   UPB_TABVALUE_PTR_INIT(&fields[48]),
-  UPB_TABVALUE_PTR_INIT(&fields[73]),
+  UPB_TABVALUE_PTR_INIT(&fields[72]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[44]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[78]),
-  UPB_TABVALUE_PTR_INIT(&fields[88]),
+  UPB_TABVALUE_PTR_INIT(&fields[89]),
   UPB_TABVALUE_PTR_INIT(&fields[42]),
-  UPB_TABVALUE_PTR_INIT(&fields[93]),
+  UPB_TABVALUE_PTR_INIT(&fields[94]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[43]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[49]),
   UPB_TABVALUE_PTR_INIT(&fields[28]),
-  UPB_TABVALUE_PTR_INIT(&fields[80]),
+  UPB_TABVALUE_PTR_INIT(&fields[81]),
   UPB_TABVALUE_PTR_INIT(&fields[59]),
   UPB_TABVALUE_PTR_INIT(&fields[16]),
-  UPB_TABVALUE_PTR_INIT(&fields[91]),
+  UPB_TABVALUE_PTR_INIT(&fields[92]),
   UPB_TABVALUE_PTR_INIT(&fields[0]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[58]),
@@ -7021,7 +7044,9 @@
 };
 
 #ifdef UPB_DEBUG_REFS
-static upb_inttable reftables[266] = {
+static upb_inttable reftables[268] = {
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
   UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
   UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
   UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
@@ -7565,6 +7590,34 @@
   return n;
 }
 
+static void *file_startphpnamespace(void *closure, const void *hd,
+                                    size_t size_hint) {
+  upb_descreader *r = closure;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(size_hint);
+
+  ok = upb_filedef_setphpnamespace(r->file, "", NULL);
+  UPB_ASSERT(ok);
+  return closure;
+}
+
+static size_t file_onphpnamespace(void *closure, const void *hd,
+                                  const char *buf, size_t n,
+                                  const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *php_namespace;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  php_namespace = upb_gstrndup(buf, n);
+  ok = upb_filedef_setphpnamespace(r->file, php_namespace, NULL);
+  upb_gfree(php_namespace);
+  UPB_ASSERT(ok);
+  return n;
+}
+
 static size_t file_onphpprefix(void *closure, const void *hd, const char *buf,
                              size_t n, const upb_bufhandle *handle) {
   upb_descreader *r = closure;
@@ -8109,6 +8162,10 @@
   } else if (upbdefs_google_protobuf_FileOptions_is(m)) {
     upb_handlers_setstring(h, F(FileOptions, php_class_prefix),
                            &file_onphpprefix, NULL);
+    upb_handlers_setstartstr(h, F(FileOptions, php_namespace),
+                             &file_startphpnamespace, NULL);
+    upb_handlers_setstring(h, F(FileOptions, php_namespace),
+                           &file_onphpnamespace, NULL);
   }
 
   UPB_ASSERT(upb_ok(upb_handlers_status(h)));
@@ -11271,57 +11328,6 @@
   return r;
 }
 
-/* Given an encoded varint v, returns an integer with a single bit set that
- * indicates the end of the varint.  Subtracting one from this value will
- * yield a mask that leaves only bits that are part of the varint.  Returns
- * 0 if the varint is unterminated. */
-static uint64_t upb_get_vstopbit(uint64_t v) {
-  uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL;
-  return ~cbits & (cbits+1);
-}
-
-/* A branchless decoder.  Credit to Pascal Massimino for the bit-twiddling. */
-upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) {
-  uint64_t b;
-  uint64_t stop_bit;
-  upb_decoderet my_r;
-  memcpy(&b, r.p, sizeof(b));
-  stop_bit = upb_get_vstopbit(b);
-  b =  (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1);
-  b +=       b & 0x007f007f007f007fULL;
-  b +=  3 * (b & 0x0000ffff0000ffffULL);
-  b += 15 * (b & 0x00000000ffffffffULL);
-  if (stop_bit == 0) {
-    /* Error: unterminated varint. */
-    upb_decoderet err_r = {(void*)0, 0};
-    return err_r;
-  }
-  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
-                            r.val | (b << 7));
-  return my_r;
-}
-
-/* A branchless decoder.  Credit to Daniel Wright for the bit-twiddling. */
-upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
-  uint64_t b;
-  uint64_t stop_bit;
-  upb_decoderet my_r;
-  memcpy(&b, r.p, sizeof(b));
-  stop_bit = upb_get_vstopbit(b);
-  b &= (stop_bit - 1);
-  b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL);
-  b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL);
-  b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL);
-  if (stop_bit == 0) {
-    /* Error: unterminated varint. */
-    upb_decoderet err_r = {(void*)0, 0};
-    return err_r;
-  }
-  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
-                            r.val | (b << 14));
-  return my_r;
-}
-
 #line 1 "upb/json/parser.rl"
 /*
 ** upb::json::Parser (upb_json_parser)
diff --git a/php/ext/google/protobuf/upb.h b/php/ext/google/protobuf/upb.h
index 78f255f..4b51275 100644
--- a/php/ext/google/protobuf/upb.h
+++ b/php/ext/google/protobuf/upb.h
@@ -2973,10 +2973,16 @@
   bool set_package(const char* package, Status* s);
 
   /* Sets the php class prefix which is prepended to all php generated classes
-   / from this .proto. Default is empty. */
+   * from this .proto. Default is empty. */
   const char* phpprefix() const;
   bool set_phpprefix(const char* phpprefix, Status* s);
 
+  /* Use this option to change the namespace of php generated classes. Default
+   * is empty. When this option is empty, the package name will be used for
+   * determining the namespace. */
+  const char* phpnamespace() const;
+  bool set_phpnamespace(const char* phpnamespace, Status* s);
+
   /* Syntax for the file.  Defaults to proto2. */
   upb_syntax_t syntax() const;
   void set_syntax(upb_syntax_t syntax);
@@ -3031,6 +3037,7 @@
 const char *upb_filedef_name(const upb_filedef *f);
 const char *upb_filedef_package(const upb_filedef *f);
 const char *upb_filedef_phpprefix(const upb_filedef *f);
+const char *upb_filedef_phpnamespace(const upb_filedef *f);
 upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
 size_t upb_filedef_defcount(const upb_filedef *f);
 size_t upb_filedef_depcount(const upb_filedef *f);
@@ -3042,6 +3049,8 @@
 bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s);
 bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix,
                               upb_status *s);
+bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace,
+                                 upb_status *s);
 bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, upb_status *s);
 
 bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
@@ -3806,6 +3815,12 @@
 inline bool FileDef::set_phpprefix(const char* phpprefix, Status* s) {
   return upb_filedef_setphpprefix(this, phpprefix, s);
 }
+inline const char* FileDef::phpnamespace() const {
+  return upb_filedef_phpnamespace(this);
+}
+inline bool FileDef::set_phpnamespace(const char* phpnamespace, Status* s) {
+  return upb_filedef_setphpnamespace(this, phpnamespace, s);
+}
 inline int FileDef::def_count() const {
   return upb_filedef_defcount(this);
 }
@@ -4021,6 +4036,7 @@
   const char *name;
   const char *package;
   const char *phpprefix;
+  const char *phpnamespace;
   upb_syntax_t syntax;
 
   upb_inttable defs;
@@ -7228,6 +7244,7 @@
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_objc_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 36); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_optimize_for(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 40); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 41); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 18); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 999); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 3); }
@@ -8326,16 +8343,8 @@
   return ret;
 }
 
-/* Four functions for decoding a varint of at most eight bytes.  They are all
- * functionally identical, but are implemented in different ways and likely have
- * different performance profiles.  We keep them around for performance testing.
- *
- * Note that these functions may not read byte-by-byte, so they must not be used
- * unless there are at least eight bytes left in the buffer! */
 upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
 upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_wright(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r);
 
 /* Template for a function that checks the first two bytes with branching
  * and dispatches 2-10 bytes with a separate function.  Note that this may read
@@ -8360,8 +8369,6 @@
 
 UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
 UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
-UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright)
-UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino)
 #undef UPB_VARINT_DECODER_CHECK2
 
 /* Our canonical functions for decoding varints, based on the currently
@@ -8373,10 +8380,6 @@
     return upb_vdecode_check2_branch32(p);
 }
 
-UPB_INLINE upb_decoderet upb_vdecode_max8_fast(upb_decoderet r) {
-  return upb_vdecode_max8_massimino(r);
-}
-
 
 /* Encoding *******************************************************************/
 
diff --git a/php/phpunit.xml b/php/phpunit.xml
index 0191a60..d707703 100644
--- a/php/phpunit.xml
+++ b/php/phpunit.xml
@@ -7,8 +7,11 @@
       <file>tests/array_test.php</file>
       <file>tests/encode_decode_test.php</file>
       <file>tests/generated_class_test.php</file>
+      <file>tests/generated_phpdoc_test.php</file>
       <file>tests/map_field_test.php</file>
       <file>tests/well_known_test.php</file>
+      <file>tests/descriptors_test.php</file>
+      <file>tests/generated_service_test.php</file>
     </testsuite>
   </testsuites>
 </phpunit>
diff --git a/php/src/GPBMetadata/Google/Protobuf/Any.php b/php/src/GPBMetadata/Google/Protobuf/Any.php
new file mode 100644
index 0000000..22cc250
--- /dev/null
+++ b/php/src/GPBMetadata/Google/Protobuf/Any.php
@@ -0,0 +1,30 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/any.proto
+
+namespace GPBMetadata\Google\Protobuf;
+
+class Any
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0acd010a19676f6f676c652f70726f746f6275662f616e792e70726f746f" .
+            "120f676f6f676c652e70726f746f62756622260a03416e7912100a087479" .
+            "70655f75726c180120012809120d0a0576616c756518022001280c426f0a" .
+            "13636f6d2e676f6f676c652e70726f746f6275664208416e7950726f746f" .
+            "50015a256769746875622e636f6d2f676f6c616e672f70726f746f627566" .
+            "2f7074797065732f616e79a20203475042aa021e476f6f676c652e50726f" .
+            "746f6275662e57656c6c4b6e6f776e5479706573620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/php/src/GPBMetadata/Google/Protobuf/Duration.php b/php/src/GPBMetadata/Google/Protobuf/Duration.php
new file mode 100644
index 0000000..b1c85ad
--- /dev/null
+++ b/php/src/GPBMetadata/Google/Protobuf/Duration.php
@@ -0,0 +1,31 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/duration.proto
+
+namespace GPBMetadata\Google\Protobuf;
+
+class Duration
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0ae3010a1e676f6f676c652f70726f746f6275662f6475726174696f6e2e" .
+            "70726f746f120f676f6f676c652e70726f746f627566222a0a0844757261" .
+            "74696f6e120f0a077365636f6e6473180120012803120d0a056e616e6f73" .
+            "180220012805427c0a13636f6d2e676f6f676c652e70726f746f62756642" .
+            "0d4475726174696f6e50726f746f50015a2a6769746875622e636f6d2f67" .
+            "6f6c616e672f70726f746f6275662f7074797065732f6475726174696f6e" .
+            "f80101a20203475042aa021e476f6f676c652e50726f746f6275662e5765" .
+            "6c6c4b6e6f776e5479706573620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
index 1b6b3d6..60722d0 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
@@ -49,6 +49,7 @@
         $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
+            ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 3, 'google.protobuf.internal.ExtensionRangeOptions')
             ->finalizeToPool();
 
         $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class)
@@ -56,6 +57,10 @@
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->finalizeToPool();
 
+        $pool->addMessage('google.protobuf.internal.ExtensionRangeOptions', \Google\Protobuf\Internal\ExtensionRangeOptions::class)
+            ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
+            ->finalizeToPool();
+
         $pool->addMessage('google.protobuf.internal.FieldDescriptorProto', \Google\Protobuf\Internal\FieldDescriptorProto::class)
             ->optional('name', \Google\Protobuf\Internal\GPBType::STRING, 1)
             ->optional('number', \Google\Protobuf\Internal\GPBType::INT32, 3)
@@ -139,12 +144,14 @@
             ->optional('cc_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 16)
             ->optional('java_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 17)
             ->optional('py_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 18)
+            ->optional('php_generic_services', \Google\Protobuf\Internal\GPBType::BOOL, 19)
             ->optional('deprecated', \Google\Protobuf\Internal\GPBType::BOOL, 23)
             ->optional('cc_enable_arenas', \Google\Protobuf\Internal\GPBType::BOOL, 31)
             ->optional('objc_class_prefix', \Google\Protobuf\Internal\GPBType::STRING, 36)
             ->optional('csharp_namespace', \Google\Protobuf\Internal\GPBType::STRING, 37)
             ->optional('swift_prefix', \Google\Protobuf\Internal\GPBType::STRING, 39)
             ->optional('php_class_prefix', \Google\Protobuf\Internal\GPBType::STRING, 40)
+            ->optional('php_namespace', \Google\Protobuf\Internal\GPBType::STRING, 41)
             ->repeated('uninterpreted_option', \Google\Protobuf\Internal\GPBType::MESSAGE, 999, 'google.protobuf.internal.UninterpretedOption')
             ->finalizeToPool();
 
diff --git a/php/src/GPBMetadata/Google/Protobuf/Timestamp.php b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php
new file mode 100644
index 0000000..373665c
--- /dev/null
+++ b/php/src/GPBMetadata/Google/Protobuf/Timestamp.php
@@ -0,0 +1,31 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/timestamp.proto
+
+namespace GPBMetadata\Google\Protobuf;
+
+class Timestamp
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0ae7010a1f676f6f676c652f70726f746f6275662f74696d657374616d70" .
+            "2e70726f746f120f676f6f676c652e70726f746f627566222b0a0954696d" .
+            "657374616d70120f0a077365636f6e6473180120012803120d0a056e616e" .
+            "6f73180220012805427e0a13636f6d2e676f6f676c652e70726f746f6275" .
+            "66420e54696d657374616d7050726f746f50015a2b6769746875622e636f" .
+            "6d2f676f6c616e672f70726f746f6275662f7074797065732f74696d6573" .
+            "74616d70f80101a20203475042aa021e476f6f676c652e50726f746f6275" .
+            "662e57656c6c4b6e6f776e5479706573620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/php/src/Google/Protobuf/Any.php b/php/src/Google/Protobuf/Any.php
new file mode 100644
index 0000000..a8ce431
--- /dev/null
+++ b/php/src/Google/Protobuf/Any.php
@@ -0,0 +1,274 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/any.proto
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\DescriptorPool;
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\GPBUtil;
+use Google\Protobuf\Internal\Message;
+use Google\Protobuf\Internal\RepeatedField;
+
+/**
+ * `Any` contains an arbitrary serialized protocol buffer message along with a
+ * URL that describes the type of the serialized message.
+ * Protobuf library provides support to pack/unpack Any values in the form
+ * of utility functions or additional generated methods of the Any type.
+ * Example 1: Pack and unpack a message in C++.
+ *     Foo foo = ...;
+ *     Any any;
+ *     any.PackFrom(foo);
+ *     ...
+ *     if (any.UnpackTo(&foo)) {
+ *       ...
+ *     }
+ * Example 2: Pack and unpack a message in Java.
+ *     Foo foo = ...;
+ *     Any any = Any.pack(foo);
+ *     ...
+ *     if (any.is(Foo.class)) {
+ *       foo = any.unpack(Foo.class);
+ *     }
+ *  Example 3: Pack and unpack a message in Python.
+ *     foo = Foo(...)
+ *     any = Any()
+ *     any.Pack(foo)
+ *     ...
+ *     if any.Is(Foo.DESCRIPTOR):
+ *       any.Unpack(foo)
+ *       ...
+ * The pack methods provided by protobuf library will by default use
+ * 'type.googleapis.com/full.type.name' as the type URL and the unpack
+ * methods only use the fully qualified type name after the last '/'
+ * in the type URL, for example "foo.bar.com/x/y.z" will yield type
+ * name "y.z".
+ * JSON
+ * ====
+ * The JSON representation of an `Any` value uses the regular
+ * representation of the deserialized, embedded message, with an
+ * additional field `&#64;type` which contains the type URL. Example:
+ *     package google.profile;
+ *     message Person {
+ *       string first_name = 1;
+ *       string last_name = 2;
+ *     }
+ *     {
+ *       "&#64;type": "type.googleapis.com/google.profile.Person",
+ *       "firstName": <string>,
+ *       "lastName": <string>
+ *     }
+ * If the embedded message type is well-known and has a custom JSON
+ * representation, that representation will be embedded adding a field
+ * `value` which holds the custom JSON in addition to the `&#64;type`
+ * field. Example (for message [google.protobuf.Duration][]):
+ *     {
+ *       "&#64;type": "type.googleapis.com/google.protobuf.Duration",
+ *       "value": "1.212s"
+ *     }
+ *
+ * Generated from protobuf message <code>google.protobuf.Any</code>
+ */
+class Any extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * A URL/resource name whose content describes the type of the
+     * serialized protocol buffer message.
+     * For URLs which use the scheme `http`, `https`, or no scheme, the
+     * following restrictions and interpretations apply:
+     * * If no scheme is provided, `https` is assumed.
+     * * The last segment of the URL's path must represent the fully
+     *   qualified name of the type (as in `path/google.protobuf.Duration`).
+     *   The name should be in a canonical form (e.g., leading "." is
+     *   not accepted).
+     * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+     *   value in binary format, or produce an error.
+     * * Applications are allowed to cache lookup results based on the
+     *   URL, or have them precompiled into a binary to avoid any
+     *   lookup. Therefore, binary compatibility needs to be preserved
+     *   on changes to types. (Use versioned type names to manage
+     *   breaking changes.)
+     * Schemes other than `http`, `https` (or the empty scheme) might be
+     * used with implementation specific semantics.
+     *
+     * Generated from protobuf field <code>string type_url = 1;</code>
+     */
+    private $type_url = '';
+    /**
+     * Must be a valid serialized protocol buffer of the above specified type.
+     *
+     * Generated from protobuf field <code>bytes value = 2;</code>
+     */
+    private $value = '';
+
+    const TYPE_URL_PREFIX = 'type.googleapis.com/';
+
+    public function __construct() {
+        \GPBMetadata\Google\Protobuf\Any::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * A URL/resource name whose content describes the type of the
+     * serialized protocol buffer message.
+     * For URLs which use the scheme `http`, `https`, or no scheme, the
+     * following restrictions and interpretations apply:
+     * * If no scheme is provided, `https` is assumed.
+     * * The last segment of the URL's path must represent the fully
+     *   qualified name of the type (as in `path/google.protobuf.Duration`).
+     *   The name should be in a canonical form (e.g., leading "." is
+     *   not accepted).
+     * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+     *   value in binary format, or produce an error.
+     * * Applications are allowed to cache lookup results based on the
+     *   URL, or have them precompiled into a binary to avoid any
+     *   lookup. Therefore, binary compatibility needs to be preserved
+     *   on changes to types. (Use versioned type names to manage
+     *   breaking changes.)
+     * Schemes other than `http`, `https` (or the empty scheme) might be
+     * used with implementation specific semantics.
+     *
+     * Generated from protobuf field <code>string type_url = 1;</code>
+     * @return string
+     */
+    public function getTypeUrl()
+    {
+        return $this->type_url;
+    }
+
+    /**
+     * A URL/resource name whose content describes the type of the
+     * serialized protocol buffer message.
+     * For URLs which use the scheme `http`, `https`, or no scheme, the
+     * following restrictions and interpretations apply:
+     * * If no scheme is provided, `https` is assumed.
+     * * The last segment of the URL's path must represent the fully
+     *   qualified name of the type (as in `path/google.protobuf.Duration`).
+     *   The name should be in a canonical form (e.g., leading "." is
+     *   not accepted).
+     * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+     *   value in binary format, or produce an error.
+     * * Applications are allowed to cache lookup results based on the
+     *   URL, or have them precompiled into a binary to avoid any
+     *   lookup. Therefore, binary compatibility needs to be preserved
+     *   on changes to types. (Use versioned type names to manage
+     *   breaking changes.)
+     * Schemes other than `http`, `https` (or the empty scheme) might be
+     * used with implementation specific semantics.
+     *
+     * Generated from protobuf field <code>string type_url = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setTypeUrl($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->type_url = $var;
+
+        return $this;
+    }
+
+    /**
+     * Must be a valid serialized protocol buffer of the above specified type.
+     *
+     * Generated from protobuf field <code>bytes value = 2;</code>
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Must be a valid serialized protocol buffer of the above specified type.
+     *
+     * Generated from protobuf field <code>bytes value = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setValue($var)
+    {
+        GPBUtil::checkString($var, False);
+        $this->value = $var;
+
+        return $this;
+    }
+
+    /**
+     * This method will try to resolve the type_url in Any message to get the
+     * targeted message type. If failed, an error will be thrown. Otherwise,
+     * the method will create a message of the targeted type and fill it with
+     * the decoded value in Any.
+     * @return unpacked message
+     * @throws Exception Type url needs to be type.googleapis.com/fully-qulified.
+     * @throws Exception Class hasn't been added to descriptor pool.
+     * @throws Exception cannot decode data in value field.
+     */
+    public function unpack()
+    {
+        // Get fully qualifed name from type url.
+        $type_url_len = strlen($this->type_url);
+        $url_prifix_len = strlen(Any::TYPE_URL_PREFIX);
+        if ($type_url_len < url_prifix_len ||
+            substr($this->type_url, 0, $url_prifix_len) !=
+                Any::TYPE_URL_PREFIX) {
+            throw new \Exception(
+                "Type url needs to be type.googleapis.com/fully-qulified");
+        }
+        $fully_qualifed_name =
+            substr($this->type_url, $url_prifix_len, $type_url_len);
+
+        // Create message according to fully qualified name.
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByProtoName( ".".$fully_qualifed_name);
+        if (is_null($desc)) {
+            throw new \Exception("Class ".$fully_qualifed_name
+                                     ." hasn't been added to descriptor pool");
+        }
+        $klass = $desc->getClass();
+        $msg = new $klass();
+
+        // Merge data into message.
+        $msg->mergeFromString($this->value);
+        return $msg;
+    }
+
+    /**
+     * The type_url will be created according to the given message’s type and
+     * the value is encoded data from the given message..
+     * @param message: A proto message.
+     */
+    public function pack($msg)
+    {
+        if (!$msg instanceof Message) {
+            trigger_error("Given parameter is not a message instance.",
+                          E_USER_ERROR);
+            return;
+        }
+
+        // Set value using serialzed message.
+        $this->value = $msg->serializeToString();
+
+        // Set type url.
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName(get_class($msg));
+        $fully_qualifed_name = $desc->getFullName();
+        $this->type_url = Any::TYPE_URL_PREFIX.substr(
+            $fully_qualifed_name, 1, strlen($fully_qualifed_name));
+    }
+
+    /**
+     * This method returns whether the type_url in any_message is corresponded
+     * to the given class.
+     * @param klass: The fully qualified PHP class name of a proto message type.
+     */
+    public function is($klass)
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName($klass);
+        $fully_qualifed_name = $desc->getFullName();
+        $type_url = Any::TYPE_URL_PREFIX.substr(
+            $fully_qualifed_name, 1, strlen($fully_qualifed_name));
+        return $this->type_url === $type_url;
+    }
+}
diff --git a/php/src/Google/Protobuf/Descriptor.php b/php/src/Google/Protobuf/Descriptor.php
new file mode 100644
index 0000000..986b81e
--- /dev/null
+++ b/php/src/Google/Protobuf/Descriptor.php
@@ -0,0 +1,100 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GetPublicDescriptorTrait;
+
+class Descriptor
+{
+    use GetPublicDescriptorTrait;
+
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string Full protobuf message name
+     */
+    public function getFullName()
+    {
+        return trim($this->internal_desc->getFullName(), ".");
+    }
+
+    /**
+     * @return string PHP class name
+     */
+    public function getClass()
+    {
+        return $this->internal_desc->getClass();
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getFieldCount()
+     * @return FieldDescriptor
+     */
+    public function getField($index)
+    {
+        return $this->getPublicDescriptor($this->internal_desc->getFieldByIndex($index));
+    }
+
+    /**
+     * @return int Number of fields in message
+     */
+    public function getFieldCount()
+    {
+        return count($this->internal_desc->getField());
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getOneofDeclCount()
+     * @return OneofDescriptor
+     */
+    public function getOneofDecl($index)
+    {
+        return $this->getPublicDescriptor($this->internal_desc->getOneofDecl()[$index]);
+    }
+
+    /**
+     * @return int Number of oneofs in message
+     */
+    public function getOneofDeclCount()
+    {
+        return count($this->internal_desc->getOneofDecl());
+    }
+}
diff --git a/php/src/Google/Protobuf/DescriptorPool.php b/php/src/Google/Protobuf/DescriptorPool.php
new file mode 100644
index 0000000..119f0e2
--- /dev/null
+++ b/php/src/Google/Protobuf/DescriptorPool.php
@@ -0,0 +1,76 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+namespace Google\Protobuf;
+
+class DescriptorPool
+{
+    private static $pool;
+
+    private $internal_pool;
+
+    /**
+     * @return DescriptorPool
+     */
+    public static function getGeneratedPool()
+    {
+        if (!isset(self::$pool)) {
+            self::$pool = new DescriptorPool(\Google\Protobuf\Internal\DescriptorPool::getGeneratedPool());
+        }
+        return self::$pool;
+    }
+
+    private function __construct($internal_pool)
+    {
+        $this->internal_pool = $internal_pool;
+    }
+
+    /**
+     * @param string $className A fully qualified protobuf class name
+     * @return Descriptor
+     */
+    public function getDescriptorByClassName($className)
+    {
+        $desc = $this->internal_pool->getDescriptorByClassName($className);
+        return is_null($desc) ? null : $desc->getPublicDescriptor();
+    }
+
+    /**
+     * @param string $className A fully qualified protobuf class name
+     * @return EnumDescriptor
+     */
+    public function getEnumDescriptorByClassName($className)
+    {
+        $desc = $this->internal_pool->getEnumDescriptorByClassName($className);
+        return is_null($desc) ? null : $desc->getPublicDescriptor();
+    }
+}
diff --git a/php/src/Google/Protobuf/Duration.php b/php/src/Google/Protobuf/Duration.php
new file mode 100644
index 0000000..ca1c4c0
--- /dev/null
+++ b/php/src/Google/Protobuf/Duration.php
@@ -0,0 +1,153 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/duration.proto
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * A Duration represents a signed, fixed-length span of time represented
+ * as a count of seconds and fractions of seconds at nanosecond
+ * resolution. It is independent of any calendar and concepts like "day"
+ * or "month". It is related to Timestamp in that the difference between
+ * two Timestamp values is a Duration and it can be added or subtracted
+ * from a Timestamp. Range is approximately +-10,000 years.
+ * # Examples
+ * Example 1: Compute Duration from two Timestamps in pseudo code.
+ *     Timestamp start = ...;
+ *     Timestamp end = ...;
+ *     Duration duration = ...;
+ *     duration.seconds = end.seconds - start.seconds;
+ *     duration.nanos = end.nanos - start.nanos;
+ *     if (duration.seconds < 0 && duration.nanos > 0) {
+ *       duration.seconds += 1;
+ *       duration.nanos -= 1000000000;
+ *     } else if (durations.seconds > 0 && duration.nanos < 0) {
+ *       duration.seconds -= 1;
+ *       duration.nanos += 1000000000;
+ *     }
+ * Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+ *     Timestamp start = ...;
+ *     Duration duration = ...;
+ *     Timestamp end = ...;
+ *     end.seconds = start.seconds + duration.seconds;
+ *     end.nanos = start.nanos + duration.nanos;
+ *     if (end.nanos < 0) {
+ *       end.seconds -= 1;
+ *       end.nanos += 1000000000;
+ *     } else if (end.nanos >= 1000000000) {
+ *       end.seconds += 1;
+ *       end.nanos -= 1000000000;
+ *     }
+ * Example 3: Compute Duration from datetime.timedelta in Python.
+ *     td = datetime.timedelta(days=3, minutes=10)
+ *     duration = Duration()
+ *     duration.FromTimedelta(td)
+ * # JSON Mapping
+ * In JSON format, the Duration type is encoded as a string rather than an
+ * object, where the string ends in the suffix "s" (indicating seconds) and
+ * is preceded by the number of seconds, with nanoseconds expressed as
+ * fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+ * encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+ * be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+ * microsecond should be expressed in JSON format as "3.000001s".
+ *
+ * Generated from protobuf message <code>google.protobuf.Duration</code>
+ */
+class Duration extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Signed seconds of the span of time. Must be from -315,576,000,000
+     * to +315,576,000,000 inclusive. Note: these bounds are computed from:
+     * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+     *
+     * Generated from protobuf field <code>int64 seconds = 1;</code>
+     */
+    private $seconds = 0;
+    /**
+     * Signed fractions of a second at nanosecond resolution of the span
+     * of time. Durations less than one second are represented with a 0
+     * `seconds` field and a positive or negative `nanos` field. For durations
+     * of one second or more, a non-zero value for the `nanos` field must be
+     * of the same sign as the `seconds` field. Must be from -999,999,999
+     * to +999,999,999 inclusive.
+     *
+     * Generated from protobuf field <code>int32 nanos = 2;</code>
+     */
+    private $nanos = 0;
+
+    public function __construct() {
+        \GPBMetadata\Google\Protobuf\Duration::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Signed seconds of the span of time. Must be from -315,576,000,000
+     * to +315,576,000,000 inclusive. Note: these bounds are computed from:
+     * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+     *
+     * Generated from protobuf field <code>int64 seconds = 1;</code>
+     * @return int|string
+     */
+    public function getSeconds()
+    {
+        return $this->seconds;
+    }
+
+    /**
+     * Signed seconds of the span of time. Must be from -315,576,000,000
+     * to +315,576,000,000 inclusive. Note: these bounds are computed from:
+     * 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+     *
+     * Generated from protobuf field <code>int64 seconds = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setSeconds($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->seconds = $var;
+
+        return $this;
+    }
+
+    /**
+     * Signed fractions of a second at nanosecond resolution of the span
+     * of time. Durations less than one second are represented with a 0
+     * `seconds` field and a positive or negative `nanos` field. For durations
+     * of one second or more, a non-zero value for the `nanos` field must be
+     * of the same sign as the `seconds` field. Must be from -999,999,999
+     * to +999,999,999 inclusive.
+     *
+     * Generated from protobuf field <code>int32 nanos = 2;</code>
+     * @return int
+     */
+    public function getNanos()
+    {
+        return $this->nanos;
+    }
+
+    /**
+     * Signed fractions of a second at nanosecond resolution of the span
+     * of time. Durations less than one second are represented with a 0
+     * `seconds` field and a positive or negative `nanos` field. For durations
+     * of one second or more, a non-zero value for the `nanos` field must be
+     * of the same sign as the `seconds` field. Must be from -999,999,999
+     * to +999,999,999 inclusive.
+     *
+     * Generated from protobuf field <code>int32 nanos = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNanos($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->nanos = $var;
+
+        return $this;
+    }
+}
+
diff --git a/php/src/Google/Protobuf/EnumDescriptor.php b/php/src/Google/Protobuf/EnumDescriptor.php
new file mode 100644
index 0000000..a8b56c0
--- /dev/null
+++ b/php/src/Google/Protobuf/EnumDescriptor.php
@@ -0,0 +1,79 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+namespace Google\Protobuf;
+
+class EnumDescriptor
+{
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string Full protobuf message name
+     */
+    public function getFullName()
+    {
+        return $this->internal_desc->getFullName();
+    }
+
+    /**
+     * @return string PHP class name
+     */
+    public function getClass()
+    {
+        return $this->internal_desc->getClass();
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getValueCount()
+     * @return EnumValueDescriptor
+     */
+    public function getValue($index)
+    {
+        return $this->internal_desc->getValueDescriptorByIndex($index);
+    }
+
+    /**
+     * @return int Number of values in enum
+     */
+    public function getValueCount()
+    {
+        return $this->internal_desc->getValueCount();
+    }
+}
diff --git a/php/src/Google/Protobuf/EnumValueDescriptor.php b/php/src/Google/Protobuf/EnumValueDescriptor.php
new file mode 100644
index 0000000..e76e199
--- /dev/null
+++ b/php/src/Google/Protobuf/EnumValueDescriptor.php
@@ -0,0 +1,64 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf;
+
+class EnumValueDescriptor
+{
+    private $name;
+    private $number;
+
+    /**
+     * @internal
+     */
+    public function __construct($name, $number)
+    {
+        $this->name = $name;
+        $this->number = $number;
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * @return int
+     */
+    public function getNumber()
+    {
+        return $this->number;
+    }
+}
diff --git a/php/src/Google/Protobuf/FieldDescriptor.php b/php/src/Google/Protobuf/FieldDescriptor.php
new file mode 100644
index 0000000..ac9271f
--- /dev/null
+++ b/php/src/Google/Protobuf/FieldDescriptor.php
@@ -0,0 +1,117 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GetPublicDescriptorTrait;
+use Google\Protobuf\Internal\GPBType;
+
+class FieldDescriptor
+{
+    use GetPublicDescriptorTrait;
+
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string Field name
+     */
+    public function getName()
+    {
+        return $this->internal_desc->getName();
+    }
+
+    /**
+     * @return int Protobuf field number
+     */
+    public function getNumber()
+    {
+        return $this->internal_desc->getNumber();
+    }
+
+    /**
+     * @return int
+     */
+    public function getLabel()
+    {
+        return $this->internal_desc->getLabel();
+    }
+
+    /**
+     * @return int
+     */
+    public function getType()
+    {
+        return $this->internal_desc->getType();
+    }
+
+    /**
+     * @return Descriptor Returns a descriptor for the field type if the field type is a message, otherwise throws \Exception
+     * @throws \Exception
+     */
+    public function getMessageType()
+    {
+        if ($this->getType() == GPBType::MESSAGE) {
+            return $this->getPublicDescriptor($this->internal_desc->getMessageType());
+        } else {
+            throw new \Exception("Cannot get message type for non-message field '" . $this->getName() . "'");
+        }
+    }
+
+    /**
+     * @return EnumDescriptor Returns an enum descriptor if the field type is an enum, otherwise throws \Exception
+     * @throws \Exception
+     */
+    public function getEnumType()
+    {
+        if ($this->getType() == GPBType::ENUM) {
+            return $this->getPublicDescriptor($this->internal_desc->getEnumType());
+        } else {
+            throw new \Exception("Cannot get enum type for non-enum field '" . $this->getName() . "'");
+        }
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isMap()
+    {
+        return $this->internal_desc->isMap();
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/InputStream.php b/php/src/Google/Protobuf/Internal/CodedInputStream.php
similarity index 95%
rename from php/src/Google/Protobuf/Internal/InputStream.php
rename to php/src/Google/Protobuf/Internal/CodedInputStream.php
index 8012a22..6131d5d 100644
--- a/php/src/Google/Protobuf/Internal/InputStream.php
+++ b/php/src/Google/Protobuf/Internal/CodedInputStream.php
@@ -34,28 +34,7 @@
 
 use Google\Protobuf\Internal\Uint64;
 
-function combineInt32ToInt64($high, $low)
-{
-    $isNeg = $high < 0;
-    if ($isNeg) {
-        $high = ~$high;
-        $low = ~$low;
-        $low++;
-        if (!$low) {
-            $high++;
-        }
-    }
-    $result = bcadd(bcmul($high, 4294967296), $low);
-    if ($low < 0) {
-        $result = bcadd($result, 4294967296);
-    }
-    if ($isNeg) {
-      $result = bcsub(0, $result);
-    }
-    return $result;
-}
-
-class InputStream
+class CodedInputStream
 {
 
     private $buffer;
@@ -94,7 +73,7 @@
         $this->current += $amount;
     }
 
-    private function bufferSize()
+    public function bufferSize()
     {
         return $this->buffer_end - $this->current;
     }
@@ -192,7 +171,10 @@
                 $count += 1;
             } while ($b & 0x80);
 
-            $var = combineInt32ToInt64($high, $low);
+            $var = GPBUtil::combineInt32ToInt64($high, $low);
+            if (bccomp($var, 0) < 0) {
+                $var = bcadd($var, "18446744073709551616");
+            }
         } else {
             $result = 0;
             $shift = 0;
@@ -265,7 +247,7 @@
         }
         $high = unpack('V', $data)[1];
         if (PHP_INT_SIZE == 4) {
-            $var = combineInt32ToInt64($high, $low);
+            $var = GPBUtil::combineInt32ToInt64($high, $low);
         } else {
             $var = ($high << 32) | $low;
         }
diff --git a/php/src/Google/Protobuf/Internal/OutputStream.php b/php/src/Google/Protobuf/Internal/CodedOutputStream.php
similarity index 92%
rename from php/src/Google/Protobuf/Internal/OutputStream.php
rename to php/src/Google/Protobuf/Internal/CodedOutputStream.php
index 8c6d9b6..4525d8d 100644
--- a/php/src/Google/Protobuf/Internal/OutputStream.php
+++ b/php/src/Google/Protobuf/Internal/CodedOutputStream.php
@@ -32,7 +32,7 @@
 
 namespace Google\Protobuf\Internal;
 
-class OutputStream
+class CodedOutputStream
 {
 
     private $buffer;
@@ -53,10 +53,10 @@
         return $this->buffer;
     }
 
-    public function writeVarint32($value)
+    public function writeVarint32($value, $trim)
     {
         $bytes = str_repeat(chr(0), self::MAX_VARINT64_BYTES);
-        $size = self::writeVarintToArray($value, $bytes);
+        $size = self::writeVarintToArray($value, $bytes, $trim);
         return $this->writeRaw($bytes, $size);
     }
 
@@ -83,7 +83,7 @@
 
     public function writeTag($tag)
     {
-        return $this->writeVarint32($tag);
+        return $this->writeVarint32($tag, true);
     }
 
     public function writeRaw($data, $size)
@@ -101,19 +101,19 @@
         return true;
     }
 
-    private static function writeVarintToArray($value, &$buffer)
+    private static function writeVarintToArray($value, &$buffer, $trim = false)
     {
         $current = 0;
 
         $high = 0;
         $low = 0;
         if (PHP_INT_SIZE == 4) {
-            GPBUtil::divideInt64ToInt32($value, $high, $low);
+            GPBUtil::divideInt64ToInt32($value, $high, $low, $trim);
         } else {
             $low = $value;
         }
 
-        while ($low >= 0x80 || $low < 0) {
+        while (($low >= 0x80 || $low < 0) || $high != 0) {
             $buffer[$current] = chr($low | 0x80);
             $value = ($value >> 7) & ~(0x7F << ((PHP_INT_SIZE << 3) - 7));
             $carry = ($high & 0x7F) << ((PHP_INT_SIZE << 3) - 7);
diff --git a/php/src/Google/Protobuf/Internal/Descriptor.php b/php/src/Google/Protobuf/Internal/Descriptor.php
new file mode 100644
index 0000000..ee3a8bd
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/Descriptor.php
@@ -0,0 +1,208 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class Descriptor
+{
+    use HasPublicDescriptorTrait;
+
+    private $full_name;
+    private $field = [];
+    private $json_to_field = [];
+    private $name_to_field = [];
+    private $index_to_field = [];
+    private $nested_type = [];
+    private $enum_type = [];
+    private $klass;
+    private $options;
+    private $oneof_decl = [];
+
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\Descriptor($this);
+    }
+
+    public function addOneofDecl($oneof)
+    {
+        $this->oneof_decl[] = $oneof;
+    }
+
+    public function getOneofDecl()
+    {
+        return $this->oneof_decl;
+    }
+
+    public function setFullName($full_name)
+    {
+        $this->full_name = $full_name;
+    }
+
+    public function getFullName()
+    {
+        return $this->full_name;
+    }
+
+    public function addField($field)
+    {
+        $this->field[$field->getNumber()] = $field;
+        $this->json_to_field[$field->getJsonName()] = $field;
+        $this->name_to_field[$field->getName()] = $field;
+        $this->index_to_field[] = $field;
+    }
+
+    public function getField()
+    {
+        return $this->field;
+    }
+
+    public function addNestedType($desc)
+    {
+        $this->nested_type[] = $desc;
+    }
+
+    public function getNestedType()
+    {
+        return $this->nested_type;
+    }
+
+    public function addEnumType($desc)
+    {
+        $this->enum_type[] = $desc;
+    }
+
+    public function getEnumType()
+    {
+        return $this->enum_type;
+    }
+
+    public function getFieldByNumber($number)
+    {
+        if (!isset($this->field[$number])) {
+          return NULL;
+        } else {
+          return $this->field[$number];
+        }
+    }
+
+    public function getFieldByJsonName($json_name)
+    {
+        if (!isset($this->json_to_field[$json_name])) {
+          return NULL;
+        } else {
+          return $this->json_to_field[$json_name];
+        }
+    }
+
+    public function getFieldByName($name)
+    {
+        if (!isset($this->name_to_field[$name])) {
+          return NULL;
+        } else {
+          return $this->name_to_field[$name];
+        }
+    }
+
+    public function getFieldByIndex($index)
+    {
+        if (count($this->index_to_field) <= $index) {
+            return NULL;
+        } else {
+            return $this->index_to_field[$index];
+        }
+    }
+
+    public function setClass($klass)
+    {
+        $this->klass = $klass;
+    }
+
+    public function getClass()
+    {
+        return $this->klass;
+    }
+
+    public function setOptions($options)
+    {
+        $this->options = $options;
+    }
+
+    public function getOptions()
+    {
+        return $this->options;
+    }
+
+    public static function buildFromProto($proto, $file_proto, $containing)
+    {
+        $desc = new Descriptor();
+
+        $message_name_without_package  = "";
+        $classname = "";
+        $fullname = "";
+        GPBUtil::getFullClassName(
+            $proto,
+            $containing,
+            $file_proto,
+            $message_name_without_package,
+            $classname,
+            $fullname);
+        $desc->setFullName($fullname);
+        $desc->setClass($classname);
+        $desc->setOptions($proto->getOptions());
+
+        foreach ($proto->getField() as $field_proto) {
+            $desc->addField(FieldDescriptor::buildFromProto($field_proto));
+        }
+
+        // Handle nested types.
+        foreach ($proto->getNestedType() as $nested_proto) {
+            $desc->addNestedType(Descriptor::buildFromProto(
+              $nested_proto, $file_proto, $message_name_without_package));
+        }
+
+        // Handle nested enum.
+        foreach ($proto->getEnumType() as $enum_proto) {
+            $desc->addEnumType(EnumDescriptor::buildFromProto(
+              $enum_proto, $file_proto, $message_name_without_package));
+        }
+
+        // Handle oneof fields.
+        $index = 0;
+        foreach ($proto->getOneofDecl() as $oneof_proto) {
+            $desc->addOneofDecl(
+                OneofDescriptor::buildFromProto($oneof_proto, $desc, $index));
+            $index++;
+        }
+
+        return $desc;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/DescriptorPool.php b/php/src/Google/Protobuf/Internal/DescriptorPool.php
index 2c00dfb..65d1a88 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorPool.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorPool.php
@@ -61,17 +61,17 @@
         $files->mergeFromString($data);
         $file = FileDescriptor::buildFromProto($files->getFile()[0]);
 
-        foreach ($file->getMessageType() as &$desc) {
+        foreach ($file->getMessageType() as $desc) {
             $this->addDescriptor($desc);
         }
         unset($desc);
 
-        foreach ($file->getEnumType() as &$desc) {
+        foreach ($file->getEnumType() as $desc) {
             $this->addEnumDescriptor($desc);
         }
         unset($desc);
 
-        foreach ($file->getMessageType() as &$desc) {
+        foreach ($file->getMessageType() as $desc) {
             $this->crossLink($desc);
         }
         unset($desc);
@@ -129,9 +129,9 @@
         return $this->class_to_enum_desc[$klass];
     }
 
-    private function crossLink(&$desc)
+    private function crossLink(Descriptor $desc)
     {
-        foreach ($desc->getField() as &$field) {
+        foreach ($desc->getField() as $field) {
             switch ($field->getType()) {
                 case GPBType::MESSAGE:
                     $proto = $field->getMessageType();
@@ -149,7 +149,7 @@
         }
         unset($field);
 
-        foreach ($desc->getNestedType() as &$nested_type) {
+        foreach ($desc->getNestedType() as $nested_type) {
             $this->crossLink($nested_type);
         }
         unset($nested_type);
@@ -157,7 +157,7 @@
 
     public function finish()
     {
-        foreach ($this->class_to_desc as $klass => &$desc) {
+        foreach ($this->class_to_desc as $klass => $desc) {
             $this->crossLink($desc);
         }
         unset($desc);
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php
index 948c587..1d6959b 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php
@@ -8,70 +8,65 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a message type.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.DescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.DescriptorProto</code>
  */
 class DescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
      */
     private $field;
     private $has_field = false;
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
      */
     private $extension;
     private $has_extension = false;
     /**
-     * <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
      */
     private $nested_type;
     private $has_nested_type = false;
     /**
-     * <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
      */
     private $enum_type;
     private $has_enum_type = false;
     /**
-     * <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
      */
     private $extension_range;
     private $has_extension_range = false;
     /**
-     * <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
      */
     private $oneof_decl;
     private $has_oneof_decl = false;
     /**
-     * <code>optional .google.protobuf.MessageOptions options = 7;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
      */
     private $options = null;
     private $has_options = false;
     /**
-     * <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
      */
     private $reserved_range;
     private $has_reserved_range = false;
     /**
-     * <pre>
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
-     * </pre>
      *
-     * <code>repeated string reserved_name = 10;</code>
+     * Generated from protobuf field <code>repeated string reserved_name = 10;</code>
      */
     private $reserved_name;
     private $has_reserved_name = false;
@@ -82,7 +77,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -90,13 +86,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -105,7 +105,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getField()
     {
@@ -113,13 +114,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto field = 2;</code>
+     * @param \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setField(&$var)
+    public function setField($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->field = $arr;
         $this->has_field = true;
+
+        return $this;
     }
 
     public function hasField()
@@ -128,7 +133,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getExtension()
     {
@@ -136,13 +142,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 6;</code>
+     * @param \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setExtension(&$var)
+    public function setExtension($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->extension = $arr;
         $this->has_extension = true;
+
+        return $this;
     }
 
     public function hasExtension()
@@ -151,7 +161,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getNestedType()
     {
@@ -159,13 +170,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto nested_type = 3;</code>
+     * @param \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setNestedType(&$var)
+    public function setNestedType($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
         $this->nested_type = $arr;
         $this->has_nested_type = true;
+
+        return $this;
     }
 
     public function hasNestedType()
@@ -174,7 +189,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getEnumType()
     {
@@ -182,13 +198,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 4;</code>
+     * @param \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setEnumType(&$var)
+    public function setEnumType($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
         $this->enum_type = $arr;
         $this->has_enum_type = true;
+
+        return $this;
     }
 
     public function hasEnumType()
@@ -197,7 +217,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getExtensionRange()
     {
@@ -205,13 +226,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
+     * @param \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setExtensionRange(&$var)
+    public function setExtensionRange($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class);
         $this->extension_range = $arr;
         $this->has_extension_range = true;
+
+        return $this;
     }
 
     public function hasExtensionRange()
@@ -220,7 +245,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getOneofDecl()
     {
@@ -228,13 +254,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;</code>
+     * @param \Google\Protobuf\Internal\OneofDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setOneofDecl(&$var)
+    public function setOneofDecl($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\OneofDescriptorProto::class);
         $this->oneof_decl = $arr;
         $this->has_oneof_decl = true;
+
+        return $this;
     }
 
     public function hasOneofDecl()
@@ -243,7 +273,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.MessageOptions options = 7;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
+     * @return \Google\Protobuf\Internal\MessageOptions
      */
     public function getOptions()
     {
@@ -251,13 +282,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.MessageOptions options = 7;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
+     * @param \Google\Protobuf\Internal\MessageOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MessageOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
@@ -266,7 +301,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getReservedRange()
     {
@@ -274,13 +310,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
+     * @param \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setReservedRange(&$var)
+    public function setReservedRange($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class);
         $this->reserved_range = $arr;
         $this->has_reserved_range = true;
+
+        return $this;
     }
 
     public function hasReservedRange()
@@ -289,12 +329,11 @@
     }
 
     /**
-     * <pre>
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
-     * </pre>
      *
-     * <code>repeated string reserved_name = 10;</code>
+     * Generated from protobuf field <code>repeated string reserved_name = 10;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getReservedName()
     {
@@ -302,18 +341,20 @@
     }
 
     /**
-     * <pre>
      * Reserved field names, which may not be used by fields in the same message.
      * A given name may only be reserved once.
-     * </pre>
      *
-     * <code>repeated string reserved_name = 10;</code>
+     * Generated from protobuf field <code>repeated string reserved_name = 10;</code>
+     * @param string[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setReservedName(&$var)
+    public function setReservedName($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->reserved_name = $arr;
         $this->has_reserved_name = true;
+
+        return $this;
     }
 
     public function hasReservedName()
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
index 738a173..1d45599 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php
@@ -8,24 +8,28 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.DescriptorProto.ExtensionRange</code>
+ * Generated from protobuf message <code>google.protobuf.DescriptorProto.ExtensionRange</code>
  */
 class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional int32 start = 1;</code>
+     * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
     private $start = 0;
     private $has_start = false;
     /**
-     * <code>optional int32 end = 2;</code>
+     * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
     private $end = 0;
     private $has_end = false;
+    /**
+     * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
+     */
+    private $options = null;
+    private $has_options = false;
 
     public function __construct() {
         \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
@@ -33,7 +37,8 @@
     }
 
     /**
-     * <code>optional int32 start = 1;</code>
+     * Generated from protobuf field <code>optional int32 start = 1;</code>
+     * @return int
      */
     public function getStart()
     {
@@ -41,13 +46,17 @@
     }
 
     /**
-     * <code>optional int32 start = 1;</code>
+     * Generated from protobuf field <code>optional int32 start = 1;</code>
+     * @param int $var
+     * @return $this
      */
     public function setStart($var)
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
         $this->has_start = true;
+
+        return $this;
     }
 
     public function hasStart()
@@ -56,7 +65,8 @@
     }
 
     /**
-     * <code>optional int32 end = 2;</code>
+     * Generated from protobuf field <code>optional int32 end = 2;</code>
+     * @return int
      */
     public function getEnd()
     {
@@ -64,13 +74,17 @@
     }
 
     /**
-     * <code>optional int32 end = 2;</code>
+     * Generated from protobuf field <code>optional int32 end = 2;</code>
+     * @param int $var
+     * @return $this
      */
     public function setEnd($var)
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
         $this->has_end = true;
+
+        return $this;
     }
 
     public function hasEnd()
@@ -78,5 +92,33 @@
         return $this->has_end;
     }
 
+    /**
+     * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
+     * @return \Google\Protobuf\Internal\ExtensionRangeOptions
+     */
+    public function getOptions()
+    {
+        return $this->options;
+    }
+
+    /**
+     * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
+     * @param \Google\Protobuf\Internal\ExtensionRangeOptions $var
+     * @return $this
+     */
+    public function setOptions($var)
+    {
+        GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ExtensionRangeOptions::class);
+        $this->options = $var;
+        $this->has_options = true;
+
+        return $this;
+    }
+
+    public function hasOptions()
+    {
+        return $this->has_options;
+    }
+
 }
 
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
index be36b8a..b1022d6 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php
@@ -8,35 +8,28 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Range of reserved tag numbers. Reserved tag numbers may not be used by
  * fields or extension ranges in the same message. Reserved ranges may
  * not overlap.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.DescriptorProto.ReservedRange</code>
+ * Generated from protobuf message <code>google.protobuf.DescriptorProto.ReservedRange</code>
  */
 class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Inclusive.
-     * </pre>
      *
-     * <code>optional int32 start = 1;</code>
+     * Generated from protobuf field <code>optional int32 start = 1;</code>
      */
     private $start = 0;
     private $has_start = false;
     /**
-     * <pre>
      * Exclusive.
-     * </pre>
      *
-     * <code>optional int32 end = 2;</code>
+     * Generated from protobuf field <code>optional int32 end = 2;</code>
      */
     private $end = 0;
     private $has_end = false;
@@ -47,11 +40,10 @@
     }
 
     /**
-     * <pre>
      * Inclusive.
-     * </pre>
      *
-     * <code>optional int32 start = 1;</code>
+     * Generated from protobuf field <code>optional int32 start = 1;</code>
+     * @return int
      */
     public function getStart()
     {
@@ -59,17 +51,19 @@
     }
 
     /**
-     * <pre>
      * Inclusive.
-     * </pre>
      *
-     * <code>optional int32 start = 1;</code>
+     * Generated from protobuf field <code>optional int32 start = 1;</code>
+     * @param int $var
+     * @return $this
      */
     public function setStart($var)
     {
         GPBUtil::checkInt32($var);
         $this->start = $var;
         $this->has_start = true;
+
+        return $this;
     }
 
     public function hasStart()
@@ -78,11 +72,10 @@
     }
 
     /**
-     * <pre>
      * Exclusive.
-     * </pre>
      *
-     * <code>optional int32 end = 2;</code>
+     * Generated from protobuf field <code>optional int32 end = 2;</code>
+     * @return int
      */
     public function getEnd()
     {
@@ -90,17 +83,19 @@
     }
 
     /**
-     * <pre>
      * Exclusive.
-     * </pre>
      *
-     * <code>optional int32 end = 2;</code>
+     * Generated from protobuf field <code>optional int32 end = 2;</code>
+     * @param int $var
+     * @return $this
      */
     public function setEnd($var)
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
         $this->has_end = true;
+
+        return $this;
     }
 
     public function hasEnd()
diff --git a/php/src/Google/Protobuf/Internal/EnumBuilderContext.php b/php/src/Google/Protobuf/Internal/EnumBuilderContext.php
index c1dac24..0839728 100644
--- a/php/src/Google/Protobuf/Internal/EnumBuilderContext.php
+++ b/php/src/Google/Protobuf/Internal/EnumBuilderContext.php
@@ -33,7 +33,7 @@
 namespace Google\Protobuf\Internal;
 
 use Google\Protobuf\Internal\EnumDescriptor;
-use Google\Protobuf\Internal\EnumValueDescriptor;
+use Google\Protobuf\EnumValueDescriptor;
 
 class EnumBuilderContext
 {
@@ -51,7 +51,7 @@
 
     public function value($name, $number)
     {
-        $value = new EnumValueDescriptor();
+        $value = new EnumValueDescriptor($name, $number);
         $this->descriptor->addValue($number, $value);
         return $this;
     }
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptor.php b/php/src/Google/Protobuf/Internal/EnumDescriptor.php
new file mode 100644
index 0000000..01649fe
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptor.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Google\Protobuf\Internal;
+
+use Google\Protobuf\EnumValueDescriptor;
+
+class EnumDescriptor
+{
+    use HasPublicDescriptorTrait;
+
+    private $klass;
+    private $full_name;
+    private $value;
+    private $name_to_value;
+    private $value_descriptor = [];
+
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\EnumDescriptor($this);
+    }
+
+    public function setFullName($full_name)
+    {
+        $this->full_name = $full_name;
+    }
+
+    public function getFullName()
+    {
+        return $this->full_name;
+    }
+
+    public function addValue($number, $value)
+    {
+        $this->value[$number] = $value;
+        $this->name_to_value[$value->getName()] = $value;
+        $this->value_descriptor[] = new EnumValueDescriptor($value->getName(), $number);
+    }
+
+    public function getValueByNumber($number)
+    {
+        return $this->value[$number];
+    }
+
+    public function getValueByName($name)
+    {
+        return $this->name_to_value[$name];
+    }
+
+    public function getValueDescriptorByIndex($index)
+    {
+        return $this->value_descriptor[$index];
+    }
+
+    public function getValueCount()
+    {
+        return count($this->value);
+    }
+
+    public function setClass($klass)
+    {
+        $this->klass = $klass;
+    }
+
+    public function getClass()
+    {
+        return $this->klass;
+    }
+
+    public static function buildFromProto($proto, $file_proto, $containing)
+    {
+        $desc = new EnumDescriptor();
+
+        $enum_name_without_package  = "";
+        $classname = "";
+        $fullname = "";
+        GPBUtil::getFullClassName(
+            $proto,
+            $containing,
+            $file_proto,
+            $enum_name_without_package,
+            $classname,
+            $fullname);
+        $desc->setFullName($fullname);
+        $desc->setClass($classname);
+        $values = $proto->getValue();
+        foreach ($values as $value) {
+            $desc->addValue($value->getNumber(), $value);
+        }
+
+        return $desc;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
index 73f6edb..816fbae 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
@@ -8,30 +8,27 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes an enum type.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.EnumDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.EnumDescriptorProto</code>
  */
 class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
      */
     private $value;
     private $has_value = false;
     /**
-     * <code>optional .google.protobuf.EnumOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
      */
     private $options = null;
     private $has_options = false;
@@ -42,7 +39,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -50,13 +48,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -65,7 +67,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getValue()
     {
@@ -73,13 +76,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumValueDescriptorProto value = 2;</code>
+     * @param \Google\Protobuf\Internal\EnumValueDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setValue(&$var)
+    public function setValue($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumValueDescriptorProto::class);
         $this->value = $arr;
         $this->has_value = true;
+
+        return $this;
     }
 
     public function hasValue()
@@ -88,7 +95,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.EnumOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
+     * @return \Google\Protobuf\Internal\EnumOptions
      */
     public function getOptions()
     {
@@ -96,13 +104,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.EnumOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
+     * @param \Google\Protobuf\Internal\EnumOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
diff --git a/php/src/Google/Protobuf/Internal/EnumOptions.php b/php/src/Google/Protobuf/Internal/EnumOptions.php
index 4fa0bce..3f598a4 100644
--- a/php/src/Google/Protobuf/Internal/EnumOptions.php
+++ b/php/src/Google/Protobuf/Internal/EnumOptions.php
@@ -8,42 +8,35 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.EnumOptions</code>
+ * Generated from protobuf message <code>google.protobuf.EnumOptions</code>
  */
 class EnumOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Set this option to true to allow mapping different tag names to the same
      * value.
-     * </pre>
      *
-     * <code>optional bool allow_alias = 2;</code>
+     * Generated from protobuf field <code>optional bool allow_alias = 2;</code>
      */
     private $allow_alias = false;
     private $has_allow_alias = false;
     /**
-     * <pre>
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the enum, or it will be completely ignored; in the very least, this
      * is a formalization for deprecating enums.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -54,12 +47,11 @@
     }
 
     /**
-     * <pre>
      * Set this option to true to allow mapping different tag names to the same
      * value.
-     * </pre>
      *
-     * <code>optional bool allow_alias = 2;</code>
+     * Generated from protobuf field <code>optional bool allow_alias = 2;</code>
+     * @return bool
      */
     public function getAllowAlias()
     {
@@ -67,18 +59,20 @@
     }
 
     /**
-     * <pre>
      * Set this option to true to allow mapping different tag names to the same
      * value.
-     * </pre>
      *
-     * <code>optional bool allow_alias = 2;</code>
+     * Generated from protobuf field <code>optional bool allow_alias = 2;</code>
+     * @param bool $var
+     * @return $this
      */
     public function setAllowAlias($var)
     {
         GPBUtil::checkBool($var);
         $this->allow_alias = $var;
         $this->has_allow_alias = true;
+
+        return $this;
     }
 
     public function hasAllowAlias()
@@ -87,14 +81,13 @@
     }
 
     /**
-     * <pre>
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the enum, or it will be completely ignored; in the very least, this
      * is a formalization for deprecating enums.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -102,20 +95,22 @@
     }
 
     /**
-     * <pre>
      * Is this enum deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the enum, or it will be completely ignored; in the very least, this
      * is a formalization for deprecating enums.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -124,11 +119,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -136,17 +130,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
index 94dc36e..e363220 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
@@ -8,30 +8,27 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a value within an enum.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.EnumValueDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.EnumValueDescriptorProto</code>
  */
 class EnumValueDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <code>optional int32 number = 2;</code>
+     * Generated from protobuf field <code>optional int32 number = 2;</code>
      */
     private $number = 0;
     private $has_number = false;
     /**
-     * <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
      */
     private $options = null;
     private $has_options = false;
@@ -42,7 +39,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -50,13 +48,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -65,7 +67,8 @@
     }
 
     /**
-     * <code>optional int32 number = 2;</code>
+     * Generated from protobuf field <code>optional int32 number = 2;</code>
+     * @return int
      */
     public function getNumber()
     {
@@ -73,13 +76,17 @@
     }
 
     /**
-     * <code>optional int32 number = 2;</code>
+     * Generated from protobuf field <code>optional int32 number = 2;</code>
+     * @param int $var
+     * @return $this
      */
     public function setNumber($var)
     {
         GPBUtil::checkInt32($var);
         $this->number = $var;
         $this->has_number = true;
+
+        return $this;
     }
 
     public function hasNumber()
@@ -88,7 +95,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
+     * @return \Google\Protobuf\Internal\EnumValueOptions
      */
     public function getOptions()
     {
@@ -96,13 +104,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
+     * @param \Google\Protobuf\Internal\EnumValueOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\EnumValueOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
diff --git a/php/src/Google/Protobuf/Internal/EnumValueOptions.php b/php/src/Google/Protobuf/Internal/EnumValueOptions.php
index 232a673..db8de17 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueOptions.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueOptions.php
@@ -8,32 +8,27 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.EnumValueOptions</code>
+ * Generated from protobuf message <code>google.protobuf.EnumValueOptions</code>
  */
 class EnumValueOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Is this enum value deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the enum value, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating enum values.
-     * </pre>
      *
-     * <code>optional bool deprecated = 1 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 1 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -44,14 +39,13 @@
     }
 
     /**
-     * <pre>
      * Is this enum value deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the enum value, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating enum values.
-     * </pre>
      *
-     * <code>optional bool deprecated = 1 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 1 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -59,20 +53,22 @@
     }
 
     /**
-     * <pre>
      * Is this enum value deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the enum value, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating enum values.
-     * </pre>
      *
-     * <code>optional bool deprecated = 1 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 1 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -81,11 +77,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -93,17 +88,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptor.php b/php/src/Google/Protobuf/Internal/FieldDescriptor.php
new file mode 100644
index 0000000..6644a2e
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptor.php
@@ -0,0 +1,265 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class FieldDescriptor
+{
+    use HasPublicDescriptorTrait;
+
+    private $name;
+    private $json_name;
+    private $setter;
+    private $getter;
+    private $number;
+    private $label;
+    private $type;
+    private $message_type;
+    private $enum_type;
+    private $packed;
+    private $is_map;
+    private $oneof_index = -1;
+
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\FieldDescriptor($this);
+    }
+
+    public function setOneofIndex($index)
+    {
+        $this->oneof_index = $index;
+    }
+
+    public function getOneofIndex()
+    {
+        return $this->oneof_index;
+    }
+
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setJsonName($json_name)
+    {
+        $this->json_name = $json_name;
+    }
+
+    public function getJsonName()
+    {
+        return $this->json_name;
+    }
+
+    public function setSetter($setter)
+    {
+        $this->setter = $setter;
+    }
+
+    public function getSetter()
+    {
+        return $this->setter;
+    }
+
+    public function setGetter($getter)
+    {
+        $this->getter = $getter;
+    }
+
+    public function getGetter()
+    {
+        return $this->getter;
+    }
+
+    public function setNumber($number)
+    {
+        $this->number = $number;
+    }
+
+    public function getNumber()
+    {
+        return $this->number;
+    }
+
+    public function setLabel($label)
+    {
+        $this->label = $label;
+    }
+
+    public function getLabel()
+    {
+        return $this->label;
+    }
+
+    public function isRepeated()
+    {
+        return $this->label === GPBLabel::REPEATED;
+    }
+
+    public function setType($type)
+    {
+        $this->type = $type;
+    }
+
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    public function setMessageType($message_type)
+    {
+        $this->message_type = $message_type;
+    }
+
+    public function getMessageType()
+    {
+        return $this->message_type;
+    }
+
+    public function setEnumType($enum_type)
+    {
+        $this->enum_type = $enum_type;
+    }
+
+    public function getEnumType()
+    {
+        return $this->enum_type;
+    }
+
+    public function setPacked($packed)
+    {
+        $this->packed = $packed;
+    }
+
+    public function getPacked()
+    {
+        return $this->packed;
+    }
+
+    public function isPackable()
+    {
+        return $this->isRepeated() && self::isTypePackable($this->type);
+    }
+
+    public function isMap()
+    {
+        return $this->getType() == GPBType::MESSAGE &&
+               !is_null($this->getMessageType()->getOptions()) &&
+               $this->getMessageType()->getOptions()->getMapEntry();
+    }
+
+    public function isTimestamp()
+    {
+        return $this->getType() == GPBType::MESSAGE &&
+            $this->getMessageType()->getClass() === "Google\Protobuf\Timestamp";
+    }
+
+    private static function isTypePackable($field_type)
+    {
+        return ($field_type !== GPBType::STRING  &&
+            $field_type !== GPBType::GROUP   &&
+            $field_type !== GPBType::MESSAGE &&
+            $field_type !== GPBType::BYTES);
+    }
+
+    public static function getFieldDescriptor($proto)
+    {
+        $type_name = null;
+        $type = $proto->getType();
+        switch ($type) {
+            case GPBType::MESSAGE:
+            case GPBType::GROUP:
+            case GPBType::ENUM:
+                $type_name = $proto->getTypeName();
+                break;
+            default:
+                break;
+        }
+
+        $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1;
+        $packed = false;
+        $options = $proto->getOptions();
+        if ($options !== null) {
+            $packed = $options->getPacked();
+        }
+
+        $field = new FieldDescriptor();
+        $field->setName($proto->getName());
+
+        $json_name = $proto->hasJsonName() ? $proto->getJsonName() :
+            lcfirst(implode('', array_map('ucwords', explode('_', $proto->getName()))));
+        if ($proto->hasJsonName()) {
+            $json_name = $proto->getJsonName();
+        } else {
+            $proto_name = $proto->getName();
+            $json_name = implode('', array_map('ucwords', explode('_', $proto_name)));
+            if ($proto_name[0] !== "_" && !ctype_upper($proto_name[0])) {
+                $json_name = lcfirst($json_name);
+            }
+        }
+        $field->setJsonName($json_name);
+
+        $camel_name = implode('', array_map('ucwords', explode('_', $proto->getName())));
+        $field->setGetter('get' . $camel_name);
+        $field->setSetter('set' . $camel_name);
+        $field->setType($proto->getType());
+        $field->setNumber($proto->getNumber());
+        $field->setLabel($proto->getLabel());
+        $field->setPacked($packed);
+        $field->setOneofIndex($oneof_index);
+
+        // At this time, the message/enum type may have not been added to pool.
+        // So we use the type name as place holder and will replace it with the
+        // actual descriptor in cross building.
+        switch ($type) {
+            case GPBType::MESSAGE:
+                $field->setMessageType($type_name);
+                break;
+            case GPBType::ENUM:
+                $field->setEnumType($type_name);
+                break;
+            default:
+                break;
+        }
+
+        return $field;
+    }
+
+    public static function buildFromProto($proto)
+    {
+        return FieldDescriptor::getFieldDescriptor($proto);
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
index 6ae2cd4..10c2759 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
@@ -8,103 +8,88 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a field within a message.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.FieldDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.FieldDescriptorProto</code>
  */
 class FieldDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <code>optional int32 number = 3;</code>
+     * Generated from protobuf field <code>optional int32 number = 3;</code>
      */
     private $number = 0;
     private $has_number = false;
     /**
-     * <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
      */
     private $label = 0;
     private $has_label = false;
     /**
-     * <pre>
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
-     * </pre>
      *
-     * <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
      */
     private $type = 0;
     private $has_type = false;
     /**
-     * <pre>
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
      * rules are used to find the type (i.e. first the nested types within this
      * message are searched, then within the parent, on up to the root
      * namespace).
-     * </pre>
      *
-     * <code>optional string type_name = 6;</code>
+     * Generated from protobuf field <code>optional string type_name = 6;</code>
      */
     private $type_name = '';
     private $has_type_name = false;
     /**
-     * <pre>
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
-     * </pre>
      *
-     * <code>optional string extendee = 2;</code>
+     * Generated from protobuf field <code>optional string extendee = 2;</code>
      */
     private $extendee = '';
     private $has_extendee = false;
     /**
-     * <pre>
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
      * For strings, contains the default text contents (not escaped in any way).
-     * For bytes, contains the C escaped value.  All bytes &gt;= 128 are escaped.
+     * For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
      * TODO(kenton):  Base-64 encode?
-     * </pre>
      *
-     * <code>optional string default_value = 7;</code>
+     * Generated from protobuf field <code>optional string default_value = 7;</code>
      */
     private $default_value = '';
     private $has_default_value = false;
     /**
-     * <pre>
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
-     * </pre>
      *
-     * <code>optional int32 oneof_index = 9;</code>
+     * Generated from protobuf field <code>optional int32 oneof_index = 9;</code>
      */
     private $oneof_index = 0;
     private $has_oneof_index = false;
     /**
-     * <pre>
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
      * will be used. Otherwise, it's deduced from the field's name by converting
      * it to camelCase.
-     * </pre>
      *
-     * <code>optional string json_name = 10;</code>
+     * Generated from protobuf field <code>optional string json_name = 10;</code>
      */
     private $json_name = '';
     private $has_json_name = false;
     /**
-     * <code>optional .google.protobuf.FieldOptions options = 8;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
      */
     private $options = null;
     private $has_options = false;
@@ -115,7 +100,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -123,13 +109,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -138,7 +128,8 @@
     }
 
     /**
-     * <code>optional int32 number = 3;</code>
+     * Generated from protobuf field <code>optional int32 number = 3;</code>
+     * @return int
      */
     public function getNumber()
     {
@@ -146,13 +137,17 @@
     }
 
     /**
-     * <code>optional int32 number = 3;</code>
+     * Generated from protobuf field <code>optional int32 number = 3;</code>
+     * @param int $var
+     * @return $this
      */
     public function setNumber($var)
     {
         GPBUtil::checkInt32($var);
         $this->number = $var;
         $this->has_number = true;
+
+        return $this;
     }
 
     public function hasNumber()
@@ -161,7 +156,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
+     * @return int
      */
     public function getLabel()
     {
@@ -169,13 +165,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Label label = 4;</code>
+     * @param int $var
+     * @return $this
      */
     public function setLabel($var)
     {
         GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class);
         $this->label = $var;
         $this->has_label = true;
+
+        return $this;
     }
 
     public function hasLabel()
@@ -184,12 +184,11 @@
     }
 
     /**
-     * <pre>
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
-     * </pre>
      *
-     * <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
+     * @return int
      */
     public function getType()
     {
@@ -197,18 +196,20 @@
     }
 
     /**
-     * <pre>
      * If type_name is set, this need not be set.  If both this and type_name
      * are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
-     * </pre>
      *
-     * <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldDescriptorProto.Type type = 5;</code>
+     * @param int $var
+     * @return $this
      */
     public function setType($var)
     {
         GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class);
         $this->type = $var;
         $this->has_type = true;
+
+        return $this;
     }
 
     public function hasType()
@@ -217,15 +218,14 @@
     }
 
     /**
-     * <pre>
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
      * rules are used to find the type (i.e. first the nested types within this
      * message are searched, then within the parent, on up to the root
      * namespace).
-     * </pre>
      *
-     * <code>optional string type_name = 6;</code>
+     * Generated from protobuf field <code>optional string type_name = 6;</code>
+     * @return string
      */
     public function getTypeName()
     {
@@ -233,21 +233,23 @@
     }
 
     /**
-     * <pre>
      * For message and enum types, this is the name of the type.  If the name
      * starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
      * rules are used to find the type (i.e. first the nested types within this
      * message are searched, then within the parent, on up to the root
      * namespace).
-     * </pre>
      *
-     * <code>optional string type_name = 6;</code>
+     * Generated from protobuf field <code>optional string type_name = 6;</code>
+     * @param string $var
+     * @return $this
      */
     public function setTypeName($var)
     {
         GPBUtil::checkString($var, True);
         $this->type_name = $var;
         $this->has_type_name = true;
+
+        return $this;
     }
 
     public function hasTypeName()
@@ -256,12 +258,11 @@
     }
 
     /**
-     * <pre>
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
-     * </pre>
      *
-     * <code>optional string extendee = 2;</code>
+     * Generated from protobuf field <code>optional string extendee = 2;</code>
+     * @return string
      */
     public function getExtendee()
     {
@@ -269,18 +270,20 @@
     }
 
     /**
-     * <pre>
      * For extensions, this is the name of the type being extended.  It is
      * resolved in the same manner as type_name.
-     * </pre>
      *
-     * <code>optional string extendee = 2;</code>
+     * Generated from protobuf field <code>optional string extendee = 2;</code>
+     * @param string $var
+     * @return $this
      */
     public function setExtendee($var)
     {
         GPBUtil::checkString($var, True);
         $this->extendee = $var;
         $this->has_extendee = true;
+
+        return $this;
     }
 
     public function hasExtendee()
@@ -289,15 +292,14 @@
     }
 
     /**
-     * <pre>
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
      * For strings, contains the default text contents (not escaped in any way).
-     * For bytes, contains the C escaped value.  All bytes &gt;= 128 are escaped.
+     * For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
      * TODO(kenton):  Base-64 encode?
-     * </pre>
      *
-     * <code>optional string default_value = 7;</code>
+     * Generated from protobuf field <code>optional string default_value = 7;</code>
+     * @return string
      */
     public function getDefaultValue()
     {
@@ -305,21 +307,23 @@
     }
 
     /**
-     * <pre>
      * For numeric types, contains the original text representation of the value.
      * For booleans, "true" or "false".
      * For strings, contains the default text contents (not escaped in any way).
-     * For bytes, contains the C escaped value.  All bytes &gt;= 128 are escaped.
+     * For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
      * TODO(kenton):  Base-64 encode?
-     * </pre>
      *
-     * <code>optional string default_value = 7;</code>
+     * Generated from protobuf field <code>optional string default_value = 7;</code>
+     * @param string $var
+     * @return $this
      */
     public function setDefaultValue($var)
     {
         GPBUtil::checkString($var, True);
         $this->default_value = $var;
         $this->has_default_value = true;
+
+        return $this;
     }
 
     public function hasDefaultValue()
@@ -328,12 +332,11 @@
     }
 
     /**
-     * <pre>
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
-     * </pre>
      *
-     * <code>optional int32 oneof_index = 9;</code>
+     * Generated from protobuf field <code>optional int32 oneof_index = 9;</code>
+     * @return int
      */
     public function getOneofIndex()
     {
@@ -341,18 +344,20 @@
     }
 
     /**
-     * <pre>
      * If set, gives the index of a oneof in the containing type's oneof_decl
      * list.  This field is a member of that oneof.
-     * </pre>
      *
-     * <code>optional int32 oneof_index = 9;</code>
+     * Generated from protobuf field <code>optional int32 oneof_index = 9;</code>
+     * @param int $var
+     * @return $this
      */
     public function setOneofIndex($var)
     {
         GPBUtil::checkInt32($var);
         $this->oneof_index = $var;
         $this->has_oneof_index = true;
+
+        return $this;
     }
 
     public function hasOneofIndex()
@@ -361,14 +366,13 @@
     }
 
     /**
-     * <pre>
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
      * will be used. Otherwise, it's deduced from the field's name by converting
      * it to camelCase.
-     * </pre>
      *
-     * <code>optional string json_name = 10;</code>
+     * Generated from protobuf field <code>optional string json_name = 10;</code>
+     * @return string
      */
     public function getJsonName()
     {
@@ -376,20 +380,22 @@
     }
 
     /**
-     * <pre>
      * JSON name of this field. The value is set by protocol compiler. If the
      * user has set a "json_name" option on this field, that option's value
      * will be used. Otherwise, it's deduced from the field's name by converting
      * it to camelCase.
-     * </pre>
      *
-     * <code>optional string json_name = 10;</code>
+     * Generated from protobuf field <code>optional string json_name = 10;</code>
+     * @param string $var
+     * @return $this
      */
     public function setJsonName($var)
     {
         GPBUtil::checkString($var, True);
         $this->json_name = $var;
         $this->has_json_name = true;
+
+        return $this;
     }
 
     public function hasJsonName()
@@ -398,7 +404,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FieldOptions options = 8;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
+     * @return \Google\Protobuf\Internal\FieldOptions
      */
     public function getOptions()
     {
@@ -406,13 +413,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FieldOptions options = 8;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
+     * @param \Google\Protobuf\Internal\FieldOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FieldOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php
index a3cd8ef..f2a32fd 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php
@@ -5,24 +5,22 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * Protobuf enum <code>google.protobuf.FieldDescriptorProto.Label</code>
+ * Protobuf enum <code>Google\Protobuf\Internal</code>
  */
 class FieldDescriptorProto_Label
 {
     /**
-     * <pre>
      * 0 is reserved for errors
-     * </pre>
      *
-     * <code>LABEL_OPTIONAL = 1;</code>
+     * Generated from protobuf enum <code>LABEL_OPTIONAL = 1;</code>
      */
     const LABEL_OPTIONAL = 1;
     /**
-     * <code>LABEL_REQUIRED = 2;</code>
+     * Generated from protobuf enum <code>LABEL_REQUIRED = 2;</code>
      */
     const LABEL_REQUIRED = 2;
     /**
-     * <code>LABEL_REPEATED = 3;</code>
+     * Generated from protobuf enum <code>LABEL_REPEATED = 3;</code>
      */
     const LABEL_REPEATED = 3;
 }
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
index 8335f9b..1b022de 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php
@@ -5,118 +5,102 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * Protobuf enum <code>google.protobuf.FieldDescriptorProto.Type</code>
+ * Protobuf enum <code>Google\Protobuf\Internal</code>
  */
 class FieldDescriptorProto_Type
 {
     /**
-     * <pre>
      * 0 is reserved for errors.
      * Order is weird for historical reasons.
-     * </pre>
      *
-     * <code>TYPE_DOUBLE = 1;</code>
+     * Generated from protobuf enum <code>TYPE_DOUBLE = 1;</code>
      */
     const TYPE_DOUBLE = 1;
     /**
-     * <code>TYPE_FLOAT = 2;</code>
+     * Generated from protobuf enum <code>TYPE_FLOAT = 2;</code>
      */
     const TYPE_FLOAT = 2;
     /**
-     * <pre>
      * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
      * negative values are likely.
-     * </pre>
      *
-     * <code>TYPE_INT64 = 3;</code>
+     * Generated from protobuf enum <code>TYPE_INT64 = 3;</code>
      */
     const TYPE_INT64 = 3;
     /**
-     * <code>TYPE_UINT64 = 4;</code>
+     * Generated from protobuf enum <code>TYPE_UINT64 = 4;</code>
      */
     const TYPE_UINT64 = 4;
     /**
-     * <pre>
      * Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
      * negative values are likely.
-     * </pre>
      *
-     * <code>TYPE_INT32 = 5;</code>
+     * Generated from protobuf enum <code>TYPE_INT32 = 5;</code>
      */
     const TYPE_INT32 = 5;
     /**
-     * <code>TYPE_FIXED64 = 6;</code>
+     * Generated from protobuf enum <code>TYPE_FIXED64 = 6;</code>
      */
     const TYPE_FIXED64 = 6;
     /**
-     * <code>TYPE_FIXED32 = 7;</code>
+     * Generated from protobuf enum <code>TYPE_FIXED32 = 7;</code>
      */
     const TYPE_FIXED32 = 7;
     /**
-     * <code>TYPE_BOOL = 8;</code>
+     * Generated from protobuf enum <code>TYPE_BOOL = 8;</code>
      */
     const TYPE_BOOL = 8;
     /**
-     * <code>TYPE_STRING = 9;</code>
+     * Generated from protobuf enum <code>TYPE_STRING = 9;</code>
      */
     const TYPE_STRING = 9;
     /**
-     * <pre>
      * Tag-delimited aggregate.
      * Group type is deprecated and not supported in proto3. However, Proto3
      * implementations should still be able to parse the group wire format and
      * treat group fields as unknown fields.
-     * </pre>
      *
-     * <code>TYPE_GROUP = 10;</code>
+     * Generated from protobuf enum <code>TYPE_GROUP = 10;</code>
      */
     const TYPE_GROUP = 10;
     /**
-     * <pre>
      * Length-delimited aggregate.
-     * </pre>
      *
-     * <code>TYPE_MESSAGE = 11;</code>
+     * Generated from protobuf enum <code>TYPE_MESSAGE = 11;</code>
      */
     const TYPE_MESSAGE = 11;
     /**
-     * <pre>
      * New in version 2.
-     * </pre>
      *
-     * <code>TYPE_BYTES = 12;</code>
+     * Generated from protobuf enum <code>TYPE_BYTES = 12;</code>
      */
     const TYPE_BYTES = 12;
     /**
-     * <code>TYPE_UINT32 = 13;</code>
+     * Generated from protobuf enum <code>TYPE_UINT32 = 13;</code>
      */
     const TYPE_UINT32 = 13;
     /**
-     * <code>TYPE_ENUM = 14;</code>
+     * Generated from protobuf enum <code>TYPE_ENUM = 14;</code>
      */
     const TYPE_ENUM = 14;
     /**
-     * <code>TYPE_SFIXED32 = 15;</code>
+     * Generated from protobuf enum <code>TYPE_SFIXED32 = 15;</code>
      */
     const TYPE_SFIXED32 = 15;
     /**
-     * <code>TYPE_SFIXED64 = 16;</code>
+     * Generated from protobuf enum <code>TYPE_SFIXED64 = 16;</code>
      */
     const TYPE_SFIXED64 = 16;
     /**
-     * <pre>
      * Uses ZigZag encoding.
-     * </pre>
      *
-     * <code>TYPE_SINT32 = 17;</code>
+     * Generated from protobuf enum <code>TYPE_SINT32 = 17;</code>
      */
     const TYPE_SINT32 = 17;
     /**
-     * <pre>
      * Uses ZigZag encoding.
-     * </pre>
      *
-     * <code>TYPE_SINT64 = 18;</code>
+     * Generated from protobuf enum <code>TYPE_SINT64 = 18;</code>
      */
     const TYPE_SINT64 = 18;
 }
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions.php b/php/src/Google/Protobuf/Internal/FieldOptions.php
index 8db7ed6..169f860 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions.php
@@ -8,58 +8,51 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.FieldOptions</code>
+ * Generated from protobuf message <code>google.protobuf.FieldOptions</code>
  */
 class FieldOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * The ctype option instructs the C++ code generator to use a different
      * representation of the field than it normally would.  See the specific
      * options below.  This option is not yet implemented in the open source
      * release -- sorry, we'll try to include it in a future version!
-     * </pre>
      *
-     * <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
      */
     private $ctype = 0;
     private $has_ctype = false;
     /**
-     * <pre>
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
      * writing the tag and type for each element, the entire array is encoded as
      * a single length-delimited blob. In proto3, only explicit setting it to
      * false will avoid using packed encoding.
-     * </pre>
      *
-     * <code>optional bool packed = 2;</code>
+     * Generated from protobuf field <code>optional bool packed = 2;</code>
      */
     private $packed = false;
     private $has_packed = false;
     /**
-     * <pre>
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
-     * (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
-     * represented as JavaScript strings.  This avoids loss of precision that can
-     * happen when a large value is converted to a floating point JavaScript
-     * numbers.  Specifying JS_NUMBER for the jstype causes the generated
-     * JavaScript code to use the JavaScript "number" type instead of strings.
-     * This option is an enum to permit additional types to be added,
-     * e.g. goog.math.Integer.
-     * </pre>
+     * (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+     * is represented as JavaScript string, which avoids loss of precision that
+     * can happen when a large value is converted to a floating point JavaScript.
+     * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+     * use the JavaScript "number" type.  The behavior of the default option
+     * JS_NORMAL is implementation dependent.
+     * This option is an enum to permit additional types to be added, e.g.
+     * goog.math.Integer.
      *
-     * <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
      */
     private $jstype = 0;
     private $has_jstype = false;
     /**
-     * <pre>
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
      * inner message's contents will not be parsed but instead stored in encoded
@@ -84,39 +77,32 @@
      * implementation must either *always* check its required fields, or *never*
      * check its required fields, regardless of whether or not the message has
      * been parsed.
-     * </pre>
      *
-     * <code>optional bool lazy = 5 [default = false];</code>
+     * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
      */
     private $lazy = false;
     private $has_lazy = false;
     /**
-     * <pre>
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for accessors, or it will be completely ignored; in the very least, this
      * is a formalization for deprecating fields.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <pre>
      * For Google-internal migration only. Do not use.
-     * </pre>
      *
-     * <code>optional bool weak = 10 [default = false];</code>
+     * Generated from protobuf field <code>optional bool weak = 10 [default = false];</code>
      */
     private $weak = false;
     private $has_weak = false;
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -127,14 +113,13 @@
     }
 
     /**
-     * <pre>
      * The ctype option instructs the C++ code generator to use a different
      * representation of the field than it normally would.  See the specific
      * options below.  This option is not yet implemented in the open source
      * release -- sorry, we'll try to include it in a future version!
-     * </pre>
      *
-     * <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
+     * @return int
      */
     public function getCtype()
     {
@@ -142,20 +127,22 @@
     }
 
     /**
-     * <pre>
      * The ctype option instructs the C++ code generator to use a different
      * representation of the field than it normally would.  See the specific
      * options below.  This option is not yet implemented in the open source
      * release -- sorry, we'll try to include it in a future version!
-     * </pre>
      *
-     * <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];</code>
+     * @param int $var
+     * @return $this
      */
     public function setCtype($var)
     {
         GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_CType::class);
         $this->ctype = $var;
         $this->has_ctype = true;
+
+        return $this;
     }
 
     public function hasCtype()
@@ -164,15 +151,14 @@
     }
 
     /**
-     * <pre>
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
      * writing the tag and type for each element, the entire array is encoded as
      * a single length-delimited blob. In proto3, only explicit setting it to
      * false will avoid using packed encoding.
-     * </pre>
      *
-     * <code>optional bool packed = 2;</code>
+     * Generated from protobuf field <code>optional bool packed = 2;</code>
+     * @return bool
      */
     public function getPacked()
     {
@@ -180,21 +166,23 @@
     }
 
     /**
-     * <pre>
      * The packed option can be enabled for repeated primitive fields to enable
      * a more efficient representation on the wire. Rather than repeatedly
      * writing the tag and type for each element, the entire array is encoded as
      * a single length-delimited blob. In proto3, only explicit setting it to
      * false will avoid using packed encoding.
-     * </pre>
      *
-     * <code>optional bool packed = 2;</code>
+     * Generated from protobuf field <code>optional bool packed = 2;</code>
+     * @param bool $var
+     * @return $this
      */
     public function setPacked($var)
     {
         GPBUtil::checkBool($var);
         $this->packed = $var;
         $this->has_packed = true;
+
+        return $this;
     }
 
     public function hasPacked()
@@ -203,19 +191,19 @@
     }
 
     /**
-     * <pre>
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
-     * (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
-     * represented as JavaScript strings.  This avoids loss of precision that can
-     * happen when a large value is converted to a floating point JavaScript
-     * numbers.  Specifying JS_NUMBER for the jstype causes the generated
-     * JavaScript code to use the JavaScript "number" type instead of strings.
-     * This option is an enum to permit additional types to be added,
-     * e.g. goog.math.Integer.
-     * </pre>
+     * (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+     * is represented as JavaScript string, which avoids loss of precision that
+     * can happen when a large value is converted to a floating point JavaScript.
+     * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+     * use the JavaScript "number" type.  The behavior of the default option
+     * JS_NORMAL is implementation dependent.
+     * This option is an enum to permit additional types to be added, e.g.
+     * goog.math.Integer.
      *
-     * <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
+     * @return int
      */
     public function getJstype()
     {
@@ -223,25 +211,28 @@
     }
 
     /**
-     * <pre>
      * The jstype option determines the JavaScript type used for values of the
      * field.  The option is permitted only for 64 bit integral and fixed types
-     * (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
-     * represented as JavaScript strings.  This avoids loss of precision that can
-     * happen when a large value is converted to a floating point JavaScript
-     * numbers.  Specifying JS_NUMBER for the jstype causes the generated
-     * JavaScript code to use the JavaScript "number" type instead of strings.
-     * This option is an enum to permit additional types to be added,
-     * e.g. goog.math.Integer.
-     * </pre>
+     * (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+     * is represented as JavaScript string, which avoids loss of precision that
+     * can happen when a large value is converted to a floating point JavaScript.
+     * Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+     * use the JavaScript "number" type.  The behavior of the default option
+     * JS_NORMAL is implementation dependent.
+     * This option is an enum to permit additional types to be added, e.g.
+     * goog.math.Integer.
      *
-     * <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];</code>
+     * @param int $var
+     * @return $this
      */
     public function setJstype($var)
     {
         GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FieldOptions_JSType::class);
         $this->jstype = $var;
         $this->has_jstype = true;
+
+        return $this;
     }
 
     public function hasJstype()
@@ -250,7 +241,6 @@
     }
 
     /**
-     * <pre>
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
      * inner message's contents will not be parsed but instead stored in encoded
@@ -275,9 +265,9 @@
      * implementation must either *always* check its required fields, or *never*
      * check its required fields, regardless of whether or not the message has
      * been parsed.
-     * </pre>
      *
-     * <code>optional bool lazy = 5 [default = false];</code>
+     * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
+     * @return bool
      */
     public function getLazy()
     {
@@ -285,7 +275,6 @@
     }
 
     /**
-     * <pre>
      * Should this field be parsed lazily?  Lazy applies only to message-type
      * fields.  It means that when the outer message is initially parsed, the
      * inner message's contents will not be parsed but instead stored in encoded
@@ -310,15 +299,18 @@
      * implementation must either *always* check its required fields, or *never*
      * check its required fields, regardless of whether or not the message has
      * been parsed.
-     * </pre>
      *
-     * <code>optional bool lazy = 5 [default = false];</code>
+     * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setLazy($var)
     {
         GPBUtil::checkBool($var);
         $this->lazy = $var;
         $this->has_lazy = true;
+
+        return $this;
     }
 
     public function hasLazy()
@@ -327,14 +319,13 @@
     }
 
     /**
-     * <pre>
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for accessors, or it will be completely ignored; in the very least, this
      * is a formalization for deprecating fields.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -342,20 +333,22 @@
     }
 
     /**
-     * <pre>
      * Is this field deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for accessors, or it will be completely ignored; in the very least, this
      * is a formalization for deprecating fields.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -364,11 +357,10 @@
     }
 
     /**
-     * <pre>
      * For Google-internal migration only. Do not use.
-     * </pre>
      *
-     * <code>optional bool weak = 10 [default = false];</code>
+     * Generated from protobuf field <code>optional bool weak = 10 [default = false];</code>
+     * @return bool
      */
     public function getWeak()
     {
@@ -376,17 +368,19 @@
     }
 
     /**
-     * <pre>
      * For Google-internal migration only. Do not use.
-     * </pre>
      *
-     * <code>optional bool weak = 10 [default = false];</code>
+     * Generated from protobuf field <code>optional bool weak = 10 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setWeak($var)
     {
         GPBUtil::checkBool($var);
         $this->weak = $var;
         $this->has_weak = true;
+
+        return $this;
     }
 
     public function hasWeak()
@@ -395,11 +389,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -407,17 +400,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php b/php/src/Google/Protobuf/Internal/FieldOptions_CType.php
index f59f20b..0f33072 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions_CType.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions_CType.php
@@ -5,24 +5,22 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * Protobuf enum <code>google.protobuf.FieldOptions.CType</code>
+ * Protobuf enum <code>Google\Protobuf\Internal</code>
  */
 class FieldOptions_CType
 {
     /**
-     * <pre>
      * Default mode.
-     * </pre>
      *
-     * <code>STRING = 0;</code>
+     * Generated from protobuf enum <code>STRING = 0;</code>
      */
     const STRING = 0;
     /**
-     * <code>CORD = 1;</code>
+     * Generated from protobuf enum <code>CORD = 1;</code>
      */
     const CORD = 1;
     /**
-     * <code>STRING_PIECE = 2;</code>
+     * Generated from protobuf enum <code>STRING_PIECE = 2;</code>
      */
     const STRING_PIECE = 2;
 }
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php b/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php
index 0c6995b..73bdf3f 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions_JSType.php
@@ -5,32 +5,26 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * Protobuf enum <code>google.protobuf.FieldOptions.JSType</code>
+ * Protobuf enum <code>Google\Protobuf\Internal</code>
  */
 class FieldOptions_JSType
 {
     /**
-     * <pre>
      * Use the default type.
-     * </pre>
      *
-     * <code>JS_NORMAL = 0;</code>
+     * Generated from protobuf enum <code>JS_NORMAL = 0;</code>
      */
     const JS_NORMAL = 0;
     /**
-     * <pre>
      * Use JavaScript strings.
-     * </pre>
      *
-     * <code>JS_STRING = 1;</code>
+     * Generated from protobuf enum <code>JS_STRING = 1;</code>
      */
     const JS_STRING = 1;
     /**
-     * <pre>
      * Use JavaScript numbers.
-     * </pre>
      *
-     * <code>JS_NUMBER = 2;</code>
+     * Generated from protobuf enum <code>JS_NUMBER = 2;</code>
      */
     const JS_NUMBER = 2;
 }
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptor.php b/php/src/Google/Protobuf/Internal/FileDescriptor.php
new file mode 100644
index 0000000..038da38
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/FileDescriptor.php
@@ -0,0 +1,89 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class FileDescriptor
+{
+
+    private $package;
+    private $message_type = [];
+    private $enum_type = [];
+
+    public function setPackage($package)
+    {
+        $this->package = $package;
+    }
+
+    public function getPackage()
+    {
+        return $this->package;
+    }
+
+    public function getMessageType()
+    {
+        return $this->message_type;
+    }
+
+    public function addMessageType($desc)
+    {
+        $this->message_type[] = $desc;
+    }
+
+    public function getEnumType()
+    {
+        return $this->enum_type;
+    }
+
+    public function addEnumType($desc)
+    {
+        $this->enum_type[]= $desc;
+    }
+
+    public static function buildFromProto($proto)
+    {
+        $file = new FileDescriptor();
+        $file->setPackage($proto->getPackage());
+        foreach ($proto->getMessageType() as $message_proto) {
+            $file->addMessageType(Descriptor::buildFromProto(
+                $message_proto, $proto, ""));
+        }
+        foreach ($proto->getEnumType() as $enum_proto) {
+            $file->addEnumType(
+                EnumDescriptor::buildFromProto(
+                    $enum_proto,
+                    $proto,
+                    ""));
+        }
+        return $file;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
index 0363d9e..9ee222d 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
@@ -8,112 +8,93 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a complete .proto file.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.FileDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.FileDescriptorProto</code>
  */
 class FileDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * file name, relative to root of source tree
-     * </pre>
      *
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <pre>
      * e.g. "foo", "foo.bar", etc.
-     * </pre>
      *
-     * <code>optional string package = 2;</code>
+     * Generated from protobuf field <code>optional string package = 2;</code>
      */
     private $package = '';
     private $has_package = false;
     /**
-     * <pre>
      * Names of files imported by this file.
-     * </pre>
      *
-     * <code>repeated string dependency = 3;</code>
+     * Generated from protobuf field <code>repeated string dependency = 3;</code>
      */
     private $dependency;
     private $has_dependency = false;
     /**
-     * <pre>
      * Indexes of the public imported files in the dependency list above.
-     * </pre>
      *
-     * <code>repeated int32 public_dependency = 10;</code>
+     * Generated from protobuf field <code>repeated int32 public_dependency = 10;</code>
      */
     private $public_dependency;
     private $has_public_dependency = false;
     /**
-     * <pre>
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
-     * </pre>
      *
-     * <code>repeated int32 weak_dependency = 11;</code>
+     * Generated from protobuf field <code>repeated int32 weak_dependency = 11;</code>
      */
     private $weak_dependency;
     private $has_weak_dependency = false;
     /**
-     * <pre>
      * All top-level definitions in this file.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
      */
     private $message_type;
     private $has_message_type = false;
     /**
-     * <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
      */
     private $enum_type;
     private $has_enum_type = false;
     /**
-     * <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
      */
     private $service;
     private $has_service = false;
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
      */
     private $extension;
     private $has_extension = false;
     /**
-     * <code>optional .google.protobuf.FileOptions options = 8;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
      */
     private $options = null;
     private $has_options = false;
     /**
-     * <pre>
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
      * functionality of the descriptors -- the information is needed only by
      * development tools.
-     * </pre>
      *
-     * <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
      */
     private $source_code_info = null;
     private $has_source_code_info = false;
     /**
-     * <pre>
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
-     * </pre>
      *
-     * <code>optional string syntax = 12;</code>
+     * Generated from protobuf field <code>optional string syntax = 12;</code>
      */
     private $syntax = '';
     private $has_syntax = false;
@@ -124,11 +105,10 @@
     }
 
     /**
-     * <pre>
      * file name, relative to root of source tree
-     * </pre>
      *
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -136,17 +116,19 @@
     }
 
     /**
-     * <pre>
      * file name, relative to root of source tree
-     * </pre>
      *
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -155,11 +137,10 @@
     }
 
     /**
-     * <pre>
      * e.g. "foo", "foo.bar", etc.
-     * </pre>
      *
-     * <code>optional string package = 2;</code>
+     * Generated from protobuf field <code>optional string package = 2;</code>
+     * @return string
      */
     public function getPackage()
     {
@@ -167,17 +148,19 @@
     }
 
     /**
-     * <pre>
      * e.g. "foo", "foo.bar", etc.
-     * </pre>
      *
-     * <code>optional string package = 2;</code>
+     * Generated from protobuf field <code>optional string package = 2;</code>
+     * @param string $var
+     * @return $this
      */
     public function setPackage($var)
     {
         GPBUtil::checkString($var, True);
         $this->package = $var;
         $this->has_package = true;
+
+        return $this;
     }
 
     public function hasPackage()
@@ -186,11 +169,10 @@
     }
 
     /**
-     * <pre>
      * Names of files imported by this file.
-     * </pre>
      *
-     * <code>repeated string dependency = 3;</code>
+     * Generated from protobuf field <code>repeated string dependency = 3;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getDependency()
     {
@@ -198,17 +180,19 @@
     }
 
     /**
-     * <pre>
      * Names of files imported by this file.
-     * </pre>
      *
-     * <code>repeated string dependency = 3;</code>
+     * Generated from protobuf field <code>repeated string dependency = 3;</code>
+     * @param string[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setDependency(&$var)
+    public function setDependency($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->dependency = $arr;
         $this->has_dependency = true;
+
+        return $this;
     }
 
     public function hasDependency()
@@ -217,11 +201,10 @@
     }
 
     /**
-     * <pre>
      * Indexes of the public imported files in the dependency list above.
-     * </pre>
      *
-     * <code>repeated int32 public_dependency = 10;</code>
+     * Generated from protobuf field <code>repeated int32 public_dependency = 10;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getPublicDependency()
     {
@@ -229,17 +212,19 @@
     }
 
     /**
-     * <pre>
      * Indexes of the public imported files in the dependency list above.
-     * </pre>
      *
-     * <code>repeated int32 public_dependency = 10;</code>
+     * Generated from protobuf field <code>repeated int32 public_dependency = 10;</code>
+     * @param int[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setPublicDependency(&$var)
+    public function setPublicDependency($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->public_dependency = $arr;
         $this->has_public_dependency = true;
+
+        return $this;
     }
 
     public function hasPublicDependency()
@@ -248,12 +233,11 @@
     }
 
     /**
-     * <pre>
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
-     * </pre>
      *
-     * <code>repeated int32 weak_dependency = 11;</code>
+     * Generated from protobuf field <code>repeated int32 weak_dependency = 11;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getWeakDependency()
     {
@@ -261,18 +245,20 @@
     }
 
     /**
-     * <pre>
      * Indexes of the weak imported files in the dependency list.
      * For Google-internal migration only. Do not use.
-     * </pre>
      *
-     * <code>repeated int32 weak_dependency = 11;</code>
+     * Generated from protobuf field <code>repeated int32 weak_dependency = 11;</code>
+     * @param int[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setWeakDependency(&$var)
+    public function setWeakDependency($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->weak_dependency = $arr;
         $this->has_weak_dependency = true;
+
+        return $this;
     }
 
     public function hasWeakDependency()
@@ -281,11 +267,10 @@
     }
 
     /**
-     * <pre>
      * All top-level definitions in this file.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getMessageType()
     {
@@ -293,17 +278,19 @@
     }
 
     /**
-     * <pre>
      * All top-level definitions in this file.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto message_type = 4;</code>
+     * @param \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setMessageType(&$var)
+    public function setMessageType($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto::class);
         $this->message_type = $arr;
         $this->has_message_type = true;
+
+        return $this;
     }
 
     public function hasMessageType()
@@ -312,7 +299,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getEnumType()
     {
@@ -320,13 +308,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto enum_type = 5;</code>
+     * @param \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setEnumType(&$var)
+    public function setEnumType($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto::class);
         $this->enum_type = $arr;
         $this->has_enum_type = true;
+
+        return $this;
     }
 
     public function hasEnumType()
@@ -335,7 +327,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getService()
     {
@@ -343,13 +336,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.ServiceDescriptorProto service = 6;</code>
+     * @param \Google\Protobuf\Internal\ServiceDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setService(&$var)
+    public function setService($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ServiceDescriptorProto::class);
         $this->service = $arr;
         $this->has_service = true;
+
+        return $this;
     }
 
     public function hasService()
@@ -358,7 +355,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getExtension()
     {
@@ -366,13 +364,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FieldDescriptorProto extension = 7;</code>
+     * @param \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setExtension(&$var)
+    public function setExtension($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FieldDescriptorProto::class);
         $this->extension = $arr;
         $this->has_extension = true;
+
+        return $this;
     }
 
     public function hasExtension()
@@ -381,7 +383,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FileOptions options = 8;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
+     * @return \Google\Protobuf\Internal\FileOptions
      */
     public function getOptions()
     {
@@ -389,13 +392,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FileOptions options = 8;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
+     * @param \Google\Protobuf\Internal\FileOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\FileOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
@@ -404,14 +411,13 @@
     }
 
     /**
-     * <pre>
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
      * functionality of the descriptors -- the information is needed only by
      * development tools.
-     * </pre>
      *
-     * <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
+     * @return \Google\Protobuf\Internal\SourceCodeInfo
      */
     public function getSourceCodeInfo()
     {
@@ -419,20 +425,22 @@
     }
 
     /**
-     * <pre>
      * This field contains optional information about the original source code.
      * You may safely remove this entire field without harming runtime
      * functionality of the descriptors -- the information is needed only by
      * development tools.
-     * </pre>
      *
-     * <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
+     * @param \Google\Protobuf\Internal\SourceCodeInfo $var
+     * @return $this
      */
-    public function setSourceCodeInfo(&$var)
+    public function setSourceCodeInfo($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\SourceCodeInfo::class);
         $this->source_code_info = $var;
         $this->has_source_code_info = true;
+
+        return $this;
     }
 
     public function hasSourceCodeInfo()
@@ -441,12 +449,11 @@
     }
 
     /**
-     * <pre>
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
-     * </pre>
      *
-     * <code>optional string syntax = 12;</code>
+     * Generated from protobuf field <code>optional string syntax = 12;</code>
+     * @return string
      */
     public function getSyntax()
     {
@@ -454,18 +461,20 @@
     }
 
     /**
-     * <pre>
      * The syntax of the proto file.
      * The supported values are "proto2" and "proto3".
-     * </pre>
      *
-     * <code>optional string syntax = 12;</code>
+     * Generated from protobuf field <code>optional string syntax = 12;</code>
+     * @param string $var
+     * @return $this
      */
     public function setSyntax($var)
     {
         GPBUtil::checkString($var, True);
         $this->syntax = $var;
         $this->has_syntax = true;
+
+        return $this;
     }
 
     public function hasSyntax()
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
index 0bcc805..0b2cf95 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorSet.php
@@ -8,21 +8,18 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * The protocol compiler can output a FileDescriptorSet containing the .proto
  * files it parses.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.FileDescriptorSet</code>
+ * Generated from protobuf message <code>google.protobuf.FileDescriptorSet</code>
  */
 class FileDescriptorSet extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
      */
     private $file;
     private $has_file = false;
@@ -33,7 +30,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getFile()
     {
@@ -41,13 +39,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.FileDescriptorProto file = 1;</code>
+     * @param \Google\Protobuf\Internal\FileDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setFile(&$var)
+    public function setFile($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\FileDescriptorProto::class);
         $this->file = $arr;
         $this->has_file = true;
+
+        return $this;
     }
 
     public function hasFile()
diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php
index 22653a4..c2dd5e0 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions.php
@@ -8,96 +8,82 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.FileOptions</code>
+ * Generated from protobuf message <code>google.protobuf.FileOptions</code>
  */
 class FileOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Sets the Java package where classes generated from this .proto will be
      * placed.  By default, the proto package is used, but this is often
      * inappropriate because proto packages do not normally start with backwards
      * domain names.
-     * </pre>
      *
-     * <code>optional string java_package = 1;</code>
+     * Generated from protobuf field <code>optional string java_package = 1;</code>
      */
     private $java_package = '';
     private $has_java_package = false;
     /**
-     * <pre>
      * If set, all the classes from the .proto file are wrapped in a single
      * outer class with the given name.  This applies to both Proto1
      * (equivalent to the old "--one_java_file" option) and Proto2 (where
      * a .proto always translates to a single class, but you may want to
      * explicitly choose the class name).
-     * </pre>
      *
-     * <code>optional string java_outer_classname = 8;</code>
+     * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      */
     private $java_outer_classname = '';
     private $has_java_outer_classname = false;
     /**
-     * <pre>
      * If set true, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
      * file.  Thus, these types will *not* be nested inside the outer class
      * named by java_outer_classname.  However, the outer class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
-     * </pre>
      *
-     * <code>optional bool java_multiple_files = 10 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_multiple_files = 10 [default = false];</code>
      */
     private $java_multiple_files = false;
     private $has_java_multiple_files = false;
     /**
-     * <pre>
      * This option does nothing.
-     * </pre>
      *
-     * <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
+     * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
      */
     private $java_generate_equals_and_hash = false;
     private $has_java_generate_equals_and_hash = false;
     /**
-     * <pre>
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
      * byte sequence to a string field.
      * Message reflection will do the same.
      * However, an extension field still accepts non-UTF-8 byte sequences.
      * This option has no effect on when used with the lite runtime.
-     * </pre>
      *
-     * <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
      */
     private $java_string_check_utf8 = false;
     private $has_java_string_check_utf8 = false;
     /**
-     * <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
      */
     private $optimize_for = 0;
     private $has_optimize_for = false;
     /**
-     * <pre>
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
      *   - The basename of the package import path, if provided.
      *   - Otherwise, the package statement in the .proto file, if present.
      *   - Otherwise, the basename of the .proto file, without extension.
-     * </pre>
      *
-     * <code>optional string go_package = 11;</code>
+     * Generated from protobuf field <code>optional string go_package = 11;</code>
      */
     private $go_package = '';
     private $has_go_package = false;
     /**
-     * <pre>
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
      * main code generators in each language (without additional plugins).
@@ -107,91 +93,90 @@
      * that generate code specific to your particular RPC system.  Therefore,
      * these default to false.  Old code which depends on generic services should
      * explicitly set them to true.
-     * </pre>
      *
-     * <code>optional bool cc_generic_services = 16 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_generic_services = 16 [default = false];</code>
      */
     private $cc_generic_services = false;
     private $has_cc_generic_services = false;
     /**
-     * <code>optional bool java_generic_services = 17 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
      */
     private $java_generic_services = false;
     private $has_java_generic_services = false;
     /**
-     * <code>optional bool py_generic_services = 18 [default = false];</code>
+     * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
      */
     private $py_generic_services = false;
     private $has_py_generic_services = false;
     /**
-     * <pre>
+     * Generated from protobuf field <code>optional bool php_generic_services = 19 [default = false];</code>
+     */
+    private $php_generic_services = false;
+    private $has_php_generic_services = false;
+    /**
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for everything in the file, or it will be completely ignored; in the very
      * least, this is a formalization for deprecating files.
-     * </pre>
      *
-     * <code>optional bool deprecated = 23 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 23 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <pre>
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
-     * </pre>
      *
-     * <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = false];</code>
      */
     private $cc_enable_arenas = false;
     private $has_cc_enable_arenas = false;
     /**
-     * <pre>
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
-     * </pre>
      *
-     * <code>optional string objc_class_prefix = 36;</code>
+     * Generated from protobuf field <code>optional string objc_class_prefix = 36;</code>
      */
     private $objc_class_prefix = '';
     private $has_objc_class_prefix = false;
     /**
-     * <pre>
      * Namespace for generated classes; defaults to the package.
-     * </pre>
      *
-     * <code>optional string csharp_namespace = 37;</code>
+     * Generated from protobuf field <code>optional string csharp_namespace = 37;</code>
      */
     private $csharp_namespace = '';
     private $has_csharp_namespace = false;
     /**
-     * <pre>
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
      * defined. When this options is provided, they will use this value instead
      * to prefix the types/symbols defined.
-     * </pre>
      *
-     * <code>optional string swift_prefix = 39;</code>
+     * Generated from protobuf field <code>optional string swift_prefix = 39;</code>
      */
     private $swift_prefix = '';
     private $has_swift_prefix = false;
     /**
-     * <pre>
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
-     * </pre>
      *
-     * <code>optional string php_class_prefix = 40;</code>
+     * Generated from protobuf field <code>optional string php_class_prefix = 40;</code>
      */
     private $php_class_prefix = '';
     private $has_php_class_prefix = false;
     /**
-     * <pre>
-     * The parser stores options it doesn't recognize here. See above.
-     * </pre>
+     * Use this option to change the namespace of php generated classes. Default
+     * is empty. When this option is empty, the package name will be used for
+     * determining the namespace.
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>optional string php_namespace = 41;</code>
+     */
+    private $php_namespace = '';
+    private $has_php_namespace = false;
+    /**
+     * The parser stores options it doesn't recognize here. See above.
+     *
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -202,14 +187,13 @@
     }
 
     /**
-     * <pre>
      * Sets the Java package where classes generated from this .proto will be
      * placed.  By default, the proto package is used, but this is often
      * inappropriate because proto packages do not normally start with backwards
      * domain names.
-     * </pre>
      *
-     * <code>optional string java_package = 1;</code>
+     * Generated from protobuf field <code>optional string java_package = 1;</code>
+     * @return string
      */
     public function getJavaPackage()
     {
@@ -217,20 +201,22 @@
     }
 
     /**
-     * <pre>
      * Sets the Java package where classes generated from this .proto will be
      * placed.  By default, the proto package is used, but this is often
      * inappropriate because proto packages do not normally start with backwards
      * domain names.
-     * </pre>
      *
-     * <code>optional string java_package = 1;</code>
+     * Generated from protobuf field <code>optional string java_package = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setJavaPackage($var)
     {
         GPBUtil::checkString($var, True);
         $this->java_package = $var;
         $this->has_java_package = true;
+
+        return $this;
     }
 
     public function hasJavaPackage()
@@ -239,15 +225,14 @@
     }
 
     /**
-     * <pre>
      * If set, all the classes from the .proto file are wrapped in a single
      * outer class with the given name.  This applies to both Proto1
      * (equivalent to the old "--one_java_file" option) and Proto2 (where
      * a .proto always translates to a single class, but you may want to
      * explicitly choose the class name).
-     * </pre>
      *
-     * <code>optional string java_outer_classname = 8;</code>
+     * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
+     * @return string
      */
     public function getJavaOuterClassname()
     {
@@ -255,21 +240,23 @@
     }
 
     /**
-     * <pre>
      * If set, all the classes from the .proto file are wrapped in a single
      * outer class with the given name.  This applies to both Proto1
      * (equivalent to the old "--one_java_file" option) and Proto2 (where
      * a .proto always translates to a single class, but you may want to
      * explicitly choose the class name).
-     * </pre>
      *
-     * <code>optional string java_outer_classname = 8;</code>
+     * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
+     * @param string $var
+     * @return $this
      */
     public function setJavaOuterClassname($var)
     {
         GPBUtil::checkString($var, True);
         $this->java_outer_classname = $var;
         $this->has_java_outer_classname = true;
+
+        return $this;
     }
 
     public function hasJavaOuterClassname()
@@ -278,16 +265,15 @@
     }
 
     /**
-     * <pre>
      * If set true, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
      * file.  Thus, these types will *not* be nested inside the outer class
      * named by java_outer_classname.  However, the outer class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
-     * </pre>
      *
-     * <code>optional bool java_multiple_files = 10 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_multiple_files = 10 [default = false];</code>
+     * @return bool
      */
     public function getJavaMultipleFiles()
     {
@@ -295,22 +281,24 @@
     }
 
     /**
-     * <pre>
      * If set true, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
      * file.  Thus, these types will *not* be nested inside the outer class
      * named by java_outer_classname.  However, the outer class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
-     * </pre>
      *
-     * <code>optional bool java_multiple_files = 10 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_multiple_files = 10 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setJavaMultipleFiles($var)
     {
         GPBUtil::checkBool($var);
         $this->java_multiple_files = $var;
         $this->has_java_multiple_files = true;
+
+        return $this;
     }
 
     public function hasJavaMultipleFiles()
@@ -319,11 +307,10 @@
     }
 
     /**
-     * <pre>
      * This option does nothing.
-     * </pre>
      *
-     * <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
+     * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
+     * @return bool
      */
     public function getJavaGenerateEqualsAndHash()
     {
@@ -331,17 +318,19 @@
     }
 
     /**
-     * <pre>
      * This option does nothing.
-     * </pre>
      *
-     * <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
+     * Generated from protobuf field <code>optional bool java_generate_equals_and_hash = 20 [deprecated = true];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setJavaGenerateEqualsAndHash($var)
     {
         GPBUtil::checkBool($var);
         $this->java_generate_equals_and_hash = $var;
         $this->has_java_generate_equals_and_hash = true;
+
+        return $this;
     }
 
     public function hasJavaGenerateEqualsAndHash()
@@ -350,16 +339,15 @@
     }
 
     /**
-     * <pre>
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
      * byte sequence to a string field.
      * Message reflection will do the same.
      * However, an extension field still accepts non-UTF-8 byte sequences.
      * This option has no effect on when used with the lite runtime.
-     * </pre>
      *
-     * <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
+     * @return bool
      */
     public function getJavaStringCheckUtf8()
     {
@@ -367,22 +355,24 @@
     }
 
     /**
-     * <pre>
      * If set true, then the Java2 code generator will generate code that
      * throws an exception whenever an attempt is made to assign a non-UTF-8
      * byte sequence to a string field.
      * Message reflection will do the same.
      * However, an extension field still accepts non-UTF-8 byte sequences.
      * This option has no effect on when used with the lite runtime.
-     * </pre>
      *
-     * <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_string_check_utf8 = 27 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setJavaStringCheckUtf8($var)
     {
         GPBUtil::checkBool($var);
         $this->java_string_check_utf8 = $var;
         $this->has_java_string_check_utf8 = true;
+
+        return $this;
     }
 
     public function hasJavaStringCheckUtf8()
@@ -391,7 +381,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
+     * @return int
      */
     public function getOptimizeFor()
     {
@@ -399,13 +390,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];</code>
+     * @param int $var
+     * @return $this
      */
     public function setOptimizeFor($var)
     {
         GPBUtil::checkEnum($var, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class);
         $this->optimize_for = $var;
         $this->has_optimize_for = true;
+
+        return $this;
     }
 
     public function hasOptimizeFor()
@@ -414,15 +409,14 @@
     }
 
     /**
-     * <pre>
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
      *   - The basename of the package import path, if provided.
      *   - Otherwise, the package statement in the .proto file, if present.
      *   - Otherwise, the basename of the .proto file, without extension.
-     * </pre>
      *
-     * <code>optional string go_package = 11;</code>
+     * Generated from protobuf field <code>optional string go_package = 11;</code>
+     * @return string
      */
     public function getGoPackage()
     {
@@ -430,21 +424,23 @@
     }
 
     /**
-     * <pre>
      * Sets the Go package where structs generated from this .proto will be
      * placed. If omitted, the Go package will be derived from the following:
      *   - The basename of the package import path, if provided.
      *   - Otherwise, the package statement in the .proto file, if present.
      *   - Otherwise, the basename of the .proto file, without extension.
-     * </pre>
      *
-     * <code>optional string go_package = 11;</code>
+     * Generated from protobuf field <code>optional string go_package = 11;</code>
+     * @param string $var
+     * @return $this
      */
     public function setGoPackage($var)
     {
         GPBUtil::checkString($var, True);
         $this->go_package = $var;
         $this->has_go_package = true;
+
+        return $this;
     }
 
     public function hasGoPackage()
@@ -453,7 +449,6 @@
     }
 
     /**
-     * <pre>
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
      * main code generators in each language (without additional plugins).
@@ -463,9 +458,9 @@
      * that generate code specific to your particular RPC system.  Therefore,
      * these default to false.  Old code which depends on generic services should
      * explicitly set them to true.
-     * </pre>
      *
-     * <code>optional bool cc_generic_services = 16 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_generic_services = 16 [default = false];</code>
+     * @return bool
      */
     public function getCcGenericServices()
     {
@@ -473,7 +468,6 @@
     }
 
     /**
-     * <pre>
      * Should generic services be generated in each language?  "Generic" services
      * are not specific to any particular RPC system.  They are generated by the
      * main code generators in each language (without additional plugins).
@@ -483,15 +477,18 @@
      * that generate code specific to your particular RPC system.  Therefore,
      * these default to false.  Old code which depends on generic services should
      * explicitly set them to true.
-     * </pre>
      *
-     * <code>optional bool cc_generic_services = 16 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_generic_services = 16 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setCcGenericServices($var)
     {
         GPBUtil::checkBool($var);
         $this->cc_generic_services = $var;
         $this->has_cc_generic_services = true;
+
+        return $this;
     }
 
     public function hasCcGenericServices()
@@ -500,7 +497,8 @@
     }
 
     /**
-     * <code>optional bool java_generic_services = 17 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
+     * @return bool
      */
     public function getJavaGenericServices()
     {
@@ -508,13 +506,17 @@
     }
 
     /**
-     * <code>optional bool java_generic_services = 17 [default = false];</code>
+     * Generated from protobuf field <code>optional bool java_generic_services = 17 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setJavaGenericServices($var)
     {
         GPBUtil::checkBool($var);
         $this->java_generic_services = $var;
         $this->has_java_generic_services = true;
+
+        return $this;
     }
 
     public function hasJavaGenericServices()
@@ -523,7 +525,8 @@
     }
 
     /**
-     * <code>optional bool py_generic_services = 18 [default = false];</code>
+     * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
+     * @return bool
      */
     public function getPyGenericServices()
     {
@@ -531,13 +534,17 @@
     }
 
     /**
-     * <code>optional bool py_generic_services = 18 [default = false];</code>
+     * Generated from protobuf field <code>optional bool py_generic_services = 18 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setPyGenericServices($var)
     {
         GPBUtil::checkBool($var);
         $this->py_generic_services = $var;
         $this->has_py_generic_services = true;
+
+        return $this;
     }
 
     public function hasPyGenericServices()
@@ -546,14 +553,41 @@
     }
 
     /**
-     * <pre>
+     * Generated from protobuf field <code>optional bool php_generic_services = 19 [default = false];</code>
+     * @return bool
+     */
+    public function getPhpGenericServices()
+    {
+        return $this->php_generic_services;
+    }
+
+    /**
+     * Generated from protobuf field <code>optional bool php_generic_services = 19 [default = false];</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setPhpGenericServices($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->php_generic_services = $var;
+        $this->has_php_generic_services = true;
+
+        return $this;
+    }
+
+    public function hasPhpGenericServices()
+    {
+        return $this->has_php_generic_services;
+    }
+
+    /**
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for everything in the file, or it will be completely ignored; in the very
      * least, this is a formalization for deprecating files.
-     * </pre>
      *
-     * <code>optional bool deprecated = 23 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 23 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -561,20 +595,22 @@
     }
 
     /**
-     * <pre>
      * Is this file deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for everything in the file, or it will be completely ignored; in the very
      * least, this is a formalization for deprecating files.
-     * </pre>
      *
-     * <code>optional bool deprecated = 23 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 23 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -583,12 +619,11 @@
     }
 
     /**
-     * <pre>
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
-     * </pre>
      *
-     * <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * @return bool
      */
     public function getCcEnableArenas()
     {
@@ -596,18 +631,20 @@
     }
 
     /**
-     * <pre>
      * Enables the use of arenas for the proto messages in this file. This applies
      * only to generated classes for C++.
-     * </pre>
      *
-     * <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * Generated from protobuf field <code>optional bool cc_enable_arenas = 31 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setCcEnableArenas($var)
     {
         GPBUtil::checkBool($var);
         $this->cc_enable_arenas = $var;
         $this->has_cc_enable_arenas = true;
+
+        return $this;
     }
 
     public function hasCcEnableArenas()
@@ -616,12 +653,11 @@
     }
 
     /**
-     * <pre>
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
-     * </pre>
      *
-     * <code>optional string objc_class_prefix = 36;</code>
+     * Generated from protobuf field <code>optional string objc_class_prefix = 36;</code>
+     * @return string
      */
     public function getObjcClassPrefix()
     {
@@ -629,18 +665,20 @@
     }
 
     /**
-     * <pre>
      * Sets the objective c class prefix which is prepended to all objective c
      * generated classes from this .proto. There is no default.
-     * </pre>
      *
-     * <code>optional string objc_class_prefix = 36;</code>
+     * Generated from protobuf field <code>optional string objc_class_prefix = 36;</code>
+     * @param string $var
+     * @return $this
      */
     public function setObjcClassPrefix($var)
     {
         GPBUtil::checkString($var, True);
         $this->objc_class_prefix = $var;
         $this->has_objc_class_prefix = true;
+
+        return $this;
     }
 
     public function hasObjcClassPrefix()
@@ -649,11 +687,10 @@
     }
 
     /**
-     * <pre>
      * Namespace for generated classes; defaults to the package.
-     * </pre>
      *
-     * <code>optional string csharp_namespace = 37;</code>
+     * Generated from protobuf field <code>optional string csharp_namespace = 37;</code>
+     * @return string
      */
     public function getCsharpNamespace()
     {
@@ -661,17 +698,19 @@
     }
 
     /**
-     * <pre>
      * Namespace for generated classes; defaults to the package.
-     * </pre>
      *
-     * <code>optional string csharp_namespace = 37;</code>
+     * Generated from protobuf field <code>optional string csharp_namespace = 37;</code>
+     * @param string $var
+     * @return $this
      */
     public function setCsharpNamespace($var)
     {
         GPBUtil::checkString($var, True);
         $this->csharp_namespace = $var;
         $this->has_csharp_namespace = true;
+
+        return $this;
     }
 
     public function hasCsharpNamespace()
@@ -680,14 +719,13 @@
     }
 
     /**
-     * <pre>
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
      * defined. When this options is provided, they will use this value instead
      * to prefix the types/symbols defined.
-     * </pre>
      *
-     * <code>optional string swift_prefix = 39;</code>
+     * Generated from protobuf field <code>optional string swift_prefix = 39;</code>
+     * @return string
      */
     public function getSwiftPrefix()
     {
@@ -695,20 +733,22 @@
     }
 
     /**
-     * <pre>
      * By default Swift generators will take the proto package and CamelCase it
      * replacing '.' with underscore and use that to prefix the types/symbols
      * defined. When this options is provided, they will use this value instead
      * to prefix the types/symbols defined.
-     * </pre>
      *
-     * <code>optional string swift_prefix = 39;</code>
+     * Generated from protobuf field <code>optional string swift_prefix = 39;</code>
+     * @param string $var
+     * @return $this
      */
     public function setSwiftPrefix($var)
     {
         GPBUtil::checkString($var, True);
         $this->swift_prefix = $var;
         $this->has_swift_prefix = true;
+
+        return $this;
     }
 
     public function hasSwiftPrefix()
@@ -717,12 +757,11 @@
     }
 
     /**
-     * <pre>
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
-     * </pre>
      *
-     * <code>optional string php_class_prefix = 40;</code>
+     * Generated from protobuf field <code>optional string php_class_prefix = 40;</code>
+     * @return string
      */
     public function getPhpClassPrefix()
     {
@@ -730,18 +769,20 @@
     }
 
     /**
-     * <pre>
      * Sets the php class prefix which is prepended to all php generated classes
      * from this .proto. Default is empty.
-     * </pre>
      *
-     * <code>optional string php_class_prefix = 40;</code>
+     * Generated from protobuf field <code>optional string php_class_prefix = 40;</code>
+     * @param string $var
+     * @return $this
      */
     public function setPhpClassPrefix($var)
     {
         GPBUtil::checkString($var, True);
         $this->php_class_prefix = $var;
         $this->has_php_class_prefix = true;
+
+        return $this;
     }
 
     public function hasPhpClassPrefix()
@@ -750,11 +791,46 @@
     }
 
     /**
-     * <pre>
-     * The parser stores options it doesn't recognize here. See above.
-     * </pre>
+     * Use this option to change the namespace of php generated classes. Default
+     * is empty. When this option is empty, the package name will be used for
+     * determining the namespace.
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>optional string php_namespace = 41;</code>
+     * @return string
+     */
+    public function getPhpNamespace()
+    {
+        return $this->php_namespace;
+    }
+
+    /**
+     * Use this option to change the namespace of php generated classes. Default
+     * is empty. When this option is empty, the package name will be used for
+     * determining the namespace.
+     *
+     * Generated from protobuf field <code>optional string php_namespace = 41;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setPhpNamespace($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->php_namespace = $var;
+        $this->has_php_namespace = true;
+
+        return $this;
+    }
+
+    public function hasPhpNamespace()
+    {
+        return $this->has_php_namespace;
+    }
+
+    /**
+     * The parser stores options it doesn't recognize here. See above.
+     *
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -762,17 +838,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php b/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php
index b550e7f..4dd56ef 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php
@@ -5,36 +5,28 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * <pre>
  * Generated classes can be optimized for speed or code size.
- * </pre>
  *
- * Protobuf enum <code>google.protobuf.FileOptions.OptimizeMode</code>
+ * Protobuf enum <code>Google\Protobuf\Internal</code>
  */
 class FileOptions_OptimizeMode
 {
     /**
-     * <pre>
      * Generate complete code for parsing, serialization,
-     * </pre>
      *
-     * <code>SPEED = 1;</code>
+     * Generated from protobuf enum <code>SPEED = 1;</code>
      */
     const SPEED = 1;
     /**
-     * <pre>
      * etc.
-     * </pre>
      *
-     * <code>CODE_SIZE = 2;</code>
+     * Generated from protobuf enum <code>CODE_SIZE = 2;</code>
      */
     const CODE_SIZE = 2;
     /**
-     * <pre>
      * Generate code using MessageLite and the lite runtime.
-     * </pre>
      *
-     * <code>LITE_RUNTIME = 3;</code>
+     * Generated from protobuf enum <code>LITE_RUNTIME = 3;</code>
      */
     const LITE_RUNTIME = 3;
 }
diff --git a/php/src/Google/Protobuf/Internal/GPBJsonWire.php b/php/src/Google/Protobuf/Internal/GPBJsonWire.php
new file mode 100644
index 0000000..9778935
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GPBJsonWire.php
@@ -0,0 +1,285 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class GPBJsonWire
+{
+
+    public static function serializeFieldToStream(
+        $value,
+        $field,
+        &$output)
+    {
+        $output->writeRaw("\"", 1);
+        $field_name = GPBJsonWire::formatFieldName($field);
+        $output->writeRaw($field_name, strlen($field_name));
+        $output->writeRaw("\":", 2);
+        return static::serializeFieldValueToStream($value, $field, $output);
+    }
+
+    private static function serializeFieldValueToStream(
+        $values,
+        $field,
+        &$output)
+    {
+        if ($field->isMap()) {
+            $output->writeRaw("{", 1);
+            $first = true;
+            $map_entry = $field->getMessageType();
+            $key_field = $map_entry->getFieldByNumber(1);
+            $value_field = $map_entry->getFieldByNumber(2);
+
+            switch ($key_field->getType()) {
+            case GPBType::STRING:
+            case GPBType::SFIXED64:
+            case GPBType::INT64:
+            case GPBType::SINT64:
+            case GPBType::FIXED64:
+            case GPBType::UINT64:
+                $additional_quote = false;
+                break;
+            default:
+                $additional_quote = true;
+            }
+
+            foreach ($values as $key => $value) {
+                if ($first) {
+                    $first = false;
+                } else {
+                    $output->writeRaw(",", 1);
+                }
+                if ($additional_quote) {
+                    $output->writeRaw("\"", 1);
+                }
+                if (!static::serializeSingularFieldValueToStream(
+                    $key,
+                    $key_field,
+                    $output)) {
+                    return false;
+                }
+                if ($additional_quote) {
+                    $output->writeRaw("\"", 1);
+                }
+                $output->writeRaw(":", 1);
+                if (!static::serializeSingularFieldValueToStream(
+                    $value,
+                    $value_field,
+                    $output)) {
+                    return false;
+                }
+            }
+            $output->writeRaw("}", 1);
+            return true;
+        } elseif ($field->isRepeated()) {
+            $output->writeRaw("[", 1);
+            $first = true;
+            foreach ($values as $value) {
+                if ($first) {
+                    $first = false;
+                } else {
+                    $output->writeRaw(",", 1);
+                }
+                if (!static::serializeSingularFieldValueToStream(
+                    $value,
+                    $field,
+                    $output)) {
+                    return false;
+                }
+            }
+            $output->writeRaw("]", 1);
+            return true;
+        } else {
+            return static::serializeSingularFieldValueToStream(
+                $values,
+                $field,
+                $output);
+        }
+    }
+
+    private static function serializeSingularFieldValueToStream(
+        $value,
+        $field,
+        &$output)
+    {
+        switch ($field->getType()) {
+            case GPBType::SFIXED32:
+            case GPBType::SINT32:
+            case GPBType::INT32:
+                $str_value = strval($value);
+                $output->writeRaw($str_value, strlen($str_value));
+                break;
+            case GPBType::FIXED32:
+            case GPBType::UINT32:
+                if ($value < 0) {
+                    $value = bcadd($value, "4294967296");
+                }
+                $str_value = strval($value);
+                $output->writeRaw($str_value, strlen($str_value));
+                break;
+            case GPBType::FIXED64:
+            case GPBType::UINT64:
+                if ($value < 0) {
+                    $value = bcadd($value, "18446744073709551616");
+                }
+                // Intentional fall through.
+            case GPBType::SFIXED64:
+            case GPBType::INT64:
+            case GPBType::SINT64:
+                $output->writeRaw("\"", 1);
+                $str_value = strval($value);
+                $output->writeRaw($str_value, strlen($str_value));
+                $output->writeRaw("\"", 1);
+                break;
+            case GPBType::FLOAT:
+                if (is_nan($value)) {
+                    $str_value = "\"NaN\"";
+                } elseif ($value === INF) {
+                    $str_value = "\"Infinity\"";
+                } elseif ($value === -INF) {
+                    $str_value = "\"-Infinity\"";
+                } else {
+                    $str_value = sprintf("%.8g", $value);
+                }
+                $output->writeRaw($str_value, strlen($str_value));
+                break;
+            case GPBType::DOUBLE:
+                if (is_nan($value)) {
+                    $str_value = "\"NaN\"";
+                } elseif ($value === INF) {
+                    $str_value = "\"Infinity\"";
+                } elseif ($value === -INF) {
+                    $str_value = "\"-Infinity\"";
+                } else {
+                    $str_value = sprintf("%.17g", $value);
+                }
+                $output->writeRaw($str_value, strlen($str_value));
+                break;
+            case GPBType::ENUM:
+                $enum_desc = $field->getEnumType();
+                $enum_value_desc = $enum_desc->getValueByNumber($value);
+                if (!is_null($enum_value_desc)) {
+                    $str_value = $enum_value_desc->getName();
+                    $output->writeRaw("\"", 1);
+                    $output->writeRaw($str_value, strlen($str_value));
+                    $output->writeRaw("\"", 1);
+                } else {
+                    $str_value = strval($value);
+                    $output->writeRaw($str_value, strlen($str_value));
+                }
+                break;
+            case GPBType::BOOL:
+                if ($value) {
+                    $output->writeRaw("true", 4);
+                } else {
+                    $output->writeRaw("false", 5);
+                }
+                break;
+            case GPBType::BYTES:
+                $value = base64_encode($value);
+            case GPBType::STRING:
+                $value = json_encode($value);
+                $output->writeRaw($value, strlen($value));
+                break;
+            //    case GPBType::GROUP:
+            //      echo "GROUP\xA";
+            //      trigger_error("Not implemented.", E_ERROR);
+            //      break;
+            case GPBType::MESSAGE:
+                $value->serializeToJsonStream($output);
+                break;
+            default:
+                user_error("Unsupported type.");
+                return false;
+        }
+        return true;
+    }
+
+    private static function formatFieldName($field)
+    {
+        return $field->getJsonName();
+    }
+
+    // Used for escaping control chars in strings.
+    private static $k_control_char_limit = 0x20;
+
+    private static function jsonNiceEscape($c)
+    {
+      switch ($c) {
+          case '"':  return "\\\"";
+          case '\\': return "\\\\";
+          case '/': return "\\/";
+          case '\b': return "\\b";
+          case '\f': return "\\f";
+          case '\n': return "\\n";
+          case '\r': return "\\r";
+          case '\t': return "\\t";
+          default:   return NULL;
+      }
+    }
+
+    private static function isJsonEscaped($c)
+    {
+        // See RFC 4627.
+        return $c < chr($k_control_char_limit) || $c === "\"" || $c === "\\";
+    }
+
+    public static function escapedJson($value)
+    {
+        $escaped_value = "";
+        $unescaped_run = "";
+        for ($i = 0; $i < strlen($value); $i++) {
+            $c = $value[$i];
+            // Handle escaping.
+            if (static::isJsonEscaped($c)) {
+                // Use a "nice" escape, like \n, if one exists for this
+                // character.
+                $escape = static::jsonNiceEscape($c);
+                if (is_null($escape)) {
+                    $escape = "\\u00" . bin2hex($c);
+                }
+                if ($unescaped_run !== "") {
+                    $escaped_value .= $unescaped_run;
+                    $unescaped_run = "";
+                }
+                $escaped_value .= $escape;
+            } else {
+              if ($unescaped_run === "") {
+                $unescaped_run .= $c;
+              }
+            }
+        }
+        $escaped_value .= $unescaped_run;
+        return $escaped_value;
+    }
+
+}
diff --git a/php/src/Google/Protobuf/Internal/GPBUtil.php b/php/src/Google/Protobuf/Internal/GPBUtil.php
index 0e66ae6..a27220a 100644
--- a/php/src/Google/Protobuf/Internal/GPBUtil.php
+++ b/php/src/Google/Protobuf/Internal/GPBUtil.php
@@ -38,15 +38,23 @@
 
 class GPBUtil
 {
-    public function divideInt64ToInt32($value, &$high, &$low, $trim = false)
+    const NANOS_PER_MILLISECOND = 1000000;
+    const NANOS_PER_MICROSECOND = 1000;
+
+    public static function divideInt64ToInt32($value, &$high, &$low, $trim = false)
     {
         $isNeg = (bccomp($value, 0) < 0);
         if ($isNeg) {
             $value = bcsub(0, $value);
         }
 
-        $high = (int) bcdiv(bcadd($value, 1), 4294967296);
+        $high = bcdiv($value, 4294967296);
         $low = bcmod($value, 4294967296);
+        if (bccomp($high, 2147483647) > 0) {
+            $high = (int) bcsub($high, 4294967296);
+        } else {
+            $high = (int) $high;
+        }
         if (bccomp($low, 2147483647) > 0) {
             $low = (int) bcsub($low, 4294967296);
         } else {
@@ -58,7 +66,7 @@
             $low = ~$low;
             $low++;
             if (!$low) {
-                $high++;
+                $high = (int)($high + 1);
             }
         }
 
@@ -67,19 +75,16 @@
         }
     }
 
-
     public static function checkString(&$var, $check_utf8)
     {
         if (is_array($var) || is_object($var)) {
-            trigger_error("Expect string.", E_USER_ERROR);
-            return;
+            throw new \InvalidArgumentException("Expect string.");
         }
         if (!is_string($var)) {
             $var = strval($var);
         }
         if ($check_utf8 && !preg_match('//u', $var)) {
-            trigger_error("Expect utf-8 encoding.", E_USER_ERROR);
-            return;
+            throw new \Exception("Expect utf-8 encoding.");
         }
     }
 
@@ -93,7 +98,7 @@
         if (is_numeric($var)) {
             $var = intval($var);
         } else {
-            trigger_error("Expect integer.", E_USER_ERROR);
+            throw new \Exception("Expect integer.");
         }
     }
 
@@ -110,7 +115,7 @@
                 $var = (int) $var;
             }
         } else {
-            trigger_error("Expect integer.", E_USER_ERROR);
+            throw new \Exception("Expect integer.");
         }
     }
 
@@ -120,10 +125,15 @@
             if (PHP_INT_SIZE == 8) {
                 $var = intval($var);
             } else {
-                $var = bcdiv($var, 1, 0);
+                if (is_float($var) ||
+                    is_integer($var) ||
+                    (is_string($var) &&
+                         bccomp($var, "9223372036854774784") < 0)) {
+                    $var = number_format($var, 0, ".", "");
+                }
             }
         } else {
-            trigger_error("Expect integer.", E_USER_ERROR);
+            throw new \Exception("Expect integer.");
         }
     }
 
@@ -133,10 +143,10 @@
             if (PHP_INT_SIZE == 8) {
                 $var = intval($var);
             } else {
-                $var = bcdiv($var, 1, 0);
+                $var = number_format($var, 0, ".", "");
             }
         } else {
-            trigger_error("Expect integer.", E_USER_ERROR);
+            throw new \Exception("Expect integer.");
         }
     }
 
@@ -145,7 +155,7 @@
         if (is_float($var) || is_numeric($var)) {
             $var = floatval($var);
         } else {
-            trigger_error("Expect float.", E_USER_ERROR);
+            throw new \Exception("Expect float.");
         }
     }
 
@@ -154,15 +164,14 @@
         if (is_float($var) || is_numeric($var)) {
             $var = floatval($var);
         } else {
-            trigger_error("Expect float.", E_USER_ERROR);
+            throw new \Exception("Expect float.");
         }
     }
 
     public static function checkBool(&$var)
     {
         if (is_array($var) || is_object($var)) {
-            trigger_error("Expect boolean.", E_USER_ERROR);
-            return;
+            throw new \Exception("Expect boolean.");
         }
         $var = boolval($var);
     }
@@ -170,14 +179,14 @@
     public static function checkMessage(&$var, $klass)
     {
         if (!$var instanceof $klass && !is_null($var)) {
-            trigger_error("Expect message.", E_USER_ERROR);
+            throw new \Exception("Expect message.");
         }
     }
 
     public static function checkRepeatedField(&$var, $type, $klass = null)
     {
         if (!$var instanceof RepeatedField && !is_array($var)) {
-            trigger_error("Expect array.", E_USER_ERROR);
+            throw new \Exception("Expect array.");
         }
         if (is_array($var)) {
             $tmp = new RepeatedField($type, $klass);
@@ -187,15 +196,13 @@
             return $tmp;
         } else {
             if ($var->getType() != $type) {
-                trigger_error(
-                    "Expect repeated field of different type.",
-                    E_USER_ERROR);
+                throw new \Exception(
+                    "Expect repeated field of different type.");
             }
             if ($var->getType() === GPBType::MESSAGE &&
                 $var->getClass() !== $klass) {
-                trigger_error(
-                    "Expect repeated field of different message.",
-                    E_USER_ERROR);
+                throw new \Exception(
+                    "Expect repeated field of different message.");
             }
             return $var;
         }
@@ -204,7 +211,7 @@
     public static function checkMapField(&$var, $key_type, $value_type, $klass = null)
     {
         if (!$var instanceof MapField && !is_array($var)) {
-            trigger_error("Expect dict.", E_USER_ERROR);
+            throw new \Exception("Expect dict.");
         }
         if (is_array($var)) {
             $tmp = new MapField($key_type, $value_type, $klass);
@@ -214,20 +221,15 @@
             return $tmp;
         } else {
             if ($var->getKeyType() != $key_type) {
-                trigger_error(
-                    "Expect map field of key type.",
-                    E_USER_ERROR);
+                throw new \Exception("Expect map field of key type.");
             }
             if ($var->getValueType() != $value_type) {
-                trigger_error(
-                    "Expect map field of value type.",
-                    E_USER_ERROR);
+                throw new \Exception("Expect map field of value type.");
             }
             if ($var->getValueType() === GPBType::MESSAGE &&
                 $var->getValueClass() !== $klass) {
-                trigger_error(
-                    "Expect map field of different value message.",
-                    E_USER_ERROR);
+                throw new \Exception(
+                    "Expect map field of different value message.");
             }
             return $var;
         }
@@ -242,4 +244,180 @@
     {
         return new Uint64($value);
     }
+
+    public static function getClassNamePrefix(
+        $classname,
+        $file_proto)
+    {
+        $option = $file_proto->getOptions();
+        $prefix = is_null($option) ? "" : $option->getPhpClassPrefix();
+        if ($prefix !== "") {
+            return $prefix;
+        }
+
+        $reserved_words = array("Empty", "ECHO", "ARRAY");
+        foreach ($reserved_words as $reserved_word) {
+            if ($classname === $reserved_word) {
+                if ($file_proto->getPackage() === "google.protobuf") {
+                    return "GPB";
+                } else {
+                    return "PB";
+                }
+            }
+        }
+
+        return "";
+    }
+
+    public static function getClassNameWithoutPackage(
+        $name,
+        $file_proto)
+    {
+        $classname = implode('_', explode('.', $name));
+        return static::getClassNamePrefix($classname, $file_proto) . $classname;
+    }
+
+    public static function getFullClassName(
+        $proto,
+        $containing,
+        $file_proto,
+        &$message_name_without_package,
+        &$classname,
+        &$fullname)
+    {
+        // Full name needs to start with '.'.
+        $message_name_without_package = $proto->getName();
+        if ($containing !== "") {
+            $message_name_without_package =
+                $containing . "." . $message_name_without_package;
+        }
+
+        $package = $file_proto->getPackage();
+        if ($package === "") {
+            $fullname = "." . $message_name_without_package;
+        } else {
+            $fullname = "." . $package . "." . $message_name_without_package;
+        }
+
+        $class_name_without_package =
+            static::getClassNameWithoutPackage($message_name_without_package, $file_proto);
+
+        $option = $file_proto->getOptions();
+        if (!is_null($option) && $option->hasPhpNamespace()) {
+            $namespace = $option->getPhpNamespace();
+            if ($namespace !== "") {
+                $classname = $namespace . "\\" . $class_name_without_package;
+                return;
+            } else {
+                $classname = $class_name_without_package;
+                return;
+            }
+        }
+
+        if ($package === "") {
+            $classname = $class_name_without_package;
+        } else {
+            $classname =
+                implode('\\', array_map('ucwords', explode('.', $package))).
+                "\\".$class_name_without_package;
+        }
+    }
+
+    public static function combineInt32ToInt64($high, $low)
+    {
+        $isNeg = $high < 0;
+        if ($isNeg) {
+            $high = ~$high;
+            $low = ~$low;
+            $low++;
+            if (!$low) {
+                $high = (int) ($high + 1);
+            }
+        }
+        $result = bcadd(bcmul($high, 4294967296), $low);
+        if ($low < 0) {
+            $result = bcadd($result, 4294967296);
+        }
+        if ($isNeg) {
+          $result = bcsub(0, $result);
+        }
+        return $result;
+    }
+    
+    public static function parseTimestamp($timestamp)
+    {
+        // prevent parsing timestamps containing with the non-existant year "0000"
+        // DateTime::createFromFormat parses without failing but as a nonsensical date
+        if (substr($timestamp, 0, 4) === "0000") {
+            throw new \Exception("Year cannot be zero.");
+        }
+        // prevent parsing timestamps ending with a lowercase z
+        if (substr($timestamp, -1, 1) === "z") {
+            throw new \Exception("Timezone cannot be a lowercase z.");
+        }
+        
+        $nanoseconds = 0;
+        $periodIndex = strpos($timestamp, ".");
+        if ($periodIndex !== false) {
+            $nanosecondsLength = 0;
+            // find the next non-numeric character in the timestamp to calculate
+            // the length of the nanoseconds text
+            for ($i = $periodIndex + 1, $length = strlen($timestamp); $i < $length; $i++) {
+                if (!is_numeric($timestamp[$i])) {
+                    $nanosecondsLength = $i - ($periodIndex + 1);
+                    break;
+                }
+            }
+            if ($nanosecondsLength % 3 !== 0) {
+                throw new \Exception("Nanoseconds must be disible by 3.");
+            }
+            if ($nanosecondsLength > 9) {
+                throw new \Exception("Nanoseconds must be in the range of 0 to 999,999,999 nanoseconds.");
+            }
+            if ($nanosecondsLength > 0) {
+                $nanoseconds = substr($timestamp, $periodIndex + 1, $nanosecondsLength);
+                $nanoseconds = intval($nanoseconds);
+
+                // remove the nanoseconds and preceding period from the timestamp
+                $date = substr($timestamp, 0, $periodIndex - 1);
+                $timezone = substr($timestamp, $periodIndex + $nanosecondsLength);
+                $timestamp = $date.$timezone;
+            }
+        }
+
+        $date = \DateTime::createFromFormat(\DateTime::RFC3339, $timestamp, new \DateTimeZone("UTC"));
+        if ($date === false) {
+            throw new \Exception("Invalid RFC 3339 timestamp.");
+        }
+
+        $value = new \Google\Protobuf\Timestamp();
+        $seconds = $date->format("U");
+        $value->setSeconds($seconds);
+        $value->setNanos($nanoseconds);
+        return $value;
+    }
+    
+    public static function formatTimestamp($value)
+    {
+        $nanoseconds = static::getNanosecondsForTimestamp($value->getNanos());
+        if (!empty($nanoseconds)) {
+            $nanoseconds = ".".$nanoseconds;
+        }
+        $date = new \DateTime('@'.$value->getSeconds(), new \DateTimeZone("UTC"));
+        return $date->format("Y-m-d\TH:i:s".$nanoseconds."\Z");
+    }
+
+    public static function getNanosecondsForTimestamp($nanoseconds)
+    {
+        if ($nanoseconds == 0) {
+            return '';
+        }
+        if ($nanoseconds % static::NANOS_PER_MILLISECOND == 0) {
+            return sprintf('%03d', $nanoseconds / static::NANOS_PER_MILLISECOND);
+        }
+        if ($nanoseconds % static::NANOS_PER_MICROSECOND == 0) {
+            return sprintf('%06d', $nanoseconds / static::NANOS_PER_MICROSECOND);
+        }
+        return sprintf('%09d', $nanoseconds);
+    }
 }
diff --git a/php/src/Google/Protobuf/Internal/GPBWire.php b/php/src/Google/Protobuf/Internal/GPBWire.php
index 67eb1be..e7eec55 100644
--- a/php/src/Google/Protobuf/Internal/GPBWire.php
+++ b/php/src/Google/Protobuf/Internal/GPBWire.php
@@ -117,19 +117,12 @@
   //        << decode <<
   public static function zigZagEncode32($int32)
   {
-      // Fill high 32 bits.
-      if (PHP_INT_SIZE === 8) {
-          $int32 |= ((($int32 << 32) >> 31) & (0xFFFFFFFF << 32));
+      if (PHP_INT_SIZE == 8) {
+          $trim_int32 = $int32 & 0xFFFFFFFF;
+          return (($trim_int32 << 1) ^ ($int32 << 32 >> 63)) & 0xFFFFFFFF;
+      } else {
+          return ($int32 << 1) ^ ($int32 >> 31);
       }
-
-      $uint32 = ($int32 << 1) ^ ($int32 >> 31);
-
-      // Fill high 32 bits.
-      if (PHP_INT_SIZE === 8) {
-          $uint32 |= ((($uint32 << 32) >> 31) & (0xFFFFFFFF << 32));
-      }
-
-      return $uint32;
   }
 
     public static function zigZagDecode32($uint32)
@@ -177,7 +170,11 @@
 
     public static function readInt64(&$input, &$value)
     {
-        return $input->readVarint64($value);
+        $success = $input->readVarint64($value);
+        if (PHP_INT_SIZE == 4 && bccomp($value, "9223372036854775807") > 0) {
+            $value = bcsub($value, "18446744073709551616");
+        }
+        return $success;
     }
 
     public static function readUint32(&$input, &$value)
@@ -231,7 +228,11 @@
 
     public static function readSfixed64(&$input, &$value)
     {
-        return $input->readLittleEndian64($value);
+        $success = $input->readLittleEndian64($value);
+        if (PHP_INT_SIZE == 4 && bccomp($value, "9223372036854775807") > 0) {
+            $value = bcsub($value, "18446744073709551616");
+        }
+        return $success;
     }
 
     public static function readFloat(&$input, &$value)
@@ -298,7 +299,7 @@
 
     public static function writeInt32(&$output, $value)
     {
-        return $output->writeVarint32($value);
+        return $output->writeVarint32($value, false);
     }
 
     public static function writeInt64(&$output, $value)
@@ -308,7 +309,7 @@
 
     public static function writeUint32(&$output, $value)
     {
-        return $output->writeVarint32($value);
+        return $output->writeVarint32($value, true);
     }
 
     public static function writeUint64(&$output, $value)
@@ -319,7 +320,7 @@
     public static function writeSint32(&$output, $value)
     {
         $value = GPBWire::zigZagEncode32($value);
-        return $output->writeVarint64($value);
+        return $output->writeVarint32($value, true);
     }
 
     public static function writeSint64(&$output, $value)
@@ -351,9 +352,9 @@
     public static function writeBool(&$output, $value)
     {
         if ($value) {
-            return $output->writeVarint32(1);
+            return $output->writeVarint32(1, true);
         } else {
-            return $output->writeVarint32(0);
+            return $output->writeVarint32(0, true);
         }
     }
 
@@ -377,7 +378,7 @@
     public static function writeBytes(&$output, $value)
     {
         $size = strlen($value);
-        if (!$output->writeVarint32($size)) {
+        if (!$output->writeVarint32($size, true)) {
             return false;
         }
         return $output->writeRaw($value, $size);
@@ -386,7 +387,7 @@
     public static function writeMessage(&$output, $value)
     {
         $size = $value->byteSize();
-        if (!$output->writeVarint32($size)) {
+        if (!$output->writeVarint32($size, true)) {
             return false;
         }
         return $value->serializeToStream($output);
@@ -442,7 +443,8 @@
     public static function varint64Size($value)
     {
         if (PHP_INT_SIZE == 4) {
-            if (bccomp($value, 0) < 0) {
+            if (bccomp($value, 0) < 0 ||
+                bccomp($value, "9223372036854775807") > 0) {
                 return 10;
             }    
             if (bccomp($value, 1 << 7) < 0) {
@@ -578,6 +580,9 @@
                 }
                 break;
             case GPBType::UINT32:
+                if (PHP_INT_SIZE === 8 && $value < 0) {
+                    $value += 4294967296;
+                }
                 if (!GPBWire::writeUint32($output, $value)) {
                     return false;
                 }
diff --git a/php/src/Google/Protobuf/Internal/GPBWireType.php b/php/src/Google/Protobuf/Internal/GPBWireType.php
new file mode 100644
index 0000000..c1ad370
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GPBWireType.php
@@ -0,0 +1,43 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class GPBWireType
+{
+    const VARINT           = 0;
+    const FIXED64          = 1;
+    const LENGTH_DELIMITED = 2;
+    const START_GROUP      = 3;
+    const END_GROUP        = 4;
+    const FIXED32          = 5;
+}
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
index 450854f..ae2ad74 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
@@ -8,27 +8,22 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes the relationship between generated code and its original source
  * file. A GeneratedCodeInfo message is associated with only one generated
  * source file, but may contain references to different source .proto files.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.GeneratedCodeInfo</code>
+ * Generated from protobuf message <code>google.protobuf.GeneratedCodeInfo</code>
  */
 class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * An Annotation connects some span of text in generated code to an element
      * of its generating .proto file.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
      */
     private $annotation;
     private $has_annotation = false;
@@ -39,12 +34,11 @@
     }
 
     /**
-     * <pre>
      * An Annotation connects some span of text in generated code to an element
      * of its generating .proto file.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getAnnotation()
     {
@@ -52,18 +46,20 @@
     }
 
     /**
-     * <pre>
      * An Annotation connects some span of text in generated code to an element
      * of its generating .proto file.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
+     * @param \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setAnnotation(&$var)
+    public function setAnnotation($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class);
         $this->annotation = $arr;
         $this->has_annotation = true;
+
+        return $this;
     }
 
     public function hasAnnotation()
diff --git a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
index ed22cc3..22ac233 100644
--- a/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
+++ b/php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php
@@ -8,51 +8,42 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.GeneratedCodeInfo.Annotation</code>
+ * Generated from protobuf message <code>google.protobuf.GeneratedCodeInfo.Annotation</code>
  */
 class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Identifies the element in the original source .proto file. This field
      * is formatted the same as SourceCodeInfo.Location.path.
-     * </pre>
      *
-     * <code>repeated int32 path = 1 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
      */
     private $path;
     private $has_path = false;
     /**
-     * <pre>
      * Identifies the filesystem path to the original source .proto.
-     * </pre>
      *
-     * <code>optional string source_file = 2;</code>
+     * Generated from protobuf field <code>optional string source_file = 2;</code>
      */
     private $source_file = '';
     private $has_source_file = false;
     /**
-     * <pre>
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
-     * </pre>
      *
-     * <code>optional int32 begin = 3;</code>
+     * Generated from protobuf field <code>optional int32 begin = 3;</code>
      */
     private $begin = 0;
     private $has_begin = false;
     /**
-     * <pre>
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
      * the last relevant byte (so the length of the text = end - begin).
-     * </pre>
      *
-     * <code>optional int32 end = 4;</code>
+     * Generated from protobuf field <code>optional int32 end = 4;</code>
      */
     private $end = 0;
     private $has_end = false;
@@ -63,12 +54,11 @@
     }
 
     /**
-     * <pre>
      * Identifies the element in the original source .proto file. This field
      * is formatted the same as SourceCodeInfo.Location.path.
-     * </pre>
      *
-     * <code>repeated int32 path = 1 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getPath()
     {
@@ -76,18 +66,20 @@
     }
 
     /**
-     * <pre>
      * Identifies the element in the original source .proto file. This field
      * is formatted the same as SourceCodeInfo.Location.path.
-     * </pre>
      *
-     * <code>repeated int32 path = 1 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
+     * @param int[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setPath(&$var)
+    public function setPath($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->path = $arr;
         $this->has_path = true;
+
+        return $this;
     }
 
     public function hasPath()
@@ -96,11 +88,10 @@
     }
 
     /**
-     * <pre>
      * Identifies the filesystem path to the original source .proto.
-     * </pre>
      *
-     * <code>optional string source_file = 2;</code>
+     * Generated from protobuf field <code>optional string source_file = 2;</code>
+     * @return string
      */
     public function getSourceFile()
     {
@@ -108,17 +99,19 @@
     }
 
     /**
-     * <pre>
      * Identifies the filesystem path to the original source .proto.
-     * </pre>
      *
-     * <code>optional string source_file = 2;</code>
+     * Generated from protobuf field <code>optional string source_file = 2;</code>
+     * @param string $var
+     * @return $this
      */
     public function setSourceFile($var)
     {
         GPBUtil::checkString($var, True);
         $this->source_file = $var;
         $this->has_source_file = true;
+
+        return $this;
     }
 
     public function hasSourceFile()
@@ -127,12 +120,11 @@
     }
 
     /**
-     * <pre>
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
-     * </pre>
      *
-     * <code>optional int32 begin = 3;</code>
+     * Generated from protobuf field <code>optional int32 begin = 3;</code>
+     * @return int
      */
     public function getBegin()
     {
@@ -140,18 +132,20 @@
     }
 
     /**
-     * <pre>
      * Identifies the starting offset in bytes in the generated code
      * that relates to the identified object.
-     * </pre>
      *
-     * <code>optional int32 begin = 3;</code>
+     * Generated from protobuf field <code>optional int32 begin = 3;</code>
+     * @param int $var
+     * @return $this
      */
     public function setBegin($var)
     {
         GPBUtil::checkInt32($var);
         $this->begin = $var;
         $this->has_begin = true;
+
+        return $this;
     }
 
     public function hasBegin()
@@ -160,13 +154,12 @@
     }
 
     /**
-     * <pre>
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
      * the last relevant byte (so the length of the text = end - begin).
-     * </pre>
      *
-     * <code>optional int32 end = 4;</code>
+     * Generated from protobuf field <code>optional int32 end = 4;</code>
+     * @return int
      */
     public function getEnd()
     {
@@ -174,19 +167,21 @@
     }
 
     /**
-     * <pre>
      * Identifies the ending offset in bytes in the generated code that
      * relates to the identified offset. The end offset should be one past
      * the last relevant byte (so the length of the text = end - begin).
-     * </pre>
      *
-     * <code>optional int32 end = 4;</code>
+     * Generated from protobuf field <code>optional int32 end = 4;</code>
+     * @param int $var
+     * @return $this
      */
     public function setEnd($var)
     {
         GPBUtil::checkInt32($var);
         $this->end = $var;
         $this->has_end = true;
+
+        return $this;
     }
 
     public function hasEnd()
diff --git a/php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php b/php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php
new file mode 100644
index 0000000..d22bc30
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php
@@ -0,0 +1,41 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+namespace Google\Protobuf\Internal;
+
+trait GetPublicDescriptorTrait
+{
+    private function getPublicDescriptor($desc)
+    {
+        return is_null($desc) ? null : $desc->getPublicDescriptor();
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php b/php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php
new file mode 100644
index 0000000..ed5d166
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php
@@ -0,0 +1,43 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+trait HasPublicDescriptorTrait
+{
+    private $public_desc;
+
+    public function getPublicDescriptor()
+    {
+        return $this->public_desc;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/MapEntry.php b/php/src/Google/Protobuf/Internal/MapEntry.php
index 926645e..9c32f1e 100644
--- a/php/src/Google/Protobuf/Internal/MapEntry.php
+++ b/php/src/Google/Protobuf/Internal/MapEntry.php
@@ -39,7 +39,7 @@
     public $key;
     public $value;
 
-    public function setKey(&$key) {
+    public function setKey($key) {
       $this->key = $key;
     }
 
@@ -47,7 +47,7 @@
       return $this->key;
     }
 
-    public function setValue(&$value) {
+    public function setValue($value) {
       $this->value = $value;
     }
 
diff --git a/php/src/Google/Protobuf/Internal/MapField.php b/php/src/Google/Protobuf/Internal/MapField.php
index 55cc12c..38736da 100644
--- a/php/src/Google/Protobuf/Internal/MapField.php
+++ b/php/src/Google/Protobuf/Internal/MapField.php
@@ -38,131 +38,6 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * MapFieldIter is used to iterate MapField. It is also need for the foreach
- * syntax.
- */
-class MapFieldIter implements \Iterator
-{
-
-    /**
-     * @ignore
-     */
-    private $container;
-
-    /**
-     * Create iterator instance for MapField.
-     *
-     * @param MapField The MapField instance for which this iterator is
-     * created.
-     * @ignore
-     */
-    public function __construct($container)
-    {
-        $this->container = $container;
-    }
-
-    /**
-     * Reset the status of the iterator
-     *
-     * @return void
-     */
-    public function rewind()
-    {
-        return reset($this->container);
-    }
-
-    /**
-     * Return the element at the current position.
-     *
-     * @return object The element at the current position.
-     */
-    public function current()
-    {
-        return current($this->container);
-    }
-
-    /**
-     * Return the current key.
-     *
-     * @return object The current key.
-     */
-    public function key()
-    {
-        return key($this->container);
-    }
-
-    /**
-     * Move to the next position.
-     *
-     * @return void
-     */
-    public function next()
-    {
-        return next($this->container);
-    }
-
-    /**
-     * Check whether there are more elements to iterate.
-     *
-     * @return bool True if there are more elements to iterate.
-     */
-    public function valid()
-    {
-        return key($this->container) !== null;
-    }
-}
-
-/**
- * @ignore
- */
-function checkKey($key_type, &$key)
-{
-    switch ($key_type) {
-        case GPBType::INT32:
-            GPBUtil::checkInt32($key);
-            break;
-        case GPBType::UINT32:
-            GPBUtil::checkUint32($key);
-            break;
-        case GPBType::INT64:
-            GPBUtil::checkInt64($key);
-            break;
-        case GPBType::UINT64:
-            GPBUtil::checkUint64($key);
-            break;
-        case GPBType::FIXED64:
-            GPBUtil::checkUint64($key);
-            break;
-        case GPBType::FIXED32:
-            GPBUtil::checkUint32($key);
-            break;
-        case GPBType::SFIXED64:
-            GPBUtil::checkInt64($key);
-            break;
-        case GPBType::SFIXED32:
-            GPBUtil::checkInt32($key);
-            break;
-        case GPBType::SINT64:
-            GPBUtil::checkInt64($key);
-            break;
-        case GPBType::SINT32:
-            GPBUtil::checkInt32($key);
-            break;
-        case GPBType::BOOL:
-            GPBUtil::checkBool($key);
-            break;
-        case GPBType::STRING:
-            GPBUtil::checkString($key, true);
-            break;
-        default:
-            trigger_error(
-                "Given type cannot be map key.",
-                E_USER_ERROR);
-            break;
-    }
-}
-
-/**
  * MapField is used by generated protocol message classes to manipulate map
  * fields. It can be used like native PHP array.
  */
@@ -255,7 +130,7 @@
      */
     public function offsetSet($key, $value)
     {
-        checkKey($this->key_type, $key);
+        $this->checkKey($this->key_type, $key);
 
         switch ($this->value_type) {
             case GPBType::INT32:
@@ -306,7 +181,7 @@
      */
     public function offsetUnset($key)
     {
-        checkKey($this->key_type, $key);
+        $this->checkKey($this->key_type, $key);
         unset($this->container[$key]);
     }
 
@@ -321,7 +196,7 @@
      */
     public function offsetExists($key)
     {
-        checkKey($this->key_type, $key);
+        $this->checkKey($this->key_type, $key);
         return isset($this->container[$key]);
     }
 
@@ -330,7 +205,7 @@
      */
     public function getIterator()
     {
-        return new MapFieldIter($this->container);
+        return new MapFieldIter($this->container, $this->key_type);
     }
 
     /**
@@ -344,4 +219,54 @@
     {
         return count($this->container);
     }
+
+    /**
+     * @ignore
+     */
+    private function checkKey($key_type, &$key)
+    {
+        switch ($key_type) {
+            case GPBType::INT32:
+                GPBUtil::checkInt32($key);
+                break;
+            case GPBType::UINT32:
+                GPBUtil::checkUint32($key);
+                break;
+            case GPBType::INT64:
+                GPBUtil::checkInt64($key);
+                break;
+            case GPBType::UINT64:
+                GPBUtil::checkUint64($key);
+                break;
+            case GPBType::FIXED64:
+                GPBUtil::checkUint64($key);
+                break;
+            case GPBType::FIXED32:
+                GPBUtil::checkUint32($key);
+                break;
+            case GPBType::SFIXED64:
+                GPBUtil::checkInt64($key);
+                break;
+            case GPBType::SFIXED32:
+                GPBUtil::checkInt32($key);
+                break;
+            case GPBType::SINT64:
+                GPBUtil::checkInt64($key);
+                break;
+            case GPBType::SINT32:
+                GPBUtil::checkInt32($key);
+                break;
+            case GPBType::BOOL:
+                GPBUtil::checkBool($key);
+                break;
+            case GPBType::STRING:
+                GPBUtil::checkString($key, true);
+                break;
+            default:
+                trigger_error(
+                    "Given type cannot be map key.",
+                    E_USER_ERROR);
+                break;
+        }
+    }
 }
diff --git a/php/src/Google/Protobuf/Internal/MapFieldIter.php b/php/src/Google/Protobuf/Internal/MapFieldIter.php
new file mode 100644
index 0000000..88e6c8b
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/MapFieldIter.php
@@ -0,0 +1,124 @@
+<?php
+
+// 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.
+
+/**
+ * MapField and MapFieldIter are used by generated protocol message classes to
+ * manipulate map fields.
+ */
+
+namespace Google\Protobuf\Internal;
+
+/**
+ * MapFieldIter is used to iterate MapField. It is also need for the foreach
+ * syntax.
+ */
+class MapFieldIter implements \Iterator
+{
+
+    /**
+     * @ignore
+     */
+    private $container;
+
+    /**
+     * Create iterator instance for MapField.
+     *
+     * @param MapField The MapField instance for which this iterator is
+     * created.
+     * @param GPBType Map key type.
+     * @ignore
+     */
+    public function __construct($container, $key_type)
+    {
+        $this->container = $container;
+        $this->key_type = $key_type;
+    }
+
+    /**
+     * Reset the status of the iterator
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        return reset($this->container);
+    }
+
+    /**
+     * Return the element at the current position.
+     *
+     * @return object The element at the current position.
+     */
+    public function current()
+    {
+        return current($this->container);
+    }
+
+    /**
+     * Return the current key.
+     *
+     * @return object The current key.
+     */
+    public function key()
+    {
+        $key = key($this->container);
+        if ($this->key_type === GPBType::BOOL) {
+            // PHP associative array stores bool as integer for key.
+            return boolval($key);
+        } elseif ($this->key_type === GPBType::STRING) {
+            // PHP associative array stores int string as int for key.
+            return strval($key);
+        } else {
+            return $key;
+        }
+    }
+
+    /**
+     * Move to the next position.
+     *
+     * @return void
+     */
+    public function next()
+    {
+        return next($this->container);
+    }
+
+    /**
+     * Check whether there are more elements to iterate.
+     *
+     * @return bool True if there are more elements to iterate.
+     */
+    public function valid()
+    {
+        return key($this->container) !== null;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index 10c639a..c0a3218 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -36,8 +36,8 @@
 
 namespace Google\Protobuf\Internal;
 
-use Google\Protobuf\Internal\InputStream;
-use Google\Protobuf\Internal\OutputStream;
+use Google\Protobuf\Internal\CodedInputStream;
+use Google\Protobuf\Internal\CodedOutputStream;
 use Google\Protobuf\Internal\DescriptorPool;
 use Google\Protobuf\Internal\GPBLabel;
 use Google\Protobuf\Internal\GPBType;
@@ -68,10 +68,17 @@
         // specific descriptor from the descriptor pool.
         if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') {
             $this->desc = $desc;
+            foreach ($desc->getField() as $field) {
+                $setter = $field->getSetter();
+                $this->$setter($this->defaultValue($field));
+            }
             return;
         }
         $pool = DescriptorPool::getGeneratedPool();
         $this->desc = $pool->getDescriptorByClassName(get_class($this));
+        if (is_null($this->desc)) {
+            user_error(get_class($this) . "is not found in descriptor pool.");
+        }
         foreach ($this->desc->getField() as $field) {
             $setter = $field->getSetter();
             if ($field->isMap()) {
@@ -219,6 +226,58 @@
     /**
      * @ignore
      */
+    private static function skipField($input, $tag)
+    {
+        $number = GPBWire::getTagFieldNumber($tag);
+        if ($number === 0) {
+            throw new GPBDecodeException("Illegal field number zero.");
+        }
+
+        switch (GPBWire::getTagWireType($tag)) {
+            case GPBWireType::VARINT:
+                $uint64 = 0;
+                if (!$input->readVarint64($uint64)) {
+                    throw new GPBDecodeException(
+                        "Unexpected EOF inside varint.");
+                }
+                return;
+            case GPBWireType::FIXED64:
+                $uint64 = 0;
+                if (!$input->readLittleEndian64($uint64)) {
+                    throw new GPBDecodeException(
+                        "Unexpected EOF inside fixed64.");
+                }
+                return;
+            case GPBWireType::FIXED32:
+                $uint32 = 0;
+                if (!$input->readLittleEndian32($uint32)) {
+                    throw new GPBDecodeException(
+                        "Unexpected EOF inside fixed32.");
+                }
+                return;
+            case GPBWireType::LENGTH_DELIMITED:
+                $length = 0;
+                if (!$input->readVarint32($length)) {
+                    throw new GPBDecodeException(
+                        "Unexpected EOF inside length.");
+                }
+                $data = NULL;
+                if (!$input->readRaw($length, $data)) {
+                    throw new GPBDecodeException(
+                        "Unexpected EOF inside length delimited data.");
+                }
+                return;
+            case GPBWireType::START_GROUP:
+            case GPBWireType::END_GROUP:
+                throw new GPBDecodeException("Unexpected wire type.");
+            default:
+                throw new GPBDecodeException("Unexpected wire type.");
+        }
+    }
+
+    /**
+     * @ignore
+     */
     private static function parseFieldFromStreamNoTag($input, $field, &$value)
     {
         switch ($field->getType()) {
@@ -278,7 +337,6 @@
                 }
                 break;
             case GPBType::GROUP:
-                echo "GROUP\xA";
                 trigger_error("Not implemented.", E_ERROR);
                 break;
             case GPBType::MESSAGE:
@@ -349,19 +407,25 @@
     private function parseFieldFromStream($tag, $input, $field)
     {
         $value = null;
-        $field_type = $field->getType();
 
-        $value_format = GPBWire::UNKNOWN;
-        if (GPBWire::getTagWireType($tag) ===
-            GPBWire::getWireType($field_type)) {
+        if (is_null($field)) {
+            $value_format = GPBWire::UNKNOWN;
+        } elseif (GPBWire::getTagWireType($tag) ===
+            GPBWire::getWireType($field->getType())) {
             $value_format = GPBWire::NORMAL_FORMAT;
         } elseif ($field->isPackable() &&
             GPBWire::getTagWireType($tag) ===
             GPBWire::WIRETYPE_LENGTH_DELIMITED) {
             $value_format = GPBWire::PACKED_FORMAT;
+        } else {
+            // the wire type doesn't match. Put it in our unknown field set.
+            $value_format = GPBWire::UNKNOWN;
         }
 
-        if ($value_format === GPBWire::NORMAL_FORMAT) {
+        if ($value_format === GPBWire::UNKNOWN) {
+            self::skipField($input, $tag);
+            return;
+        } elseif ($value_format === GPBWire::NORMAL_FORMAT) {
             self::parseFieldFromStreamNoTag($input, $field, $value);
         } elseif ($value_format === GPBWire::PACKED_FORMAT) {
             $length = 0;
@@ -373,20 +437,18 @@
             $getter = $field->getGetter();
             while ($input->bytesUntilLimit() > 0) {
                 self::parseFieldFromStreamNoTag($input, $field, $value);
-                $this->$getter()[] = $value;
+                $this->appendHelper($field, $value);
             }
             $input->popLimit($limit);
             return;
         } else {
-            return false;
+            return;
         }
 
         if ($field->isMap()) {
-            $getter = $field->getGetter();
-            $this->$getter()[$value->getKey()] = $value->getValue();
+            $this->kvUpdateHelper($field, $value->getKey(), $value->getValue());
         } else if ($field->isRepeated()) {
-            $getter = $field->getGetter();
-            $this->$getter()[] = $value;
+            $this->appendHelper($field, $value);
         } else {
             $setter = $field->getSetter();
             $this->$setter($value);
@@ -533,9 +595,10 @@
                           $klass = $value_field->getMessageType()->getClass();
                           $copy = new $klass;
                           $copy->mergeFrom($value);
-                          $this->$getter()[$key] = $copy;
+
+                          $this->kvUpdateHelper($field, $key, $copy);
                       } else {
-                          $this->$getter()[$key] = $value;
+                          $this->kvUpdateHelper($field, $key, $value);
                       }
                   }
               }
@@ -546,9 +609,9 @@
                           $klass = $field->getMessageType()->getClass();
                           $copy = new $klass;
                           $copy->mergeFrom($tmp);
-                          $this->$getter()[] = $copy;
+                          $this->appendHelper($field, $copy);
                       } else {
-                          $this->$getter()[] = $tmp;
+                          $this->appendHelper($field, $tmp);
                       }
                   }
               }
@@ -584,11 +647,29 @@
      */
     public function mergeFromString($data)
     {
-        $input = new InputStream($data);
+        $input = new CodedInputStream($data);
         $this->parseFromStream($input);
     }
 
     /**
+     * Parses a json string to protobuf message.
+     *
+     * This function takes a string in the json wire format, matching the
+     * encoding output by serializeToJsonString().
+     * See mergeFrom() for merging behavior, if the field is already set in the
+     * specified message.
+     *
+     * @param string $data Json protobuf data.
+     * @return null.
+     * @throws Exception Invalid data.
+     */
+    public function mergeFromJsonString($data)
+    {
+        $input = new RawInputStream($data);
+        $this->parseFromJsonStream($input);
+    }
+
+    /**
      * @ignore
      */
     public function parseFromStream($input)
@@ -603,15 +684,247 @@
             $number = GPBWire::getTagFieldNumber($tag);
             $field = $this->desc->getFieldByNumber($number);
 
-            // Check whether we retrieved a known field
-            if ($field === NULL) {
-              continue;
-            }
-
             $this->parseFieldFromStream($tag, $input, $field);
         }
     }
 
+    private function convertJsonValueToProtoValue(
+        $value,
+        $field,
+        $is_map_key = false)
+    {
+        if (is_null($value)) {
+            return $this->defaultValue($field);
+        }
+        switch ($field->getType()) {
+            case GPBType::MESSAGE:
+                $klass = $field->getMessageType()->getClass();
+                $submsg = new $klass;
+
+                if ($field->isTimestamp()) {
+                    if (!is_string($value)) {
+                        throw new GPBDecodeException("Expect string.");
+                    }
+                    try {
+                        $timestamp = GPBUtil::parseTimestamp($value);
+                    } catch (\Exception $e) {
+                        throw new GPBDecodeException("Invalid RFC 3339 timestamp: ".$e->getMessage());
+                    }
+
+                    $submsg->setSeconds($timestamp->getSeconds());
+                    $submsg->setNanos($timestamp->getNanos());
+                } else if ($klass !== "Google\Protobuf\Any") {
+                    if (!is_object($value) && !is_array($value)) {
+                        throw new GPBDecodeException("Expect message.");
+                    }
+
+                    $submsg->mergeFromJsonArray($value);
+                }
+                return $submsg;
+            case GPBType::ENUM:
+                if (is_integer($value)) {
+                    return $value;
+                } else {
+                    $enum_value =
+                        $field->getEnumType()->getValueByName($value);
+                }
+                if (!is_null($enum_value)) {
+                    return $enum_value->getNumber();
+                }
+            case GPBType::STRING:
+                if (!is_string($value)) {
+                    throw new GPBDecodeException("Expect string");
+                }
+                return $value;
+            case GPBType::BYTES:
+                if (!is_string($value)) {
+                    throw new GPBDecodeException("Expect string");
+                }
+                $proto_value = base64_decode($value, true);
+                if ($proto_value === false) {
+                    throw new GPBDecodeException(
+                        "Invalid base64 characters");
+                }
+                return $proto_value;
+            case GPBType::BOOL:
+                if ($is_map_key) {
+                    if ($value === "true") {
+                        return true;
+                    }
+                    if ($value === "false") {
+                        return false;
+                    }
+                    throw new GPBDecodeException(
+                        "Bool field only accept bool value");
+                }
+                if (!is_bool($value)) {
+                    throw new GPBDecodeException(
+                        "Bool field only accept bool value");
+                }
+                return $value;
+            case GPBType::FLOAT:
+                if ($value === "Infinity") {
+                    return INF;
+                }
+                if ($value === "-Infinity") {
+                    return -INF;
+                }
+                if ($value === "NaN") {
+                    return NAN;
+                }
+                return $value;
+            case GPBType::DOUBLE:
+                if ($value === "Infinity") {
+                    return INF;
+                }
+                if ($value === "-Infinity") {
+                    return -INF;
+                }
+                if ($value === "NaN") {
+                    return NAN;
+                }
+                return $value;
+            case GPBType::INT32:
+                if (!is_numeric($value)) {
+                   throw new GPBDecodeException(
+                       "Invalid data type for int32 field");
+                }
+                if (bccomp($value, "2147483647") > 0) {
+                   throw new GPBDecodeException(
+                       "Int32 too large");
+                }
+                if (bccomp($value, "-2147483648") < 0) {
+                   throw new GPBDecodeException(
+                       "Int32 too small");
+                }
+                return $value;
+            case GPBType::UINT32:
+                if (!is_numeric($value)) {
+                   throw new GPBDecodeException(
+                       "Invalid data type for uint32 field");
+                }
+                if (bccomp($value, 4294967295) > 0) {
+                    throw new GPBDecodeException(
+                        "Uint32 too large");
+                }
+                return $value;
+            case GPBType::INT64:
+                if (!is_numeric($value)) {
+                   throw new GPBDecodeException(
+                       "Invalid data type for int64 field");
+                }
+                if (bccomp($value, "9223372036854775807") > 0) {
+                    throw new GPBDecodeException(
+                        "Int64 too large");
+                }
+                if (bccomp($value, "-9223372036854775808") < 0) {
+                    throw new GPBDecodeException(
+                        "Int64 too small");
+                }
+                return $value;
+            case GPBType::UINT64:
+                if (!is_numeric($value)) {
+                   throw new GPBDecodeException(
+                       "Invalid data type for int64 field");
+                }
+                if (bccomp($value, "18446744073709551615") > 0) {
+                    throw new GPBDecodeException(
+                        "Uint64 too large");
+                }
+                if (bccomp($value, "9223372036854775807") > 0) {
+                    $value = bcsub($value, "18446744073709551616");
+                }
+                return $value;
+            case GPBType::FIXED64:
+                return $value;
+            default:
+                return $value;
+        }
+    }
+
+    private function mergeFromJsonArray($array)
+    {
+        foreach ($array as $key => $value) {
+            $field = $this->desc->getFieldByJsonName($key);
+            if (is_null($field)) {
+                $field = $this->desc->getFieldByName($key);
+                if (is_null($field)) {
+                    continue;
+                }
+            }
+            $setter = $field->getSetter();
+            if ($field->isMap()) {
+                if (is_null($value)) {
+                    continue;
+                }
+                $key_field = $field->getMessageType()->getFieldByNumber(1);
+                $value_field = $field->getMessageType()->getFieldByNumber(2);
+                foreach ($value as $tmp_key => $tmp_value) {
+                    if (is_null($tmp_value)) {
+                        throw new \Exception(
+                            "Map value field element cannot be null.");
+                    }
+                    $proto_key =
+                        $this->convertJsonValueToProtoValue(
+                            $tmp_key,
+                            $key_field,
+                            true);
+                    $proto_value =
+                        $this->convertJsonValueToProtoValue(
+                            $tmp_value,
+                            $value_field);
+                    self::kvUpdateHelper($field, $proto_key, $proto_value);
+                }
+            } else if ($field->isRepeated()) {
+                if (is_null($value)) {
+                    continue;
+                }
+                foreach ($value as $tmp) {
+                    if (is_null($tmp)) {
+                        throw new \Exception(
+                            "Repeated field elements cannot be null.");
+                    }
+                    $proto_value =
+                        $this->convertJsonValueToProtoValue($tmp, $field);
+                    self::appendHelper($field, $proto_value);
+                }
+            } else {
+                $setter = $field->getSetter();
+                $proto_value =
+                    $this->convertJsonValueToProtoValue($value, $field);
+                if ($field->getType() === GPBType::MESSAGE) {
+                    if (is_null($proto_value)) {
+                        continue;
+                    }
+                    $getter = $field->getGetter();
+                    $submsg = $this->$getter();
+                    if (!is_null($submsg)) {
+                        $submsg->mergeFrom($proto_value);
+                        continue;
+                    }
+                }
+                $this->$setter($proto_value);
+            }
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    public function parseFromJsonStream($input)
+    {
+        $array = json_decode($input->getData(), JSON_BIGINT_AS_STRING);
+        if (is_null($array)) {
+            throw new GPBDecodeException(
+                "Cannot decode json string.");
+        }
+        try {
+            $this->mergeFromJsonArray($array);
+        } catch (Exception $e) {
+            throw new GPBDecodeException($e->getMessage());
+        }
+    }
+
     /**
      * @ignore
      */
@@ -651,7 +964,7 @@
             foreach ($values as $value) {
                 $size += $this->fieldDataOnlyByteSize($field, $value);
             }
-            if (!$output->writeVarint32($size)) {
+            if (!$output->writeVarint32($size, true)) {
                 return false;
             }
         }
@@ -712,6 +1025,16 @@
     /**
      * @ignore
      */
+    private function serializeFieldToJsonStream(&$output, $field)
+    {
+        $getter = $field->getGetter();
+        $values = $this->$getter();
+        return GPBJsonWire::serializeFieldToStream($values, $field, $output);
+    }
+
+    /**
+     * @ignore
+     */
     public function serializeToStream(&$output)
     {
         $fields = $this->desc->getField();
@@ -724,17 +1047,58 @@
     }
 
     /**
+     * @ignore
+     */
+    public function serializeToJsonStream(&$output)
+    {
+        if (get_class($this) === 'Google\Protobuf\Timestamp') {
+            $timestamp = GPBUtil::formatTimestamp($this);
+            $timestamp = json_encode($timestamp);
+            $output->writeRaw($timestamp, strlen($timestamp));
+        } else {
+            $output->writeRaw("{", 1);
+            $fields = $this->desc->getField();
+            $first = true;
+            foreach ($fields as $field) {
+                if ($this->existField($field)) {
+                    if ($first) {
+                        $first = false;
+                    } else {
+                        $output->writeRaw(",", 1);
+                    }
+                    if (!$this->serializeFieldToJsonStream($output, $field)) {
+                        return false;
+                    }
+                }
+            }
+            $output->writeRaw("}", 1);
+        }
+        return true;
+    }
+
+    /**
      * Serialize the message to string.
      * @return string Serialized binary protobuf data.
      */
     public function serializeToString()
     {
-        $output = new OutputStream($this->byteSize());
+        $output = new CodedOutputStream($this->byteSize());
         $this->serializeToStream($output);
         return $output->getData();
     }
 
     /**
+     * Serialize the message to json string.
+     * @return string Serialized json protobuf data.
+     */
+    public function serializeToJsonString()
+    {
+        $output = new CodedOutputStream($this->jsonByteSize());
+        $this->serializeToJsonStream($output);
+        return $output->getData();
+    }
+
+    /**
      * @ignore
      */
     private function existField($field)
@@ -747,8 +1111,14 @@
         }
 
         $getter = $field->getGetter();
-        $value = $this->$getter();
-        return $value !== $this->defaultValue($field);
+        $values = $this->$getter();
+        if ($field->isMap()) {
+            return count($values) !== 0;
+        } elseif ($field->isRepeated()) {
+            return count($values) !== 0;
+        } else {
+            return $values !== $this->defaultValue($field);
+        }
     }
 
     /**
@@ -831,6 +1201,101 @@
     /**
      * @ignore
      */
+    private function fieldDataOnlyJsonByteSize($field, $value)
+    {
+        $size = 0;
+
+        switch ($field->getType()) {
+            case GPBType::SFIXED32:
+            case GPBType::SINT32:
+            case GPBType::INT32:
+                $size += strlen(strval($value));
+                break;
+            case GPBType::FIXED32:
+            case GPBType::UINT32:
+                if ($value < 0) {
+                    $value = bcadd($value, "4294967296");
+                }
+                $size += strlen(strval($value));
+                break;
+            case GPBType::FIXED64:
+            case GPBType::UINT64:
+                if ($value < 0) {
+                    $value = bcadd($value, "18446744073709551616");
+                }
+                // Intentional fall through.
+            case GPBType::SFIXED64:
+            case GPBType::INT64:
+            case GPBType::SINT64:
+                $size += 2;  // size for ""
+                $size += strlen(strval($value));
+                break;
+            case GPBType::FLOAT:
+                if (is_nan($value)) {
+                    $size += strlen("NaN") + 2;
+                } elseif ($value === INF) {
+                    $size += strlen("Infinity") + 2;
+                } elseif ($value === -INF) {
+                    $size += strlen("-Infinity") + 2;
+                } else {
+                    $size += strlen(sprintf("%.8g", $value));
+                }
+                break;
+            case GPBType::DOUBLE:
+                if (is_nan($value)) {
+                    $size += strlen("NaN") + 2;
+                } elseif ($value === INF) {
+                    $size += strlen("Infinity") + 2;
+                } elseif ($value === -INF) {
+                    $size += strlen("-Infinity") + 2;
+                } else {
+                    $size += strlen(sprintf("%.17g", $value));
+                }
+                break;
+            case GPBType::ENUM:
+                $enum_desc = $field->getEnumType();
+                $enum_value_desc = $enum_desc->getValueByNumber($value);
+                if (!is_null($enum_value_desc)) {
+                    $size += 2;  // size for ""
+                    $size += strlen($enum_value_desc->getName());
+                } else {
+                    $str_value = strval($value);
+                    $size += strlen($str_value);
+                }
+                break;
+            case GPBType::BOOL:
+                if ($value) {
+                    $size += 4;
+                } else {
+                    $size += 5;
+                }
+                break;
+            case GPBType::STRING:
+                $value = json_encode($value);
+                $size += strlen($value);
+                break;
+            case GPBType::BYTES:
+                $size += strlen(base64_encode($value));
+                $size += 2;  // size for \"\"
+                break;
+            case GPBType::MESSAGE:
+                $size += $value->jsonByteSize();
+                break;
+#             case GPBType::GROUP:
+#                 // TODO(teboring): Add support.
+#                 user_error("Unsupported type.");
+#                 break;
+            default:
+                user_error("Unsupported type " . $field->getType());
+                return 0;
+        }
+
+        return $size;
+    }
+
+    /**
+     * @ignore
+     */
     private function fieldByteSize($field)
     {
         $size = 0;
@@ -845,12 +1310,18 @@
                 $value_field = $message_type->getFieldByNumber(2);
                 foreach ($values as $key => $value) {
                     $data_size = 0;
-                    $data_size += $this->fieldDataOnlyByteSize($key_field, $key);
-                    $data_size += $this->fieldDataOnlyByteSize(
-                        $value_field,
-                        $value);
-                    $data_size += GPBWire::tagSize($key_field);
-                    $data_size += GPBWire::tagSize($value_field);
+                    if ($key != $this->defaultValue($key_field)) {
+                        $data_size += $this->fieldDataOnlyByteSize(
+                            $key_field,
+                            $key);
+                        $data_size += GPBWire::tagSize($key_field);
+                    }
+                    if ($value != $this->defaultValue($value_field)) {
+                        $data_size += $this->fieldDataOnlyByteSize(
+                            $value_field,
+                            $value);
+                        $data_size += GPBWire::tagSize($value_field);
+                    }
                     $size += GPBWire::varint32Size($data_size) + $data_size;
                 }
             }
@@ -886,6 +1357,69 @@
     /**
      * @ignore
      */
+    private function fieldJsonByteSize($field)
+    {
+        $size = 0;
+
+        if ($field->isMap()) {
+            $getter = $field->getGetter();
+            $values = $this->$getter();
+            $count = count($values);
+            if ($count !== 0) {
+                $size += 5;                              // size for "\"\":{}".
+                $size += strlen($field->getJsonName());  // size for field name
+                $size += $count - 1;                     // size for commas
+                $getter = $field->getGetter();
+                $map_entry = $field->getMessageType();
+                $key_field = $map_entry->getFieldByNumber(1);
+                $value_field = $map_entry->getFieldByNumber(2);
+                switch ($key_field->getType()) {
+                case GPBType::STRING:
+                case GPBType::SFIXED64:
+                case GPBType::INT64:
+                case GPBType::SINT64:
+                case GPBType::FIXED64:
+                case GPBType::UINT64:
+                    $additional_quote = false;
+                    break;
+                default:
+                    $additional_quote = true;
+                }
+                foreach ($values as $key => $value) {
+                    if ($additional_quote) {
+                        $size += 2;  // size for ""
+                    }
+                    $size += $this->fieldDataOnlyJsonByteSize($key_field, $key);
+                    $size += $this->fieldDataOnlyJsonByteSize($value_field, $value);
+                    $size += 1;  // size for :
+                }
+            }
+        } elseif ($field->isRepeated()) {
+            $getter = $field->getGetter();
+            $values = $this->$getter();
+            $count = count($values);
+            if ($count !== 0) {
+                $size += 5;                              // size for "\"\":[]".
+                $size += strlen($field->getJsonName());  // size for field name
+                $size += $count - 1;                     // size for commas
+                $getter = $field->getGetter();
+                foreach ($values as $value) {
+                    $size += $this->fieldDataOnlyJsonByteSize($field, $value);
+                }
+            }
+        } elseif ($this->existField($field)) {
+            $size += 3;                              // size for "\"\":".
+            $size += strlen($field->getJsonName());  // size for field name
+            $getter = $field->getGetter();
+            $value = $this->$getter();
+            $size += $this->fieldDataOnlyJsonByteSize($field, $value);
+        }
+        return $size;
+    }
+
+    /**
+     * @ignore
+     */
     public function byteSize()
     {
         $size = 0;
@@ -896,4 +1430,59 @@
         }
         return $size;
     }
+
+    private function appendHelper($field, $append_value)
+    {
+        $getter = $field->getGetter();
+        $setter = $field->getSetter();
+
+        $field_arr_value = $this->$getter();
+        $field_arr_value[] = $append_value;
+
+        if (!is_object($field_arr_value)) {
+            $this->$setter($field_arr_value);
+        }
+    }
+
+    private function kvUpdateHelper($field, $update_key, $update_value)
+    {
+        $getter = $field->getGetter();
+        $setter = $field->getSetter();
+
+        $field_arr_value = $this->$getter();
+        $field_arr_value[$update_key] = $update_value;
+
+        if (!is_object($field_arr_value)) {
+            $this->$setter($field_arr_value);
+        }
+    }
+
+    /**
+     * @ignore
+     */
+    public function jsonByteSize()
+    {
+        $size = 0;
+        if (get_class($this) === 'Google\Protobuf\Timestamp') {
+            $timestamp = GPBUtil::formatTimestamp($this);
+            $timestamp = json_encode($timestamp);
+            $size += strlen($timestamp);
+        } else {
+            // Size for "{}".
+            $size += 2;
+            
+            $fields = $this->desc->getField();
+            $count = 0;
+            foreach ($fields as $field) {
+                $field_size = $this->fieldJsonByteSize($field);
+                $size += $field_size;
+                if ($field_size != 0) {
+                  $count++;
+                }
+            }
+            // size for comma
+            $size += $count > 0 ? ($count - 1) : 0;
+        }
+        return $size;
+    }
 }
diff --git a/php/src/Google/Protobuf/Internal/MessageOptions.php b/php/src/Google/Protobuf/Internal/MessageOptions.php
index 747f329..99ff3d0 100644
--- a/php/src/Google/Protobuf/Internal/MessageOptions.php
+++ b/php/src/Google/Protobuf/Internal/MessageOptions.php
@@ -8,16 +8,14 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.MessageOptions</code>
+ * Generated from protobuf message <code>google.protobuf.MessageOptions</code>
  */
 class MessageOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Set true to use the old proto1 MessageSet wire format for extensions.
      * This is provided for backwards-compatibility with the MessageSet wire
      * format.  You should not use this for any other reason:  It's less
@@ -33,41 +31,35 @@
      * be int32s, enums, or repeated messages.
      * Because this is an option, the above two restrictions are not enforced by
      * the protocol compiler.
-     * </pre>
      *
-     * <code>optional bool message_set_wire_format = 1 [default = false];</code>
+     * Generated from protobuf field <code>optional bool message_set_wire_format = 1 [default = false];</code>
      */
     private $message_set_wire_format = false;
     private $has_message_set_wire_format = false;
     /**
-     * <pre>
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
      * from proto1 easier; new code should avoid fields named "descriptor".
-     * </pre>
      *
-     * <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
+     * Generated from protobuf field <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
      */
     private $no_standard_descriptor_accessor = false;
     private $has_no_standard_descriptor_accessor = false;
     /**
-     * <pre>
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the message, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating messages.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <pre>
      * Whether the message is an automatically generated map entry type for the
      * maps field.
      * For maps fields:
-     *     map&lt;KeyType, ValueType&gt; map_field = 1;
+     *     map<KeyType, ValueType> map_field = 1;
      * The parsed descriptor looks like:
      *     message MapFieldEntry {
      *         option map_entry = true;
@@ -82,18 +74,15 @@
      * NOTE: Do not set the option in .proto files. Always use the maps syntax
      * instead. The option should only be implicitly set by the proto compiler
      * parser.
-     * </pre>
      *
-     * <code>optional bool map_entry = 7;</code>
+     * Generated from protobuf field <code>optional bool map_entry = 7;</code>
      */
     private $map_entry = false;
     private $has_map_entry = false;
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -104,7 +93,6 @@
     }
 
     /**
-     * <pre>
      * Set true to use the old proto1 MessageSet wire format for extensions.
      * This is provided for backwards-compatibility with the MessageSet wire
      * format.  You should not use this for any other reason:  It's less
@@ -120,9 +108,9 @@
      * be int32s, enums, or repeated messages.
      * Because this is an option, the above two restrictions are not enforced by
      * the protocol compiler.
-     * </pre>
      *
-     * <code>optional bool message_set_wire_format = 1 [default = false];</code>
+     * Generated from protobuf field <code>optional bool message_set_wire_format = 1 [default = false];</code>
+     * @return bool
      */
     public function getMessageSetWireFormat()
     {
@@ -130,7 +118,6 @@
     }
 
     /**
-     * <pre>
      * Set true to use the old proto1 MessageSet wire format for extensions.
      * This is provided for backwards-compatibility with the MessageSet wire
      * format.  You should not use this for any other reason:  It's less
@@ -146,15 +133,18 @@
      * be int32s, enums, or repeated messages.
      * Because this is an option, the above two restrictions are not enforced by
      * the protocol compiler.
-     * </pre>
      *
-     * <code>optional bool message_set_wire_format = 1 [default = false];</code>
+     * Generated from protobuf field <code>optional bool message_set_wire_format = 1 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setMessageSetWireFormat($var)
     {
         GPBUtil::checkBool($var);
         $this->message_set_wire_format = $var;
         $this->has_message_set_wire_format = true;
+
+        return $this;
     }
 
     public function hasMessageSetWireFormat()
@@ -163,13 +153,12 @@
     }
 
     /**
-     * <pre>
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
      * from proto1 easier; new code should avoid fields named "descriptor".
-     * </pre>
      *
-     * <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
+     * Generated from protobuf field <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
+     * @return bool
      */
     public function getNoStandardDescriptorAccessor()
     {
@@ -177,19 +166,21 @@
     }
 
     /**
-     * <pre>
      * Disables the generation of the standard "descriptor()" accessor, which can
      * conflict with a field of the same name.  This is meant to make migration
      * from proto1 easier; new code should avoid fields named "descriptor".
-     * </pre>
      *
-     * <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
+     * Generated from protobuf field <code>optional bool no_standard_descriptor_accessor = 2 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setNoStandardDescriptorAccessor($var)
     {
         GPBUtil::checkBool($var);
         $this->no_standard_descriptor_accessor = $var;
         $this->has_no_standard_descriptor_accessor = true;
+
+        return $this;
     }
 
     public function hasNoStandardDescriptorAccessor()
@@ -198,14 +189,13 @@
     }
 
     /**
-     * <pre>
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the message, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating messages.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -213,20 +203,22 @@
     }
 
     /**
-     * <pre>
      * Is this message deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the message, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating messages.
-     * </pre>
      *
-     * <code>optional bool deprecated = 3 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 3 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -235,11 +227,10 @@
     }
 
     /**
-     * <pre>
      * Whether the message is an automatically generated map entry type for the
      * maps field.
      * For maps fields:
-     *     map&lt;KeyType, ValueType&gt; map_field = 1;
+     *     map<KeyType, ValueType> map_field = 1;
      * The parsed descriptor looks like:
      *     message MapFieldEntry {
      *         option map_entry = true;
@@ -254,9 +245,9 @@
      * NOTE: Do not set the option in .proto files. Always use the maps syntax
      * instead. The option should only be implicitly set by the proto compiler
      * parser.
-     * </pre>
      *
-     * <code>optional bool map_entry = 7;</code>
+     * Generated from protobuf field <code>optional bool map_entry = 7;</code>
+     * @return bool
      */
     public function getMapEntry()
     {
@@ -264,11 +255,10 @@
     }
 
     /**
-     * <pre>
      * Whether the message is an automatically generated map entry type for the
      * maps field.
      * For maps fields:
-     *     map&lt;KeyType, ValueType&gt; map_field = 1;
+     *     map<KeyType, ValueType> map_field = 1;
      * The parsed descriptor looks like:
      *     message MapFieldEntry {
      *         option map_entry = true;
@@ -283,15 +273,18 @@
      * NOTE: Do not set the option in .proto files. Always use the maps syntax
      * instead. The option should only be implicitly set by the proto compiler
      * parser.
-     * </pre>
      *
-     * <code>optional bool map_entry = 7;</code>
+     * Generated from protobuf field <code>optional bool map_entry = 7;</code>
+     * @param bool $var
+     * @return $this
      */
     public function setMapEntry($var)
     {
         GPBUtil::checkBool($var);
         $this->map_entry = $var;
         $this->has_map_entry = true;
+
+        return $this;
     }
 
     public function hasMapEntry()
@@ -300,11 +293,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -312,17 +304,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
index 3d8df7a..ccfce2d 100644
--- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
@@ -8,58 +8,49 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a method of a service.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.MethodDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.MethodDescriptorProto</code>
  */
 class MethodDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <pre>
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
-     * </pre>
      *
-     * <code>optional string input_type = 2;</code>
+     * Generated from protobuf field <code>optional string input_type = 2;</code>
      */
     private $input_type = '';
     private $has_input_type = false;
     /**
-     * <code>optional string output_type = 3;</code>
+     * Generated from protobuf field <code>optional string output_type = 3;</code>
      */
     private $output_type = '';
     private $has_output_type = false;
     /**
-     * <code>optional .google.protobuf.MethodOptions options = 4;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
      */
     private $options = null;
     private $has_options = false;
     /**
-     * <pre>
      * Identifies if client streams multiple client messages
-     * </pre>
      *
-     * <code>optional bool client_streaming = 5 [default = false];</code>
+     * Generated from protobuf field <code>optional bool client_streaming = 5 [default = false];</code>
      */
     private $client_streaming = false;
     private $has_client_streaming = false;
     /**
-     * <pre>
      * Identifies if server streams multiple server messages
-     * </pre>
      *
-     * <code>optional bool server_streaming = 6 [default = false];</code>
+     * Generated from protobuf field <code>optional bool server_streaming = 6 [default = false];</code>
      */
     private $server_streaming = false;
     private $has_server_streaming = false;
@@ -70,7 +61,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -78,13 +70,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -93,12 +89,11 @@
     }
 
     /**
-     * <pre>
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
-     * </pre>
      *
-     * <code>optional string input_type = 2;</code>
+     * Generated from protobuf field <code>optional string input_type = 2;</code>
+     * @return string
      */
     public function getInputType()
     {
@@ -106,18 +101,20 @@
     }
 
     /**
-     * <pre>
      * Input and output type names.  These are resolved in the same way as
      * FieldDescriptorProto.type_name, but must refer to a message type.
-     * </pre>
      *
-     * <code>optional string input_type = 2;</code>
+     * Generated from protobuf field <code>optional string input_type = 2;</code>
+     * @param string $var
+     * @return $this
      */
     public function setInputType($var)
     {
         GPBUtil::checkString($var, True);
         $this->input_type = $var;
         $this->has_input_type = true;
+
+        return $this;
     }
 
     public function hasInputType()
@@ -126,7 +123,8 @@
     }
 
     /**
-     * <code>optional string output_type = 3;</code>
+     * Generated from protobuf field <code>optional string output_type = 3;</code>
+     * @return string
      */
     public function getOutputType()
     {
@@ -134,13 +132,17 @@
     }
 
     /**
-     * <code>optional string output_type = 3;</code>
+     * Generated from protobuf field <code>optional string output_type = 3;</code>
+     * @param string $var
+     * @return $this
      */
     public function setOutputType($var)
     {
         GPBUtil::checkString($var, True);
         $this->output_type = $var;
         $this->has_output_type = true;
+
+        return $this;
     }
 
     public function hasOutputType()
@@ -149,7 +151,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.MethodOptions options = 4;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
+     * @return \Google\Protobuf\Internal\MethodOptions
      */
     public function getOptions()
     {
@@ -157,13 +160,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.MethodOptions options = 4;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
+     * @param \Google\Protobuf\Internal\MethodOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\MethodOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
@@ -172,11 +179,10 @@
     }
 
     /**
-     * <pre>
      * Identifies if client streams multiple client messages
-     * </pre>
      *
-     * <code>optional bool client_streaming = 5 [default = false];</code>
+     * Generated from protobuf field <code>optional bool client_streaming = 5 [default = false];</code>
+     * @return bool
      */
     public function getClientStreaming()
     {
@@ -184,17 +190,19 @@
     }
 
     /**
-     * <pre>
      * Identifies if client streams multiple client messages
-     * </pre>
      *
-     * <code>optional bool client_streaming = 5 [default = false];</code>
+     * Generated from protobuf field <code>optional bool client_streaming = 5 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setClientStreaming($var)
     {
         GPBUtil::checkBool($var);
         $this->client_streaming = $var;
         $this->has_client_streaming = true;
+
+        return $this;
     }
 
     public function hasClientStreaming()
@@ -203,11 +211,10 @@
     }
 
     /**
-     * <pre>
      * Identifies if server streams multiple server messages
-     * </pre>
      *
-     * <code>optional bool server_streaming = 6 [default = false];</code>
+     * Generated from protobuf field <code>optional bool server_streaming = 6 [default = false];</code>
+     * @return bool
      */
     public function getServerStreaming()
     {
@@ -215,17 +222,19 @@
     }
 
     /**
-     * <pre>
      * Identifies if server streams multiple server messages
-     * </pre>
      *
-     * <code>optional bool server_streaming = 6 [default = false];</code>
+     * Generated from protobuf field <code>optional bool server_streaming = 6 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setServerStreaming($var)
     {
         GPBUtil::checkBool($var);
         $this->server_streaming = $var;
         $this->has_server_streaming = true;
+
+        return $this;
     }
 
     public function hasServerStreaming()
diff --git a/php/src/Google/Protobuf/Internal/MethodOptions.php b/php/src/Google/Protobuf/Internal/MethodOptions.php
index 6dca585..baa806b 100644
--- a/php/src/Google/Protobuf/Internal/MethodOptions.php
+++ b/php/src/Google/Protobuf/Internal/MethodOptions.php
@@ -8,37 +8,32 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.MethodOptions</code>
+ * Generated from protobuf message <code>google.protobuf.MethodOptions</code>
  */
 class MethodOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Is this method deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the method, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating methods.
-     * </pre>
      *
-     * <code>optional bool deprecated = 33 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
      */
     private $idempotency_level = 0;
     private $has_idempotency_level = false;
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -49,14 +44,13 @@
     }
 
     /**
-     * <pre>
      * Is this method deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the method, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating methods.
-     * </pre>
      *
-     * <code>optional bool deprecated = 33 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -64,20 +58,22 @@
     }
 
     /**
-     * <pre>
      * Is this method deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the method, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating methods.
-     * </pre>
      *
-     * <code>optional bool deprecated = 33 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -86,7 +82,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
+     * @return int
      */
     public function getIdempotencyLevel()
     {
@@ -94,13 +91,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
+     * Generated from protobuf field <code>optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];</code>
+     * @param int $var
+     * @return $this
      */
     public function setIdempotencyLevel($var)
     {
         GPBUtil::checkEnum($var, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class);
         $this->idempotency_level = $var;
         $this->has_idempotency_level = true;
+
+        return $this;
     }
 
     public function hasIdempotencyLevel()
@@ -109,11 +110,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -121,17 +121,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php b/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php
index ce4adfe..9e06d8e 100644
--- a/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php
+++ b/php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php
@@ -5,34 +5,28 @@
 namespace Google\Protobuf\Internal;
 
 /**
- * <pre>
  * Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
  * or neither? HTTP based RPC implementation may choose GET verb for safe
  * methods, and PUT verb for idempotent methods instead of the default POST.
- * </pre>
  *
- * Protobuf enum <code>google.protobuf.MethodOptions.IdempotencyLevel</code>
+ * Protobuf enum <code>Google\Protobuf\Internal</code>
  */
 class MethodOptions_IdempotencyLevel
 {
     /**
-     * <code>IDEMPOTENCY_UNKNOWN = 0;</code>
+     * Generated from protobuf enum <code>IDEMPOTENCY_UNKNOWN = 0;</code>
      */
     const IDEMPOTENCY_UNKNOWN = 0;
     /**
-     * <pre>
      * implies idempotent
-     * </pre>
      *
-     * <code>NO_SIDE_EFFECTS = 1;</code>
+     * Generated from protobuf enum <code>NO_SIDE_EFFECTS = 1;</code>
      */
     const NO_SIDE_EFFECTS = 1;
     /**
-     * <pre>
      * idempotent, but may have side effects
-     * </pre>
      *
-     * <code>IDEMPOTENT = 2;</code>
+     * Generated from protobuf enum <code>IDEMPOTENT = 2;</code>
      */
     const IDEMPOTENT = 2;
 }
diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptor.php b/php/src/Google/Protobuf/Internal/OneofDescriptor.php
new file mode 100644
index 0000000..67b107f
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/OneofDescriptor.php
@@ -0,0 +1,78 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class OneofDescriptor
+{
+    use HasPublicDescriptorTrait;
+
+    private $name;
+    private $fields;
+
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\OneofDescriptor($this);
+    }
+
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function addField(FieldDescriptor $field)
+    {
+        $this->fields[] = $field;
+    }
+
+    public function getFields()
+    {
+        return $this->fields;
+    }
+
+    public static function buildFromProto($oneof_proto, $desc, $index)
+    {
+        $oneof = new OneofDescriptor();
+        $oneof->setName($oneof_proto->getName());
+        foreach ($desc->getField() as $field) {
+            if ($field->getOneofIndex() == $index) {
+                $oneof->addField($field);
+            }
+        }
+        return $oneof;
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
index e5fbe37..15ff061 100644
--- a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
@@ -8,25 +8,22 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a oneof.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.OneofDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.OneofDescriptorProto</code>
  */
 class OneofDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <code>optional .google.protobuf.OneofOptions options = 2;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
      */
     private $options = null;
     private $has_options = false;
@@ -37,7 +34,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -45,13 +43,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -60,7 +62,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.OneofOptions options = 2;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
+     * @return \Google\Protobuf\Internal\OneofOptions
      */
     public function getOptions()
     {
@@ -68,13 +71,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.OneofOptions options = 2;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
+     * @param \Google\Protobuf\Internal\OneofOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\OneofOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
diff --git a/php/src/Google/Protobuf/Internal/OneofOptions.php b/php/src/Google/Protobuf/Internal/OneofOptions.php
index b61325d..e5b4633 100644
--- a/php/src/Google/Protobuf/Internal/OneofOptions.php
+++ b/php/src/Google/Protobuf/Internal/OneofOptions.php
@@ -8,20 +8,17 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.OneofOptions</code>
+ * Generated from protobuf message <code>google.protobuf.OneofOptions</code>
  */
 class OneofOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -32,11 +29,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -44,17 +40,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/RawInputStream.php b/php/src/Google/Protobuf/Internal/RawInputStream.php
new file mode 100644
index 0000000..4e7ed5c
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/RawInputStream.php
@@ -0,0 +1,50 @@
+<?php
+
+// 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.
+
+namespace Google\Protobuf\Internal;
+
+class RawInputStream
+{
+
+    private $buffer;
+
+    public function __construct($buffer)
+    {
+        $this->buffer = $buffer;
+    }
+
+    public function getData()
+    {
+        return $this->buffer;
+    }
+
+}
diff --git a/php/src/Google/Protobuf/Internal/RepeatedField.php b/php/src/Google/Protobuf/Internal/RepeatedField.php
index 2ad4709..797b3b3 100644
--- a/php/src/Google/Protobuf/Internal/RepeatedField.php
+++ b/php/src/Google/Protobuf/Internal/RepeatedField.php
@@ -41,86 +41,6 @@
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * RepeatedFieldIter is used to iterate RepeatedField. It is also need for the
- * foreach syntax.
- */
-class RepeatedFieldIter implements \Iterator
-{
-
-    /**
-     * @ignore
-     */
-    private $position;
-    /**
-     * @ignore
-     */
-    private $container;
-
-    /**
-     * Create iterator instance for RepeatedField.
-     *
-     * @param RepeatedField The RepeatedField instance for which this iterator
-     * is created.
-     * @ignore
-     */
-    public function __construct($container)
-    {
-        $this->position = 0;
-        $this->container = $container;
-    }
-
-    /**
-     * Reset the status of the iterator
-     *
-     * @return void
-     */
-    public function rewind()
-    {
-        $this->position = 0;
-    }
-
-    /**
-     * Return the element at the current position.
-     *
-     * @return object The element at the current position.
-     */
-    public function current()
-    {
-        return $this->container[$this->position];
-    }
-
-    /**
-     * Return the current position.
-     *
-     * @return integer The current position.
-     */
-    public function key()
-    {
-        return $this->position;
-    }
-
-    /**
-     * Move to the next position.
-     *
-     * @return void
-     */
-    public function next()
-    {
-        ++$this->position;
-    }
-
-    /**
-     * Check whether there are more elements to iterate.
-     *
-     * @return bool True if there are more elements to iterate.
-     */
-    public function valid()
-    {
-        return isset($this->container[$this->position]);
-    }
-}
-
-/**
  * RepeatedField is used by generated protocol message classes to manipulate
  * repeated fields. It can be used like native PHP array.
  */
diff --git a/php/src/Google/Protobuf/Internal/RepeatedFieldIter.php b/php/src/Google/Protobuf/Internal/RepeatedFieldIter.php
new file mode 100644
index 0000000..2b6f823
--- /dev/null
+++ b/php/src/Google/Protobuf/Internal/RepeatedFieldIter.php
@@ -0,0 +1,118 @@
+<?php
+
+// 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.
+
+/**
+ * RepeatedField and RepeatedFieldIter are used by generated protocol message
+ * classes to manipulate repeated fields.
+ */
+
+namespace Google\Protobuf\Internal;
+
+/**
+ * RepeatedFieldIter is used to iterate RepeatedField. It is also need for the
+ * foreach syntax.
+ */
+class RepeatedFieldIter implements \Iterator
+{
+
+    /**
+     * @ignore
+     */
+    private $position;
+    /**
+     * @ignore
+     */
+    private $container;
+
+    /**
+     * Create iterator instance for RepeatedField.
+     *
+     * @param RepeatedField The RepeatedField instance for which this iterator
+     * is created.
+     * @ignore
+     */
+    public function __construct($container)
+    {
+        $this->position = 0;
+        $this->container = $container;
+    }
+
+    /**
+     * Reset the status of the iterator
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->position = 0;
+    }
+
+    /**
+     * Return the element at the current position.
+     *
+     * @return object The element at the current position.
+     */
+    public function current()
+    {
+        return $this->container[$this->position];
+    }
+
+    /**
+     * Return the current position.
+     *
+     * @return integer The current position.
+     */
+    public function key()
+    {
+        return $this->position;
+    }
+
+    /**
+     * Move to the next position.
+     *
+     * @return void
+     */
+    public function next()
+    {
+        ++$this->position;
+    }
+
+    /**
+     * Check whether there are more elements to iterate.
+     *
+     * @return bool True if there are more elements to iterate.
+     */
+    public function valid()
+    {
+        return isset($this->container[$this->position]);
+    }
+}
diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
index 4777620..da88e9c 100644
--- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
@@ -8,30 +8,27 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Describes a service.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.ServiceDescriptorProto</code>
+ * Generated from protobuf message <code>google.protobuf.ServiceDescriptorProto</code>
  */
 class ServiceDescriptorProto extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
      */
     private $name = '';
     private $has_name = false;
     /**
-     * <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
      */
     private $method;
     private $has_method = false;
     /**
-     * <code>optional .google.protobuf.ServiceOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
      */
     private $options = null;
     private $has_options = false;
@@ -42,7 +39,8 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @return string
      */
     public function getName()
     {
@@ -50,13 +48,17 @@
     }
 
     /**
-     * <code>optional string name = 1;</code>
+     * Generated from protobuf field <code>optional string name = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setName($var)
     {
         GPBUtil::checkString($var, True);
         $this->name = $var;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -65,7 +67,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getMethod()
     {
@@ -73,13 +76,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.MethodDescriptorProto method = 2;</code>
+     * @param \Google\Protobuf\Internal\MethodDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setMethod(&$var)
+    public function setMethod($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\MethodDescriptorProto::class);
         $this->method = $arr;
         $this->has_method = true;
+
+        return $this;
     }
 
     public function hasMethod()
@@ -88,7 +95,8 @@
     }
 
     /**
-     * <code>optional .google.protobuf.ServiceOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
+     * @return \Google\Protobuf\Internal\ServiceOptions
      */
     public function getOptions()
     {
@@ -96,13 +104,17 @@
     }
 
     /**
-     * <code>optional .google.protobuf.ServiceOptions options = 3;</code>
+     * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
+     * @param \Google\Protobuf\Internal\ServiceOptions $var
+     * @return $this
      */
-    public function setOptions(&$var)
+    public function setOptions($var)
     {
         GPBUtil::checkMessage($var, \Google\Protobuf\Internal\ServiceOptions::class);
         $this->options = $var;
         $this->has_options = true;
+
+        return $this;
     }
 
     public function hasOptions()
diff --git a/php/src/Google/Protobuf/Internal/ServiceOptions.php b/php/src/Google/Protobuf/Internal/ServiceOptions.php
index 62323db..3e7214a 100644
--- a/php/src/Google/Protobuf/Internal/ServiceOptions.php
+++ b/php/src/Google/Protobuf/Internal/ServiceOptions.php
@@ -8,32 +8,27 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.ServiceOptions</code>
+ * Generated from protobuf message <code>google.protobuf.ServiceOptions</code>
  */
 class ServiceOptions extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Is this service deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the service, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating services.
-     * </pre>
      *
-     * <code>optional bool deprecated = 33 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
      */
     private $deprecated = false;
     private $has_deprecated = false;
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
      */
     private $uninterpreted_option;
     private $has_uninterpreted_option = false;
@@ -44,14 +39,13 @@
     }
 
     /**
-     * <pre>
      * Is this service deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the service, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating services.
-     * </pre>
      *
-     * <code>optional bool deprecated = 33 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
+     * @return bool
      */
     public function getDeprecated()
     {
@@ -59,20 +53,22 @@
     }
 
     /**
-     * <pre>
      * Is this service deprecated?
      * Depending on the target platform, this can emit Deprecated annotations
      * for the service, or it will be completely ignored; in the very least,
      * this is a formalization for deprecating services.
-     * </pre>
      *
-     * <code>optional bool deprecated = 33 [default = false];</code>
+     * Generated from protobuf field <code>optional bool deprecated = 33 [default = false];</code>
+     * @param bool $var
+     * @return $this
      */
     public function setDeprecated($var)
     {
         GPBUtil::checkBool($var);
         $this->deprecated = $var;
         $this->has_deprecated = true;
+
+        return $this;
     }
 
     public function hasDeprecated()
@@ -81,11 +77,10 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getUninterpretedOption()
     {
@@ -93,17 +88,19 @@
     }
 
     /**
-     * <pre>
      * The parser stores options it doesn't recognize here. See above.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setUninterpretedOption(&$var)
+    public function setUninterpretedOption($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
         $this->uninterpreted_option = $arr;
         $this->has_uninterpreted_option = true;
+
+        return $this;
     }
 
     public function hasUninterpretedOption()
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
index eab6088..6ce05ed 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo.php
@@ -8,21 +8,17 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * Encapsulates information about the original source file from which a
  * FileDescriptorProto was generated.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.SourceCodeInfo</code>
+ * Generated from protobuf message <code>google.protobuf.SourceCodeInfo</code>
  */
 class SourceCodeInfo extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * A Location identifies a piece of source code in a .proto file which
      * corresponds to a particular definition.  This information is intended
      * to be useful to IDEs, code indexers, documentation generators, and similar
@@ -64,9 +60,8 @@
      * - Code which tries to interpret locations should probably be designed to
      *   ignore those that it doesn't understand, as more types of locations could
      *   be recorded in the future.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
      */
     private $location;
     private $has_location = false;
@@ -77,7 +72,6 @@
     }
 
     /**
-     * <pre>
      * A Location identifies a piece of source code in a .proto file which
      * corresponds to a particular definition.  This information is intended
      * to be useful to IDEs, code indexers, documentation generators, and similar
@@ -119,9 +113,9 @@
      * - Code which tries to interpret locations should probably be designed to
      *   ignore those that it doesn't understand, as more types of locations could
      *   be recorded in the future.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getLocation()
     {
@@ -129,7 +123,6 @@
     }
 
     /**
-     * <pre>
      * A Location identifies a piece of source code in a .proto file which
      * corresponds to a particular definition.  This information is intended
      * to be useful to IDEs, code indexers, documentation generators, and similar
@@ -171,15 +164,18 @@
      * - Code which tries to interpret locations should probably be designed to
      *   ignore those that it doesn't understand, as more types of locations could
      *   be recorded in the future.
-     * </pre>
      *
-     * <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
+     * @param \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setLocation(&$var)
+    public function setLocation($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo_Location::class);
         $this->location = $arr;
         $this->has_location = true;
+
+        return $this;
     }
 
     public function hasLocation()
diff --git a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php b/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
index 5a02b26..19ed2bc 100644
--- a/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
+++ b/php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php
@@ -8,16 +8,14 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * Protobuf type <code>google.protobuf.SourceCodeInfo.Location</code>
+ * Generated from protobuf message <code>google.protobuf.SourceCodeInfo.Location</code>
  */
 class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <pre>
      * Identifies which part of the FileDescriptorProto was defined at this
      * location.
      * Each element is a field number or an index.  They form a path from
@@ -39,27 +37,23 @@
      *   [ 4, 3, 2, 7 ]
      * this path refers to the whole field declaration (from the beginning
      * of the label to the terminating semicolon).
-     * </pre>
      *
-     * <code>repeated int32 path = 1 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
      */
     private $path;
     private $has_path = false;
     /**
-     * <pre>
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
      * These are packed into a single field for efficiency.  Note that line
      * and column numbers are zero-based -- typically you will want to add
      * 1 to each before displaying to a user.
-     * </pre>
      *
-     * <code>repeated int32 span = 2 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 span = 2 [packed = true];</code>
      */
     private $span;
     private $has_span = false;
     /**
-     * <pre>
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
      * attached to the declaration.
@@ -96,19 +90,18 @@
      *    * grault. *&#47;
      *   optional int32 grault = 6;
      *   // ignored detached comments.
-     * </pre>
      *
-     * <code>optional string leading_comments = 3;</code>
+     * Generated from protobuf field <code>optional string leading_comments = 3;</code>
      */
     private $leading_comments = '';
     private $has_leading_comments = false;
     /**
-     * <code>optional string trailing_comments = 4;</code>
+     * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
      */
     private $trailing_comments = '';
     private $has_trailing_comments = false;
     /**
-     * <code>repeated string leading_detached_comments = 6;</code>
+     * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
      */
     private $leading_detached_comments;
     private $has_leading_detached_comments = false;
@@ -119,7 +112,6 @@
     }
 
     /**
-     * <pre>
      * Identifies which part of the FileDescriptorProto was defined at this
      * location.
      * Each element is a field number or an index.  They form a path from
@@ -141,9 +133,9 @@
      *   [ 4, 3, 2, 7 ]
      * this path refers to the whole field declaration (from the beginning
      * of the label to the terminating semicolon).
-     * </pre>
      *
-     * <code>repeated int32 path = 1 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getPath()
     {
@@ -151,7 +143,6 @@
     }
 
     /**
-     * <pre>
      * Identifies which part of the FileDescriptorProto was defined at this
      * location.
      * Each element is a field number or an index.  They form a path from
@@ -173,15 +164,18 @@
      *   [ 4, 3, 2, 7 ]
      * this path refers to the whole field declaration (from the beginning
      * of the label to the terminating semicolon).
-     * </pre>
      *
-     * <code>repeated int32 path = 1 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 path = 1 [packed = true];</code>
+     * @param int[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setPath(&$var)
+    public function setPath($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->path = $arr;
         $this->has_path = true;
+
+        return $this;
     }
 
     public function hasPath()
@@ -190,15 +184,14 @@
     }
 
     /**
-     * <pre>
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
      * These are packed into a single field for efficiency.  Note that line
      * and column numbers are zero-based -- typically you will want to add
      * 1 to each before displaying to a user.
-     * </pre>
      *
-     * <code>repeated int32 span = 2 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 span = 2 [packed = true];</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getSpan()
     {
@@ -206,21 +199,23 @@
     }
 
     /**
-     * <pre>
      * Always has exactly three or four elements: start line, start column,
      * end line (optional, otherwise assumed same as start line), end column.
      * These are packed into a single field for efficiency.  Note that line
      * and column numbers are zero-based -- typically you will want to add
      * 1 to each before displaying to a user.
-     * </pre>
      *
-     * <code>repeated int32 span = 2 [packed = true];</code>
+     * Generated from protobuf field <code>repeated int32 span = 2 [packed = true];</code>
+     * @param int[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setSpan(&$var)
+    public function setSpan($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::INT32);
         $this->span = $arr;
         $this->has_span = true;
+
+        return $this;
     }
 
     public function hasSpan()
@@ -229,7 +224,6 @@
     }
 
     /**
-     * <pre>
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
      * attached to the declaration.
@@ -266,9 +260,9 @@
      *    * grault. *&#47;
      *   optional int32 grault = 6;
      *   // ignored detached comments.
-     * </pre>
      *
-     * <code>optional string leading_comments = 3;</code>
+     * Generated from protobuf field <code>optional string leading_comments = 3;</code>
+     * @return string
      */
     public function getLeadingComments()
     {
@@ -276,7 +270,6 @@
     }
 
     /**
-     * <pre>
      * If this SourceCodeInfo represents a complete declaration, these are any
      * comments appearing before and after the declaration which appear to be
      * attached to the declaration.
@@ -313,15 +306,18 @@
      *    * grault. *&#47;
      *   optional int32 grault = 6;
      *   // ignored detached comments.
-     * </pre>
      *
-     * <code>optional string leading_comments = 3;</code>
+     * Generated from protobuf field <code>optional string leading_comments = 3;</code>
+     * @param string $var
+     * @return $this
      */
     public function setLeadingComments($var)
     {
         GPBUtil::checkString($var, True);
         $this->leading_comments = $var;
         $this->has_leading_comments = true;
+
+        return $this;
     }
 
     public function hasLeadingComments()
@@ -330,7 +326,8 @@
     }
 
     /**
-     * <code>optional string trailing_comments = 4;</code>
+     * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
+     * @return string
      */
     public function getTrailingComments()
     {
@@ -338,13 +335,17 @@
     }
 
     /**
-     * <code>optional string trailing_comments = 4;</code>
+     * Generated from protobuf field <code>optional string trailing_comments = 4;</code>
+     * @param string $var
+     * @return $this
      */
     public function setTrailingComments($var)
     {
         GPBUtil::checkString($var, True);
         $this->trailing_comments = $var;
         $this->has_trailing_comments = true;
+
+        return $this;
     }
 
     public function hasTrailingComments()
@@ -353,7 +354,8 @@
     }
 
     /**
-     * <code>repeated string leading_detached_comments = 6;</code>
+     * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getLeadingDetachedComments()
     {
@@ -361,13 +363,17 @@
     }
 
     /**
-     * <code>repeated string leading_detached_comments = 6;</code>
+     * Generated from protobuf field <code>repeated string leading_detached_comments = 6;</code>
+     * @param string[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setLeadingDetachedComments(&$var)
+    public function setLeadingDetachedComments($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
         $this->leading_detached_comments = $arr;
         $this->has_leading_detached_comments = true;
+
+        return $this;
     }
 
     public function hasLeadingDetachedComments()
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption.php b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
index 2865501..4d342eb 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption.php
@@ -8,60 +8,55 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * A message representing a option the parser does not recognize. This only
  * appears in options protos created by the compiler::Parser class.
  * DescriptorPool resolves these when building Descriptor objects. Therefore,
  * options protos in descriptor objects (e.g. returned by Descriptor::options(),
  * or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
  * in them.
- * </pre>
  *
- * Protobuf type <code>google.protobuf.UninterpretedOption</code>
+ * Generated from protobuf message <code>google.protobuf.UninterpretedOption</code>
  */
 class UninterpretedOption extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
      */
     private $name;
     private $has_name = false;
     /**
-     * <pre>
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
-     * </pre>
      *
-     * <code>optional string identifier_value = 3;</code>
+     * Generated from protobuf field <code>optional string identifier_value = 3;</code>
      */
     private $identifier_value = '';
     private $has_identifier_value = false;
     /**
-     * <code>optional uint64 positive_int_value = 4;</code>
+     * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
      */
     private $positive_int_value = 0;
     private $has_positive_int_value = false;
     /**
-     * <code>optional int64 negative_int_value = 5;</code>
+     * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
      */
     private $negative_int_value = 0;
     private $has_negative_int_value = false;
     /**
-     * <code>optional double double_value = 6;</code>
+     * Generated from protobuf field <code>optional double double_value = 6;</code>
      */
     private $double_value = 0.0;
     private $has_double_value = false;
     /**
-     * <code>optional bytes string_value = 7;</code>
+     * Generated from protobuf field <code>optional bytes string_value = 7;</code>
      */
     private $string_value = '';
     private $has_string_value = false;
     /**
-     * <code>optional string aggregate_value = 8;</code>
+     * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
      */
     private $aggregate_value = '';
     private $has_aggregate_value = false;
@@ -72,7 +67,8 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
      */
     public function getName()
     {
@@ -80,13 +76,17 @@
     }
 
     /**
-     * <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
+     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
+     * @param \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
      */
-    public function setName(&$var)
+    public function setName($var)
     {
         $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class);
         $this->name = $arr;
         $this->has_name = true;
+
+        return $this;
     }
 
     public function hasName()
@@ -95,12 +95,11 @@
     }
 
     /**
-     * <pre>
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
-     * </pre>
      *
-     * <code>optional string identifier_value = 3;</code>
+     * Generated from protobuf field <code>optional string identifier_value = 3;</code>
+     * @return string
      */
     public function getIdentifierValue()
     {
@@ -108,18 +107,20 @@
     }
 
     /**
-     * <pre>
      * The value of the uninterpreted option, in whatever type the tokenizer
      * identified it as during parsing. Exactly one of these should be set.
-     * </pre>
      *
-     * <code>optional string identifier_value = 3;</code>
+     * Generated from protobuf field <code>optional string identifier_value = 3;</code>
+     * @param string $var
+     * @return $this
      */
     public function setIdentifierValue($var)
     {
         GPBUtil::checkString($var, True);
         $this->identifier_value = $var;
         $this->has_identifier_value = true;
+
+        return $this;
     }
 
     public function hasIdentifierValue()
@@ -128,7 +129,8 @@
     }
 
     /**
-     * <code>optional uint64 positive_int_value = 4;</code>
+     * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
+     * @return int|string
      */
     public function getPositiveIntValue()
     {
@@ -136,13 +138,17 @@
     }
 
     /**
-     * <code>optional uint64 positive_int_value = 4;</code>
+     * Generated from protobuf field <code>optional uint64 positive_int_value = 4;</code>
+     * @param int|string $var
+     * @return $this
      */
     public function setPositiveIntValue($var)
     {
         GPBUtil::checkUint64($var);
         $this->positive_int_value = $var;
         $this->has_positive_int_value = true;
+
+        return $this;
     }
 
     public function hasPositiveIntValue()
@@ -151,7 +157,8 @@
     }
 
     /**
-     * <code>optional int64 negative_int_value = 5;</code>
+     * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
+     * @return int|string
      */
     public function getNegativeIntValue()
     {
@@ -159,13 +166,17 @@
     }
 
     /**
-     * <code>optional int64 negative_int_value = 5;</code>
+     * Generated from protobuf field <code>optional int64 negative_int_value = 5;</code>
+     * @param int|string $var
+     * @return $this
      */
     public function setNegativeIntValue($var)
     {
         GPBUtil::checkInt64($var);
         $this->negative_int_value = $var;
         $this->has_negative_int_value = true;
+
+        return $this;
     }
 
     public function hasNegativeIntValue()
@@ -174,7 +185,8 @@
     }
 
     /**
-     * <code>optional double double_value = 6;</code>
+     * Generated from protobuf field <code>optional double double_value = 6;</code>
+     * @return float
      */
     public function getDoubleValue()
     {
@@ -182,13 +194,17 @@
     }
 
     /**
-     * <code>optional double double_value = 6;</code>
+     * Generated from protobuf field <code>optional double double_value = 6;</code>
+     * @param float $var
+     * @return $this
      */
     public function setDoubleValue($var)
     {
         GPBUtil::checkDouble($var);
         $this->double_value = $var;
         $this->has_double_value = true;
+
+        return $this;
     }
 
     public function hasDoubleValue()
@@ -197,7 +213,8 @@
     }
 
     /**
-     * <code>optional bytes string_value = 7;</code>
+     * Generated from protobuf field <code>optional bytes string_value = 7;</code>
+     * @return string
      */
     public function getStringValue()
     {
@@ -205,13 +222,17 @@
     }
 
     /**
-     * <code>optional bytes string_value = 7;</code>
+     * Generated from protobuf field <code>optional bytes string_value = 7;</code>
+     * @param string $var
+     * @return $this
      */
     public function setStringValue($var)
     {
         GPBUtil::checkString($var, False);
         $this->string_value = $var;
         $this->has_string_value = true;
+
+        return $this;
     }
 
     public function hasStringValue()
@@ -220,7 +241,8 @@
     }
 
     /**
-     * <code>optional string aggregate_value = 8;</code>
+     * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
+     * @return string
      */
     public function getAggregateValue()
     {
@@ -228,13 +250,17 @@
     }
 
     /**
-     * <code>optional string aggregate_value = 8;</code>
+     * Generated from protobuf field <code>optional string aggregate_value = 8;</code>
+     * @param string $var
+     * @return $this
      */
     public function setAggregateValue($var)
     {
         GPBUtil::checkString($var, True);
         $this->aggregate_value = $var;
         $this->has_aggregate_value = true;
+
+        return $this;
     }
 
     public function hasAggregateValue()
diff --git a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php b/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
index 86484d2..c9a6fc3 100644
--- a/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
+++ b/php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php
@@ -8,29 +8,26 @@
 use Google\Protobuf\Internal\GPBWire;
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\InputStream;
-
 use Google\Protobuf\Internal\GPBUtil;
 
 /**
- * <pre>
  * The name of the uninterpreted option.  Each string represents a segment in
  * a dot-separated name.  is_extension is true iff a segment represents an
  * extension (denoted with parentheses in options specs in .proto files).
  * E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
  * "foo.(bar.baz).qux".
- * </pre>
  *
- * Protobuf type <code>google.protobuf.UninterpretedOption.NamePart</code>
+ * Generated from protobuf message <code>google.protobuf.UninterpretedOption.NamePart</code>
  */
 class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message
 {
     /**
-     * <code>required string name_part = 1;</code>
+     * Generated from protobuf field <code>required string name_part = 1;</code>
      */
     private $name_part = '';
     private $has_name_part = false;
     /**
-     * <code>required bool is_extension = 2;</code>
+     * Generated from protobuf field <code>required bool is_extension = 2;</code>
      */
     private $is_extension = false;
     private $has_is_extension = false;
@@ -41,7 +38,8 @@
     }
 
     /**
-     * <code>required string name_part = 1;</code>
+     * Generated from protobuf field <code>required string name_part = 1;</code>
+     * @return string
      */
     public function getNamePart()
     {
@@ -49,13 +47,17 @@
     }
 
     /**
-     * <code>required string name_part = 1;</code>
+     * Generated from protobuf field <code>required string name_part = 1;</code>
+     * @param string $var
+     * @return $this
      */
     public function setNamePart($var)
     {
         GPBUtil::checkString($var, True);
         $this->name_part = $var;
         $this->has_name_part = true;
+
+        return $this;
     }
 
     public function hasNamePart()
@@ -64,7 +66,8 @@
     }
 
     /**
-     * <code>required bool is_extension = 2;</code>
+     * Generated from protobuf field <code>required bool is_extension = 2;</code>
+     * @return bool
      */
     public function getIsExtension()
     {
@@ -72,13 +75,17 @@
     }
 
     /**
-     * <code>required bool is_extension = 2;</code>
+     * Generated from protobuf field <code>required bool is_extension = 2;</code>
+     * @param bool $var
+     * @return $this
      */
     public function setIsExtension($var)
     {
         GPBUtil::checkBool($var);
         $this->is_extension = $var;
         $this->has_is_extension = true;
+
+        return $this;
     }
 
     public function hasIsExtension()
diff --git a/php/src/Google/Protobuf/OneofDescriptor.php b/php/src/Google/Protobuf/OneofDescriptor.php
new file mode 100644
index 0000000..d973663
--- /dev/null
+++ b/php/src/Google/Protobuf/OneofDescriptor.php
@@ -0,0 +1,75 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 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.
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GetPublicDescriptorTrait;
+
+class OneofDescriptor
+{
+    use GetPublicDescriptorTrait;
+
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string The name of the oneof
+     */
+    public function getName()
+    {
+        return $this->internal_desc->getName();
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getFieldCount()
+     * @return FieldDescriptor
+     */
+    public function getField($index)
+    {
+        return $this->getPublicDescriptor($this->internal_desc->getFields()[$index]);
+    }
+
+    /**
+     * @return int Number of fields in the oneof
+     */
+    public function getFieldCount()
+    {
+        return count($this->internal_desc->getFields());
+    }
+}
diff --git a/php/src/Google/Protobuf/Timestamp.php b/php/src/Google/Protobuf/Timestamp.php
new file mode 100644
index 0000000..d139da9
--- /dev/null
+++ b/php/src/Google/Protobuf/Timestamp.php
@@ -0,0 +1,184 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/timestamp.proto
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * A Timestamp represents a point in time independent of any time zone
+ * or calendar, represented as seconds and fractions of seconds at
+ * nanosecond resolution in UTC Epoch time. It is encoded using the
+ * Proleptic Gregorian Calendar which extends the Gregorian calendar
+ * backwards to year one. It is encoded assuming all minutes are 60
+ * seconds long, i.e. leap seconds are "smeared" so that no leap second
+ * table is needed for interpretation. Range is from
+ * 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+ * By restricting to that range, we ensure that we can convert to
+ * and from  RFC 3339 date strings.
+ * See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+ * # Examples
+ * Example 1: Compute Timestamp from POSIX `time()`.
+ *     Timestamp timestamp;
+ *     timestamp.set_seconds(time(NULL));
+ *     timestamp.set_nanos(0);
+ * Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+ *     struct timeval tv;
+ *     gettimeofday(&tv, NULL);
+ *     Timestamp timestamp;
+ *     timestamp.set_seconds(tv.tv_sec);
+ *     timestamp.set_nanos(tv.tv_usec * 1000);
+ * Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+ *     FILETIME ft;
+ *     GetSystemTimeAsFileTime(&ft);
+ *     UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+ *     // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+ *     // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+ *     Timestamp timestamp;
+ *     timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+ *     timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+ * Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+ *     long millis = System.currentTimeMillis();
+ *     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+ *         .setNanos((int) ((millis % 1000) * 1000000)).build();
+ * Example 5: Compute Timestamp from current time in Python.
+ *     timestamp = Timestamp()
+ *     timestamp.GetCurrentTime()
+ * # JSON Mapping
+ * In JSON format, the Timestamp type is encoded as a string in the
+ * [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+ * format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+ * where {year} is always expressed using four digits while {month}, {day},
+ * {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+ * seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+ * are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+ * is required, though only UTC (as indicated by "Z") is presently supported.
+ * For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+ * 01:30 UTC on January 15, 2017.
+ * In JavaScript, one can convert a Date object to this format using the
+ * standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+ * method. In Python, a standard `datetime.datetime` object can be converted
+ * to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
+ * with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
+ * can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+ * http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime())
+ * to obtain a formatter capable of generating timestamps in this format.
+ *
+ * Generated from protobuf message <code>google.protobuf.Timestamp</code>
+ */
+class Timestamp extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Represents seconds of UTC time since Unix epoch
+     * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+     * 9999-12-31T23:59:59Z inclusive.
+     *
+     * Generated from protobuf field <code>int64 seconds = 1;</code>
+     */
+    private $seconds = 0;
+    /**
+     * Non-negative fractions of a second at nanosecond resolution. Negative
+     * second values with fractions must still have non-negative nanos values
+     * that count forward in time. Must be from 0 to 999,999,999
+     * inclusive.
+     *
+     * Generated from protobuf field <code>int32 nanos = 2;</code>
+     */
+    private $nanos = 0;
+
+    public function __construct() {
+        \GPBMetadata\Google\Protobuf\Timestamp::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Represents seconds of UTC time since Unix epoch
+     * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+     * 9999-12-31T23:59:59Z inclusive.
+     *
+     * Generated from protobuf field <code>int64 seconds = 1;</code>
+     * @return int|string
+     */
+    public function getSeconds()
+    {
+        return $this->seconds;
+    }
+
+    /**
+     * Represents seconds of UTC time since Unix epoch
+     * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+     * 9999-12-31T23:59:59Z inclusive.
+     *
+     * Generated from protobuf field <code>int64 seconds = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setSeconds($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->seconds = $var;
+
+        return $this;
+    }
+
+    /**
+     * Non-negative fractions of a second at nanosecond resolution. Negative
+     * second values with fractions must still have non-negative nanos values
+     * that count forward in time. Must be from 0 to 999,999,999
+     * inclusive.
+     *
+     * Generated from protobuf field <code>int32 nanos = 2;</code>
+     * @return int
+     */
+    public function getNanos()
+    {
+        return $this->nanos;
+    }
+
+    /**
+     * Non-negative fractions of a second at nanosecond resolution. Negative
+     * second values with fractions must still have non-negative nanos values
+     * that count forward in time. Must be from 0 to 999,999,999
+     * inclusive.
+     *
+     * Generated from protobuf field <code>int32 nanos = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setNanos($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->nanos = $var;
+
+        return $this;
+    }
+
+    /**
+     * Converts PHP DateTime to Timestamp.
+     *
+     * @param DateTime $datetime
+     */
+    public function fromDateTime($datetime)
+    {
+        if (get_class($datetime) !== \DateTime::class) {
+            trigger_error("Given parameter is not a DateTime.",
+                          E_USER_ERROR);
+        }
+        $this->seconds = $datetime->format('U');
+        $this->nanos = 0;
+    }
+
+    /**
+     * Converts Timestamp to PHP DateTime. Nano second is ignored.
+     *
+     * @return DateTime $datetime
+     */
+    public function toDateTime()
+    {
+        return \DateTime::createFromFormat('U', $this->seconds);
+    }
+}
+
diff --git a/php/src/Google/Protobuf/descriptor.php b/php/src/Google/Protobuf/descriptor.php
deleted file mode 100644
index 35e4929..0000000
--- a/php/src/Google/Protobuf/descriptor.php
+++ /dev/null
@@ -1,587 +0,0 @@
-<?php
-
-// 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.
-
-namespace Google\Protobuf\Internal;
-
-use Google\Protobuf\Internal\GPBType;
-use Google\Protobuf\Internal\MessageOptions;
-
-class FileDescriptor
-{
-
-    private $package;
-    private $message_type = [];
-    private $enum_type = [];
-
-    public function setPackage($package)
-    {
-        $this->package = $package;
-    }
-
-    public function getPackage()
-    {
-        return $this->package;
-    }
-
-    public function getMessageType()
-    {
-        return $this->message_type;
-    }
-
-    public function addMessageType($desc)
-    {
-        $this->message_type[] = $desc;
-    }
-
-    public function getEnumType()
-    {
-        return $this->enum_type;
-    }
-
-    public function addEnumType($desc)
-    {
-        $this->enum_type[]= $desc;
-    }
-
-    public static function buildFromProto($proto)
-    {
-        $file = new FileDescriptor();
-        $file->setPackage($proto->getPackage());
-        foreach ($proto->getMessageType() as $message_proto) {
-            $file->addMessageType(Descriptor::buildFromProto(
-                $message_proto, $proto, ""));
-        }
-        foreach ($proto->getEnumType() as $enum_proto) {
-            $file->getEnumType()[] =
-                $file->addEnumType(
-                    EnumDescriptor::buildFromProto(
-                        $enum_proto,
-                        $proto,
-                        ""));
-        }
-        return $file;
-    }
-}
-
-class Descriptor
-{
-
-    private $full_name;
-    private $field = [];
-    private $nested_type = [];
-    private $enum_type = [];
-    private $klass;
-    private $options;
-    private $oneof_decl = [];
-
-    public function addOneofDecl($oneof)
-    {
-        $this->oneof_decl[] = $oneof;
-    }
-
-    public function getOneofDecl()
-    {
-        return $this->oneof_decl;
-    }
-
-    public function setFullName($full_name)
-    {
-        $this->full_name = $full_name;
-    }
-
-    public function getFullName()
-    {
-        return $this->full_name;
-    }
-
-    public function addField($field)
-    {
-        $this->field[$field->getNumber()] = $field;
-    }
-
-    public function getField()
-    {
-        return $this->field;
-    }
-
-    public function addNestedType($desc)
-    {
-        $this->nested_type[] = $desc;
-    }
-
-    public function getNestedType()
-    {
-        return $this->nested_type;
-    }
-
-    public function addEnumType($desc)
-    {
-        $this->enum_type[] = $desc;
-    }
-
-    public function getEnumType()
-    {
-        return $this->enum_type;
-    }
-
-    public function getFieldByNumber($number)
-    {
-      if (!isset($this->field[$number])) {
-        return NULL;
-      } else {
-        return $this->field[$number];
-      }
-    }
-
-    public function setClass($klass)
-    {
-        $this->klass = $klass;
-    }
-
-    public function getClass()
-    {
-        return $this->klass;
-    }
-
-    public function setOptions($options)
-    {
-        $this->options = $options;
-    }
-
-    public function getOptions()
-    {
-        return $this->options;
-    }
-
-    public static function buildFromProto($proto, $file_proto, $containing)
-    {
-        $desc = new Descriptor();
-
-        $message_name_without_package  = "";
-        $classname = "";
-        $fullname = "";
-        getFullClassName(
-            $proto,
-            $containing,
-            $file_proto,
-            $message_name_without_package,
-            $classname,
-            $fullname);
-        $desc->setFullName($fullname);
-        $desc->setClass($classname);
-        $desc->setOptions($proto->getOptions());
-
-        foreach ($proto->getField() as $field_proto) {
-            $desc->addField(FieldDescriptor::buildFromProto($field_proto));
-        }
-
-        // Handle nested types.
-        foreach ($proto->getNestedType() as $nested_proto) {
-            $desc->addNestedType(Descriptor::buildFromProto(
-              $nested_proto, $file_proto, $message_name_without_package));
-        }
-
-        // Handle nested enum.
-        foreach ($proto->getEnumType() as $enum_proto) {
-            $desc->addEnumType(EnumDescriptor::buildFromProto(
-              $enum_proto, $file_proto, $message_name_without_package));
-        }
-
-        // Handle oneof fields.
-        foreach ($proto->getOneofDecl() as $oneof_proto) {
-            $desc->addOneofDecl(
-                OneofDescriptor::buildFromProto($oneof_proto, $desc));
-        }
-
-        return $desc;
-    }
-}
-
-function getClassNamePrefix(
-    $classname,
-    $file_proto)
-{
-    $option = $file_proto->getOptions();
-    $prefix = is_null($option) ? "" : $option->getPhpClassPrefix();
-    if ($prefix !== "") {
-        return $prefix;
-    }
-
-    $reserved_words = array("Empty", "ECHO", "ARRAY");
-    foreach ($reserved_words as $reserved_word) {
-        if ($classname === $reserved_word) {
-            if ($file_proto->getPackage() === "google.protobuf") {
-                return "GPB";
-            } else {
-                return "PB";
-            }
-        }
-    }
-
-    return "";
-}
-
-function getClassNameWithoutPackage(
-    $name,
-    $file_proto)
-{
-    $classname = implode('_', array_map('ucwords', explode('.', $name)));
-    return getClassNamePrefix($classname, $file_proto) . $classname;
-}
-
-function getFullClassName(
-    $proto,
-    $containing,
-    $file_proto,
-    &$message_name_without_package,
-    &$classname,
-    &$fullname)
-{
-    // Full name needs to start with '.'.
-    $message_name_without_package = $proto->getName();
-    if ($containing !== "") {
-        $message_name_without_package =
-            $containing . "." . $message_name_without_package;
-    }
-
-    $package = $file_proto->getPackage();
-    if ($package === "") {
-        $fullname = "." . $message_name_without_package;
-    } else {
-        $fullname = "." . $package . "." . $message_name_without_package;
-    }
-
-    $class_name_without_package =
-        getClassNameWithoutPackage($message_name_without_package, $file_proto);
-    if ($package === "") {
-        $classname = $class_name_without_package;
-    } else {
-        $classname =
-            implode('\\', array_map('ucwords', explode('.', $package))).
-            "\\".$class_name_without_package;
-    }
-}
-
-class OneofDescriptor
-{
-
-    private $name;
-    private $fields;
-
-    public function setName($name)
-    {
-        $this->name = $name;
-    }
-
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    public function addField(&$field)
-    {
-        $this->fields[] = $field;
-    }
-
-    public function getFields()
-    {
-        return $this->fields;
-    }
-
-    public static function buildFromProto($oneof_proto)
-    {
-        $oneof = new OneofDescriptor();
-        $oneof->setName($oneof_proto->getName());
-        return $oneof;
-    }
-}
-
-
-class EnumDescriptor
-{
-
-    private $klass;
-    private $full_name;
-    private $value;
-
-    public function setFullName($full_name)
-    {
-        $this->full_name = $full_name;
-    }
-
-    public function getFullName()
-    {
-        return $this->full_name;
-    }
-
-    public function addValue($number, $value)
-    {
-        $this->value[$number] = $value;
-    }
-
-    public function setClass($klass)
-    {
-        $this->klass = $klass;
-    }
-
-    public function getClass()
-    {
-        return $this->klass;
-    }
-
-    public static function buildFromProto($proto, $file_proto, $containing)
-    {
-        $desc = new EnumDescriptor();
-
-        $enum_name_without_package  = "";
-        $classname = "";
-        $fullname = "";
-        getFullClassName(
-            $proto,
-            $containing,
-            $file_proto,
-            $enum_name_without_package,
-            $classname,
-            $fullname);
-        $desc->setFullName($fullname);
-        $desc->setClass($classname);
-
-        return $desc;
-    }
-}
-
-class EnumValueDescriptor
-{
-}
-
-class FieldDescriptor
-{
-
-    private $name;
-    private $setter;
-    private $getter;
-    private $number;
-    private $label;
-    private $type;
-    private $message_type;
-    private $enum_type;
-    private $packed;
-    private $is_map;
-    private $oneof_index = -1;
-
-    public function setOneofIndex($index)
-    {
-        $this->oneof_index = $index;
-    }
-
-    public function getOneofIndex()
-    {
-        return $this->oneof_index;
-    }
-
-    public function setName($name)
-    {
-        $this->name = $name;
-    }
-
-    public function getName()
-    {
-        return $this->name;
-    }
-
-    public function setSetter($setter)
-    {
-        $this->setter = $setter;
-    }
-
-    public function getSetter()
-    {
-        return $this->setter;
-    }
-
-    public function setGetter($getter)
-    {
-        $this->getter = $getter;
-    }
-
-    public function getGetter()
-    {
-        return $this->getter;
-    }
-
-    public function setNumber($number)
-    {
-        $this->number = $number;
-    }
-
-    public function getNumber()
-    {
-        return $this->number;
-    }
-
-    public function setLabel($label)
-    {
-        $this->label = $label;
-    }
-
-    public function getLabel()
-    {
-        return $this->label;
-    }
-
-    public function isRepeated()
-    {
-        return $this->label === GPBLabel::REPEATED;
-    }
-
-    public function setType($type)
-    {
-        $this->type = $type;
-    }
-
-    public function getType()
-    {
-        return $this->type;
-    }
-
-    public function setMessageType($message_type)
-    {
-        $this->message_type = $message_type;
-    }
-
-    public function getMessageType()
-    {
-        return $this->message_type;
-    }
-
-    public function setEnumType($enum_type)
-    {
-        $this->enum_type = $enum_type;
-    }
-
-    public function getEnumType()
-    {
-        return $this->enum_type;
-    }
-
-    public function setPacked($packed)
-    {
-        $this->packed = $packed;
-    }
-
-    public function getPacked()
-    {
-        return $this->packed;
-    }
-
-    public function isPackable()
-    {
-        return $this->isRepeated() && self::isTypePackable($this->type);
-    }
-
-    public function isMap()
-    {
-        return $this->getType() == GPBType::MESSAGE &&
-               !is_null($this->getMessageType()->getOptions()) &&
-               $this->getMessageType()->getOptions()->getMapEntry();
-    }
-
-    private static function isTypePackable($field_type)
-    {
-        return ($field_type !== GPBType::STRING  &&
-            $field_type !== GPBType::GROUP   &&
-            $field_type !== GPBType::MESSAGE &&
-            $field_type !== GPBType::BYTES);
-    }
-
-    public static function getFieldDescriptor(
-        $name,
-        $label,
-        $type,
-        $number,
-        $oneof_index,
-        $packed,
-        $type_name = null)
-    {
-        $field = new FieldDescriptor();
-        $field->setName($name);
-        $camel_name = implode('', array_map('ucwords', explode('_', $name)));
-        $field->setGetter('get' . $camel_name);
-        $field->setSetter('set' . $camel_name);
-        $field->setType($type);
-        $field->setNumber($number);
-        $field->setLabel($label);
-        $field->setPacked($packed);
-        $field->setOneofIndex($oneof_index);
-
-        // At this time, the message/enum type may have not been added to pool.
-        // So we use the type name as place holder and will replace it with the
-        // actual descriptor in cross building.
-        switch ($type) {
-            case GPBType::MESSAGE:
-                $field->setMessageType($type_name);
-                break;
-            case GPBType::ENUM:
-                $field->setEnumType($type_name);
-                break;
-            default:
-                break;
-        }
-
-        return $field;
-    }
-
-    public static function buildFromProto($proto)
-    {
-        $type_name = null;
-        switch ($proto->getType()) {
-            case GPBType::MESSAGE:
-            case GPBType::GROUP:
-            case GPBType::ENUM:
-                $type_name = $proto->getTypeName();
-                break;
-            default:
-                break;
-        }
-
-        $oneof_index = $proto->hasOneofIndex() ? $proto->getOneofIndex() : -1;
-        $packed = false;
-        $options = $proto->getOptions();
-        if ($options !== null) {
-            $packed = $options->getPacked();
-        }
-
-        return FieldDescriptor::getFieldDescriptor(
-            $proto->getName(), $proto->getLabel(), $proto->getType(),
-            $proto->getNumber(), $oneof_index, $packed, $type_name);
-    }
-}
diff --git a/php/tests/array_test.php b/php/tests/array_test.php
index b55408d..1a26d72 100644
--- a/php/tests/array_test.php
+++ b/php/tests/array_test.php
@@ -19,23 +19,23 @@
         $arr = new RepeatedField(GPBType::INT32);
 
         // Test append.
-        $arr []= MAX_INT32;
+        $arr[] = MAX_INT32;
         $this->assertSame(MAX_INT32, $arr[0]);
-        $arr []= MIN_INT32;
+        $arr[] = MIN_INT32;
         $this->assertSame(MIN_INT32, $arr[1]);
 
-        $arr []= 1.1;
+        $arr[] = 1.1;
         $this->assertSame(1, $arr[2]);
-        $arr []= MAX_INT32_FLOAT;
+        $arr[] = MAX_INT32_FLOAT;
         $this->assertSame(MAX_INT32, $arr[3]);
-        $arr []= MAX_INT32_FLOAT;
+        $arr[] = MAX_INT32_FLOAT;
         $this->assertSame(MAX_INT32, $arr[4]);
 
-        $arr []= '2';
+        $arr[] = '2';
         $this->assertSame(2, $arr[5]);
-        $arr []= '3.1';
+        $arr[] = '3.1';
         $this->assertSame(3, $arr[6]);
-        $arr []= MAX_INT32_STRING;
+        $arr[] = MAX_INT32_STRING;
         $this->assertSame(MAX_INT32, $arr[7]);
 
         $this->assertEquals(8, count($arr));
@@ -46,29 +46,29 @@
         }
 
         // Test set.
-        $arr [0]= MAX_INT32;
+        $arr[0] = MAX_INT32;
         $this->assertSame(MAX_INT32, $arr[0]);
-        $arr [1]= MIN_INT32;
+        $arr[1] = MIN_INT32;
         $this->assertSame(MIN_INT32, $arr[1]);
 
-        $arr [2]= 1.1;
+        $arr[2] = 1.1;
         $this->assertSame(1, $arr[2]);
-        $arr [3]= MAX_INT32_FLOAT;
+        $arr[3] = MAX_INT32_FLOAT;
         $this->assertSame(MAX_INT32, $arr[3]);
-        $arr [4]= MAX_INT32_FLOAT;
+        $arr[4] = MAX_INT32_FLOAT;
         $this->assertSame(MAX_INT32, $arr[4]);
 
-        $arr [5]= '2';
+        $arr[5] = '2';
         $this->assertSame(2, $arr[5]);
-        $arr [6]= '3.1';
+        $arr[6] = '3.1';
         $this->assertSame(3, $arr[6]);
-        $arr [7]= MAX_INT32_STRING;
+        $arr[7] = MAX_INT32_STRING;
         $this->assertSame(MAX_INT32, $arr[7]);
 
         // Test foreach.
         $arr = new RepeatedField(GPBType::INT32);
         for ($i = 0; $i < 3; $i++) {
-          $arr []= $i;
+          $arr[] = $i;
         }
         $i = 0;
         foreach ($arr as $val) {
@@ -77,44 +77,6 @@
         $this->assertSame(3, $i);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr []= 0;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr []= 0;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test uint32 field.
     #########################################################
@@ -124,31 +86,31 @@
         $arr = new RepeatedField(GPBType::UINT32);
 
         // Test append.
-        $arr []= MAX_UINT32;
+        $arr[] = MAX_UINT32;
         $this->assertSame(-1, $arr[0]);
-        $arr []= -1;
+        $arr[] = -1;
         $this->assertSame(-1, $arr[1]);
-        $arr []= MIN_UINT32;
+        $arr[] = MIN_UINT32;
         $this->assertSame(MIN_UINT32, $arr[2]);
 
-        $arr []= 1.1;
+        $arr[] = 1.1;
         $this->assertSame(1, $arr[3]);
-        $arr []= MAX_UINT32_FLOAT;
+        $arr[] = MAX_UINT32_FLOAT;
         $this->assertSame(-1, $arr[4]);
-        $arr []= -1.0;
+        $arr[] = -1.0;
         $this->assertSame(-1, $arr[5]);
-        $arr []= MIN_UINT32_FLOAT;
+        $arr[] = MIN_UINT32_FLOAT;
         $this->assertSame(MIN_UINT32, $arr[6]);
 
-        $arr []= '2';
+        $arr[] = '2';
         $this->assertSame(2, $arr[7]);
-        $arr []= '3.1';
+        $arr[] = '3.1';
         $this->assertSame(3, $arr[8]);
-        $arr []= MAX_UINT32_STRING;
+        $arr[] = MAX_UINT32_STRING;
         $this->assertSame(-1, $arr[9]);
-        $arr []= '-1.0';
+        $arr[] = '-1.0';
         $this->assertSame(-1, $arr[10]);
-        $arr []= MIN_UINT32_STRING;
+        $arr[] = MIN_UINT32_STRING;
         $this->assertSame(MIN_UINT32, $arr[11]);
 
         $this->assertEquals(12, count($arr));
@@ -159,72 +121,34 @@
         }
 
         // Test set.
-        $arr [0]= MAX_UINT32;
+        $arr[0] = MAX_UINT32;
         $this->assertSame(-1, $arr[0]);
-        $arr [1]= -1;
+        $arr[1] = -1;
         $this->assertSame(-1, $arr[1]);
-        $arr [2]= MIN_UINT32;
+        $arr[2] = MIN_UINT32;
         $this->assertSame(MIN_UINT32, $arr[2]);
 
-        $arr [3]= 1.1;
+        $arr[3] = 1.1;
         $this->assertSame(1, $arr[3]);
-        $arr [4]= MAX_UINT32_FLOAT;
+        $arr[4] = MAX_UINT32_FLOAT;
         $this->assertSame(-1, $arr[4]);
-        $arr [5]= -1.0;
+        $arr[5] = -1.0;
         $this->assertSame(-1, $arr[5]);
-        $arr [6]= MIN_UINT32_FLOAT;
+        $arr[6] = MIN_UINT32_FLOAT;
         $this->assertSame(MIN_UINT32, $arr[6]);
 
-        $arr [7]= '2';
+        $arr[7] = '2';
         $this->assertSame(2, $arr[7]);
-        $arr [8]= '3.1';
+        $arr[8] = '3.1';
         $this->assertSame(3, $arr[8]);
-        $arr [9]= MAX_UINT32_STRING;
+        $arr[9] = MAX_UINT32_STRING;
         $this->assertSame(-1, $arr[9]);
-        $arr [10]= '-1.0';
+        $arr[10] = '-1.0';
         $this->assertSame(-1, $arr[10]);
-        $arr [11]= MIN_UINT32_STRING;
+        $arr[11] = MIN_UINT32_STRING;
         $this->assertSame(MIN_UINT32, $arr[11]);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr []= 0;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT32);
-        $arr []= 0;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test int64 field.
     #########################################################
@@ -234,13 +158,13 @@
         $arr = new RepeatedField(GPBType::INT64);
 
         // Test append.
-        $arr []= MAX_INT64;
-        $arr []= MIN_INT64;
-        $arr []= 1.1;
-        $arr []= '2';
-        $arr []= '3.1';
-        $arr []= MAX_INT64_STRING;
-        $arr []= MIN_INT64_STRING;
+        $arr[] = MAX_INT64;
+        $arr[] = MIN_INT64;
+        $arr[] = 1.1;
+        $arr[] = '2';
+        $arr[] = '3.1';
+        $arr[] = MAX_INT64_STRING;
+        $arr[] = MIN_INT64_STRING;
         if (PHP_INT_SIZE == 4) {
             $this->assertSame(MAX_INT64, $arr[0]);
             $this->assertSame(MIN_INT64, $arr[1]);
@@ -272,13 +196,13 @@
         }
 
         // Test set.
-        $arr [0]= MAX_INT64;
-        $arr [1]= MIN_INT64;
-        $arr [2]= 1.1;
-        $arr [3]= '2';
-        $arr [4]= '3.1';
-        $arr [5]= MAX_INT64_STRING;
-        $arr [6]= MIN_INT64_STRING;
+        $arr[0] = MAX_INT64;
+        $arr[1] = MIN_INT64;
+        $arr[2] = 1.1;
+        $arr[3] = '2';
+        $arr[4] = '3.1';
+        $arr[5] = MAX_INT64_STRING;
+        $arr[6] = MIN_INT64_STRING;
 
         if (PHP_INT_SIZE == 4) {
             $this->assertSame(MAX_INT64_STRING, $arr[0]);
@@ -299,44 +223,6 @@
         }
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr []= 0;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::INT64);
-        $arr []= 0;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test uint64 field.
     #########################################################
@@ -346,11 +232,11 @@
         $arr = new RepeatedField(GPBType::UINT64);
 
         // Test append.
-        $arr []= MAX_UINT64;
-        $arr []= 1.1;
-        $arr []= '2';
-        $arr []= '3.1';
-        $arr []= MAX_UINT64_STRING;
+        $arr[] = MAX_UINT64;
+        $arr[] = 1.1;
+        $arr[] = '2';
+        $arr[] = '3.1';
+        $arr[] = MAX_UINT64_STRING;
 
         if (PHP_INT_SIZE == 4) {
             $this->assertSame(MAX_UINT64_STRING, $arr[0]);
@@ -379,11 +265,11 @@
         }
 
         // Test set.
-        $arr [0]= MAX_UINT64;
-        $arr [1]= 1.1;
-        $arr [2]= '2';
-        $arr [3]= '3.1';
-        $arr [4]= MAX_UINT64_STRING;
+        $arr[0] = MAX_UINT64;
+        $arr[1] = 1.1;
+        $arr[2] = '2';
+        $arr[3] = '3.1';
+        $arr[4] = MAX_UINT64_STRING;
 
         if (PHP_INT_SIZE == 4) {
             $this->assertSame(MAX_UINT64_STRING, $arr[0]);
@@ -400,44 +286,6 @@
         }
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64AppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr []= 0;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64AppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::UINT64);
-        $arr []= 0;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test float field.
     #########################################################
@@ -447,15 +295,15 @@
         $arr = new RepeatedField(GPBType::FLOAT);
 
         // Test append.
-        $arr []= 1;
+        $arr[] = 1;
         $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
 
-        $arr []= 1.1;
+        $arr[] = 1.1;
         $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
 
-        $arr []= '2';
+        $arr[] = '2';
         $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
-        $arr []= '3.1';
+        $arr[] = '3.1';
         $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
 
         $this->assertEquals(4, count($arr));
@@ -466,56 +314,18 @@
         }
 
         // Test set.
-        $arr [0]= 1;
+        $arr[0] = 1;
         $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
 
-        $arr [1]= 1.1;
+        $arr[1] = 1.1;
         $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
 
-        $arr [2]= '2';
+        $arr[2] = '2';
         $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
-        $arr [3]= '3.1';
+        $arr[3] = '3.1';
         $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatAppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatSetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr []= 0.0;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::FLOAT);
-        $arr []= 0.0;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test double field.
     #########################################################
@@ -525,15 +335,15 @@
         $arr = new RepeatedField(GPBType::DOUBLE);
 
         // Test append.
-        $arr []= 1;
+        $arr[] = 1;
         $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
 
-        $arr []= 1.1;
+        $arr[] = 1.1;
         $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
 
-        $arr []= '2';
+        $arr[] = '2';
         $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
-        $arr []= '3.1';
+        $arr[] = '3.1';
         $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
 
         $this->assertEquals(4, count($arr));
@@ -544,56 +354,18 @@
         }
 
         // Test set.
-        $arr [0]= 1;
+        $arr[0] = 1;
         $this->assertEquals(1.0, $arr[0], '', MAX_FLOAT_DIFF);
 
-        $arr [1]= 1.1;
+        $arr[1] = 1.1;
         $this->assertEquals(1.1, $arr[1], '', MAX_FLOAT_DIFF);
 
-        $arr [2]= '2';
+        $arr[2] = '2';
         $this->assertEquals(2.0, $arr[2], '', MAX_FLOAT_DIFF);
-        $arr [3]= '3.1';
+        $arr[3] = '3.1';
         $this->assertEquals(3.1, $arr[3], '', MAX_FLOAT_DIFF);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleAppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr []= 0.0;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr []= 0.0;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test bool field.
     #########################################################
@@ -603,16 +375,16 @@
         $arr = new RepeatedField(GPBType::BOOL);
 
         // Test append.
-        $arr []= true;
+        $arr[] = true;
         $this->assertSame(true, $arr[0]);
 
-        $arr []= -1;
+        $arr[] = -1;
         $this->assertSame(true, $arr[1]);
 
-        $arr []= 1.1;
+        $arr[] = 1.1;
         $this->assertSame(true, $arr[2]);
 
-        $arr []= '';
+        $arr[] = '';
         $this->assertSame(false, $arr[3]);
 
         $this->assertEquals(4, count($arr));
@@ -623,38 +395,19 @@
         }
 
         // Test set.
-        $arr [0]= true;
+        $arr[0] = true;
         $this->assertSame(true, $arr[0]);
 
-        $arr [1]= -1;
+        $arr[1] = -1;
         $this->assertSame(true, $arr[1]);
 
-        $arr [2]= 1.1;
+        $arr[2] = 1.1;
         $this->assertSame(true, $arr[2]);
 
-        $arr [3]= '';
+        $arr[3] = '';
         $this->assertSame(false, $arr[3]);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::BOOL);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::BOOL);
-        $arr []= true;
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test string field.
     #########################################################
@@ -664,16 +417,16 @@
         $arr = new RepeatedField(GPBType::STRING);
 
         // Test append.
-        $arr []= 'abc';
+        $arr[] = 'abc';
         $this->assertSame('abc', $arr[0]);
 
-        $arr []= 1;
+        $arr[] = 1;
         $this->assertSame('1', $arr[1]);
 
-        $arr []= 1.1;
+        $arr[] = 1.1;
         $this->assertSame('1.1', $arr[2]);
 
-        $arr []= true;
+        $arr[] = true;
         $this->assertSame('1', $arr[3]);
 
         $this->assertEquals(4, count($arr));
@@ -684,59 +437,19 @@
         }
 
         // Test set.
-        $arr [0]= 'abc';
+        $arr[0] = 'abc';
         $this->assertSame('abc', $arr[0]);
 
-        $arr [1]= 1;
+        $arr[1] = 1;
         $this->assertSame('1', $arr[1]);
 
-        $arr [2]= 1.1;
+        $arr[2] = 1.1;
         $this->assertSame('1.1', $arr[2]);
 
-        $arr [3]= true;
+        $arr[3] = true;
         $this->assertSame('1', $arr[3]);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringAppendMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $arr []= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $arr []= 'abc';
-        $arr [0]= new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringAppendInvalidUTF8Fail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $hex = hex2bin("ff");
-        $arr []= $hex;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetInvalidUTF8Fail()
-    {
-        $arr = new RepeatedField(GPBType::STRING);
-        $arr []= 'abc';
-        $hex = hex2bin("ff");
-        $arr [0]= $hex;
-    }
-
     #########################################################
     # Test message field.
     #########################################################
@@ -748,7 +461,7 @@
         // Test append.
         $sub_m = new TestMessage_Sub();
         $sub_m->setA(1);
-        $arr []= $sub_m;
+        $arr[] = $sub_m;
         $this->assertSame(1, $arr[0]->getA());
 
         $this->assertEquals(1, count($arr));
@@ -756,76 +469,20 @@
         // Test set.
         $sub_m = new TestMessage_Sub();
         $sub_m->setA(2);
-        $arr [0]= $sub_m;
+        $arr[0] = $sub_m;
         $this->assertSame(2, $arr[0]->getA());
-    }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendIntFail()
-    {
+        // Test foreach.
         $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr []= 1;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetIntFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr []= new TestMessage_Sub;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendStringFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr []= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetStringFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr []= new TestMessage_Sub;
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendOtherMessageFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr []= new TestMessage;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageAppendNullFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $null = null;
-        $arr []= $null;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetNullFail()
-    {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr []= new TestMessage_Sub();
-        $null = null;
-        $arr[0] = $null;
+        for ($i = 0; $i < 3; $i++) {
+          $arr[] = new TestMessage_Sub();
+          $arr[$i]->setA($i);
+        }
+        $i = 0;
+        foreach ($arr as $val) {
+          $this->assertSame($i++, $val->getA());
+        }
+        $this->assertSame(3, $i);
     }
 
     #########################################################
@@ -835,18 +492,18 @@
     public function testOffset()
     {
         $arr = new RepeatedField(GPBType::INT32);
-        $arr []= 0;
+        $arr[] = 0;
 
-        $arr [0]= 1;
+        $arr[0] = 1;
         $this->assertSame(1, $arr[0]);
         $this->assertSame(1, count($arr));
 
-        $arr ['0']= 2;
+        $arr['0'] = 2;
         $this->assertSame(2, $arr['0']);
         $this->assertSame(2, $arr[0]);
         $this->assertSame(1, count($arr));
 
-        $arr [0.0]= 3;
+        $arr[0.0] = 3;
         $this->assertSame(3, $arr[0.0]);
         $this->assertSame(1, count($arr));
     }
@@ -855,9 +512,9 @@
     {
         $arr = new RepeatedField(GPBType::INT32);
 
-        $arr []= 0;
-        $arr []= 1;
-        $arr []= 2;
+        $arr[] = 0;
+        $arr[] = 1;
+        $arr[] = 2;
         $this->assertSame(3, count($arr));
 
         unset($arr[2]);
@@ -865,75 +522,22 @@
         $this->assertSame(0, $arr[0]);
         $this->assertSame(1, $arr[1]);
 
-        $arr [] = 3;
+        $arr[] = 3;
         $this->assertSame(3, count($arr));
         $this->assertSame(0, $arr[0]);
         $this->assertSame(1, $arr[1]);
         $this->assertSame(3, $arr[2]);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRemoveMiddleFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-
-        $arr []= 0;
-        $arr []= 1;
-        $arr []= 2;
-        $this->assertSame(3, count($arr));
-
-        unset($arr[1]);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRemoveEmptyFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-
-        unset($arr[0]);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageOffsetFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr []= 0;
-        $arr [new TestMessage_Sub()]= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringOffsetFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr []= 0;
-        $arr ['abc']= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testSetNonExistedOffsetFail()
-    {
-        $arr = new RepeatedField(GPBType::INT32);
-        $arr [0]= 0;
-    }
-
     #########################################################
     # Test memory leak
     #########################################################
 
     public function testCycleLeak()
     {
+        gc_collect_cycles();
         $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
-        $arr []= new TestMessage;
+        $arr[] = new TestMessage;
         $arr[0]->SetRepeatedRecursive($arr);
 
         // Clean up memory before test.
diff --git a/php/tests/compatibility_test.sh b/php/tests/compatibility_test.sh
index e05b2af..6f1e4900 100755
--- a/php/tests/compatibility_test.sh
+++ b/php/tests/compatibility_test.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-use_php() {
+function use_php() {
   VERSION=$1
   PHP=`which php`
   PHP_CONFIG=`which php-config`
@@ -10,7 +10,7 @@
   ln -sfn "/usr/local/php-${VERSION}/bin/phpize" $PHPIZE
 }
 
-generate_proto() {
+function generate_proto() {
   PROTOC1=$1
   PROTOC2=$2
 
@@ -25,6 +25,27 @@
   popd
 }
 
+# Remove tests to expect error. These were added to API tests by mistake.
+function remove_error_test() {
+  local TEMPFILE=`tempfile`
+  cat $1 | \
+  awk -v file=`basename $1` -v dir=`basename $(dirname $1)` '
+    BEGIN {
+      show = 1
+    }
+    /@expectedException PHPUnit_Framework_Error/ { show = 0; next; }
+    / *\*\//                                     { print; next; }
+    / *}/ {
+      if (!show) {
+        show = 1;
+        next;
+      }
+    }
+    show { print }
+  ' > $TEMPFILE
+  cp $TEMPFILE $1
+}
+
 set -ex
 
 # Change to the script's directory.
@@ -81,6 +102,15 @@
 cd protobuf/php
 cp -r /usr/local/vendor-5.5 vendor
 wget https://phar.phpunit.de/phpunit-4.8.0.phar -O /usr/bin/phpunit
+
+# Remove implementation detail tests.
+tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
+sed -i.bak '/php_implementation_test.php/d' phpunit.xml
+for t in "${tests[@]}"
+do
+  remove_error_test tests/$t
+done
+
 cd tests
 
 # Test A.1:
diff --git a/php/tests/descriptors_test.php b/php/tests/descriptors_test.php
new file mode 100644
index 0000000..17e8a4f
--- /dev/null
+++ b/php/tests/descriptors_test.php
@@ -0,0 +1,246 @@
+<?php
+
+require_once('generated/Descriptors/TestDescriptorsEnum.php');
+require_once('generated/Descriptors/TestDescriptorsMessage.php');
+require_once('test_base.php');
+require_once('test_util.php');
+
+use Google\Protobuf\DescriptorPool;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\MapField;
+use Descriptors\TestDescriptorsEnum;
+use Descriptors\TestDescriptorsMessage;
+use Descriptors\TestDescriptorsMessage_Sub;
+
+class DescriptorsTest extends TestBase
+{
+
+    // Redefine these here for compatibility with c extension
+    const GPBLABEL_OPTIONAL = 1;
+    const GPBLABEL_REQUIRED = 2;
+    const GPBLABEL_REPEATED = 3;
+
+    const GPBTYPE_DOUBLE   =  1;
+    const GPBTYPE_FLOAT    =  2;
+    const GPBTYPE_INT64    =  3;
+    const GPBTYPE_UINT64   =  4;
+    const GPBTYPE_INT32    =  5;
+    const GPBTYPE_FIXED64  =  6;
+    const GPBTYPE_FIXED32  =  7;
+    const GPBTYPE_BOOL     =  8;
+    const GPBTYPE_STRING   =  9;
+    const GPBTYPE_GROUP    = 10;
+    const GPBTYPE_MESSAGE  = 11;
+    const GPBTYPE_BYTES    = 12;
+    const GPBTYPE_UINT32   = 13;
+    const GPBTYPE_ENUM     = 14;
+    const GPBTYPE_SFIXED32 = 15;
+    const GPBTYPE_SFIXED64 = 16;
+    const GPBTYPE_SINT32   = 17;
+    const GPBTYPE_SINT64   = 18;
+
+    #########################################################
+    # Test descriptor pool.
+    #########################################################
+
+    public function testDescriptorPool()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+
+        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
+        $this->assertInstanceOf('\Google\Protobuf\Descriptor', $desc);
+
+        $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum()));
+        $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $enumDesc);
+    }
+
+    public function testDescriptorPoolIncorrectArgs()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+
+        $desc = $pool->getDescriptorByClassName('NotAClass');
+        $this->assertNull($desc);
+
+        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsEnum()));
+        $this->assertNull($desc);
+
+        $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsMessage()));
+        $this->assertNull($enumDesc);
+    }
+
+    #########################################################
+    # Test descriptor.
+    #########################################################
+
+    public function testDescriptor()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $class = get_class(new TestDescriptorsMessage());
+        $this->assertSame('Descriptors\TestDescriptorsMessage', $class);
+        $desc = $pool->getDescriptorByClassName($class);
+
+        $this->assertSame('descriptors.TestDescriptorsMessage', $desc->getFullName());
+        $this->assertSame($class, $desc->getClass());
+
+        $this->assertInstanceOf('\Google\Protobuf\FieldDescriptor', $desc->getField(0));
+        $this->assertSame(7, $desc->getFieldCount());
+
+        $this->assertInstanceOf('\Google\Protobuf\OneofDescriptor', $desc->getOneofDecl(0));
+        $this->assertSame(1, $desc->getOneofDeclCount());
+    }
+
+    #########################################################
+    # Test enum descriptor.
+    #########################################################
+
+    public function testEnumDescriptor()
+    {
+        // WARNINIG - we need to do this so that TestDescriptorsEnum is registered!!?
+        new TestDescriptorsMessage();
+
+        $pool = DescriptorPool::getGeneratedPool();
+
+        $enumDesc = $pool->getEnumDescriptorByClassName(get_class(new TestDescriptorsEnum()));
+
+        // Build map of enum values
+        $enumDescMap = [];
+        for ($i = 0; $i < $enumDesc->getValueCount(); $i++) {
+            $enumValueDesc = $enumDesc->getValue($i);
+            $this->assertInstanceOf('\Google\Protobuf\EnumValueDescriptor', $enumValueDesc);
+            $enumDescMap[$enumValueDesc->getNumber()] = $enumValueDesc->getName();
+        }
+
+        $this->assertSame('ZERO', $enumDescMap[0]);
+        $this->assertSame('ONE', $enumDescMap[1]);
+
+        $this->assertSame(2, $enumDesc->getValueCount());
+    }
+
+    #########################################################
+    # Test field descriptor.
+    #########################################################
+
+    public function testFieldDescriptor()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
+
+        $fieldDescMap = $this->buildFieldMap($desc);
+
+        // Optional int field
+        $fieldDesc = $fieldDescMap[1];
+        $this->assertSame('optional_int32', $fieldDesc->getName());
+        $this->assertSame(1, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType());
+        $this->assertFalse($fieldDesc->isMap());
+
+        // Optional enum field
+        $fieldDesc = $fieldDescMap[16];
+        $this->assertSame('optional_enum', $fieldDesc->getName());
+        $this->assertSame(16, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_ENUM, $fieldDesc->getType());
+        $this->assertInstanceOf('\Google\Protobuf\EnumDescriptor', $fieldDesc->getEnumType());
+        $this->assertFalse($fieldDesc->isMap());
+
+        // Optional message field
+        $fieldDesc = $fieldDescMap[17];
+        $this->assertSame('optional_message', $fieldDesc->getName());
+        $this->assertSame(17, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType());
+        $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType());
+        $this->assertFalse($fieldDesc->isMap());
+
+        // Repeated int field
+        $fieldDesc = $fieldDescMap[31];
+        $this->assertSame('repeated_int32', $fieldDesc->getName());
+        $this->assertSame(31, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType());
+        $this->assertFalse($fieldDesc->isMap());
+
+        // Repeated message field
+        $fieldDesc = $fieldDescMap[47];
+        $this->assertSame('repeated_message', $fieldDesc->getName());
+        $this->assertSame(47, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType());
+        $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType());
+        $this->assertFalse($fieldDesc->isMap());
+
+        // Oneof int field
+        // Tested further in testOneofDescriptor()
+        $fieldDesc = $fieldDescMap[51];
+        $this->assertSame('oneof_int32', $fieldDesc->getName());
+        $this->assertSame(51, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType());
+        $this->assertFalse($fieldDesc->isMap());
+
+        // Map int-enum field
+        $fieldDesc = $fieldDescMap[71];
+        $this->assertSame('map_int32_enum', $fieldDesc->getName());
+        $this->assertSame(71, $fieldDesc->getNumber());
+        $this->assertSame(self::GPBLABEL_REPEATED, $fieldDesc->getLabel());
+        $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType());
+        $this->assertTrue($fieldDesc->isMap());
+        $mapDesc = $fieldDesc->getMessageType();
+        $this->assertSame('descriptors.TestDescriptorsMessage.MapInt32EnumEntry', $mapDesc->getFullName());
+        $this->assertSame(self::GPBTYPE_INT32, $mapDesc->getField(0)->getType());
+        $this->assertSame(self::GPBTYPE_ENUM, $mapDesc->getField(1)->getType());
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testFieldDescriptorEnumException()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
+        $fieldDesc = $desc->getField(0);
+        $fieldDesc->getEnumType();
+    }
+
+    /**
+     * @expectedException \Exception
+     */
+    public function testFieldDescriptorMessageException()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
+        $fieldDesc = $desc->getField(0);
+        $fieldDesc->getMessageType();
+    }
+
+    #########################################################
+    # Test oneof descriptor.
+    #########################################################
+
+    public function testOneofDescriptor()
+    {
+        $pool = DescriptorPool::getGeneratedPool();
+        $desc = $pool->getDescriptorByClassName(get_class(new TestDescriptorsMessage()));
+
+        $fieldDescMap = $this->buildFieldMap($desc);
+        $fieldDesc = $fieldDescMap[51];
+
+        $oneofDesc = $desc->getOneofDecl(0);
+
+        $this->assertSame('my_oneof', $oneofDesc->getName());
+        $fieldDescFromOneof = $oneofDesc->getField(0);
+        $this->assertSame($fieldDesc, $fieldDescFromOneof);
+        $this->assertSame(1, $oneofDesc->getFieldCount());
+    }
+
+    private function buildFieldMap($desc)
+    {
+        $fieldDescMap = [];
+        for ($i = 0; $i < $desc->getFieldCount(); $i++) {
+            $fieldDesc = $desc->getField($i);
+            $fieldDescMap[$fieldDesc->getNumber()] = $fieldDesc;
+        }
+        return $fieldDescMap;
+    }
+}
diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php
index b4cfed4..b43dffb 100644
--- a/php/tests/encode_decode_test.php
+++ b/php/tests/encode_decode_test.php
@@ -9,6 +9,7 @@
 use Foo\TestMessage;
 use Foo\TestMessage_Sub;
 use Foo\TestPackedMessage;
+use Foo\TestRandomFieldOrder;
 use Foo\TestUnpackedMessage;
 
 class EncodeDecodeTest extends TestBase
@@ -95,6 +96,23 @@
         $n = new TestMessage();
         $n->mergeFromString($data);
         $this->assertSame("oneof_enum", $n->getMyOneof());
+        $this->assertSame(TestEnum::ZERO, $n->getOneofEnum());
+
+        $m->setOneofString("");
+        $data = $m->serializeToString();
+        $n = new TestMessage();
+        $n->mergeFromString($data);
+        $this->assertSame("oneof_string", $n->getMyOneof());
+        $this->assertSame("", $n->getOneofString());
+
+        $sub_m = new TestMessage_Sub();
+        $m->setOneofMessage($sub_m);
+        $data = $m->serializeToString();
+        $n = new TestMessage();
+        $n->mergeFromString($data);
+        $this->assertSame("oneof_message", $n->getMyOneof());
+        $this->assertFalse(is_null($n->getOneofMessage()));
+
     }
 
     public function testPackedEncode()
@@ -218,6 +236,13 @@
         $this->assertEquals(-1, $m->getOptionalInt32());
     }
 
+    public function testRandomFieldOrder()
+    {
+        $m = new TestRandomFieldOrder();
+        $data = $m->serializeToString();
+        $this->assertSame("", $data);
+    }
+
     /**
      * @expectedException Exception
      */
@@ -416,15 +441,13 @@
         $m->mergeFromString(hex2bin('D205'));
     }
 
-    # TODO(teboring): Add test back when php implementation is ready for json
-    # encode/decode.
-    # public function testJsonEncode()
-    # {
-    #     $from = new TestMessage();
-    #     $this->setFields($from);
-    #     $data = $from->jsonEncode();
-    #     $to = new TestMessage();
-    #     $to->jsonDecode($data);
-    #     $this->expectFields($to);
-    # }
+    public function testJsonEncode()
+    {
+        $from = new TestMessage();
+        $this->setFields($from);
+        $data = $from->serializeToJsonString();
+        $to = new TestMessage();
+        $to->mergeFromJsonString($data);
+        $this->expectFields($to);
+    }
 }
diff --git a/php/tests/generated_class_test.php b/php/tests/generated_class_test.php
index be641b6..98918bc 100644
--- a/php/tests/generated_class_test.php
+++ b/php/tests/generated_class_test.php
@@ -9,9 +9,14 @@
 use Google\Protobuf\Internal\MapField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestEnum;
+use Foo\TestIncludeNamespaceMessage;
 use Foo\TestIncludePrefixMessage;
 use Foo\TestMessage;
 use Foo\TestMessage_Sub;
+use Foo\TestReverseFieldOrder;
+use Foo\testLowerCaseMessage;
+use Foo\testLowerCaseEnum;
+use Php\Test\TestNamespace;
 
 class GeneratedClassTest extends TestBase
 {
@@ -60,24 +65,6 @@
         $this->assertSame(MIN_INT32, $m->getOptionalInt32());
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt32(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt32('abc');
-    }
-
     #########################################################
     # Test uint32 field.
     #########################################################
@@ -117,24 +104,6 @@
         $this->assertSame(MIN_INT32, $m->getOptionalUint32());
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint32(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint32('abc');
-    }
-
     #########################################################
     # Test int64 field.
     #########################################################
@@ -187,24 +156,6 @@
         }
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt64(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalInt64('abc');
-    }
-
     #########################################################
     # Test uint64 field.
     #########################################################
@@ -252,24 +203,6 @@
         }
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64FieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint64(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64FieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalUint64('abc');
-    }
-
     #########################################################
     # Test enum field.
     #########################################################
@@ -324,24 +257,6 @@
         $this->assertEquals(3.1, $m->getOptionalFloat(), '', MAX_FLOAT_DIFF);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatFieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalFloat(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatFieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalFloat('abc');
-    }
-
     #########################################################
     # Test double field.
     #########################################################
@@ -365,24 +280,6 @@
         $this->assertEquals(3.1, $m->getOptionalDouble(), '', MAX_FLOAT_DIFF);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleFieldInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalDouble(new TestMessage());
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleFieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalDouble('abc');
-    }
-
     #########################################################
     # Test bool field.
     #########################################################
@@ -408,15 +305,6 @@
         $this->assertSame(false, $m->getOptionalBool());
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolFieldInvalidStringFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalBool(new TestMessage());
-    }
-
     #########################################################
     # Test string field.
     #########################################################
@@ -442,16 +330,6 @@
         $this->assertSame('1', $m->getOptionalString());
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringFieldInvalidUTF8Fail()
-    {
-        $m = new TestMessage();
-        $hex = hex2bin("ff");
-        $m->setOptionalString($hex);
-    }
-
     #########################################################
     # Test bytes field.
     #########################################################
@@ -502,25 +380,6 @@
         $this->assertNull($m->getOptionalMessage());
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageFieldWrongTypeFail()
-    {
-        $m = new TestMessage();
-        $a = 1;
-        $m->setOptionalMessage($a);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageFieldWrongClassFail()
-    {
-        $m = new TestMessage();
-        $m->setOptionalMessage(new TestMessage());
-    }
-
     #########################################################
     # Test repeated field.
     #########################################################
@@ -554,48 +413,6 @@
         $this->assertFalse($arr instanceof RepeatedField);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongTypeFail()
-    {
-        $m = new TestMessage();
-        $a = 1;
-        $m->setRepeatedInt32($a);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongObjectFail()
-    {
-        $m = new TestMessage();
-        $m->setRepeatedInt32($m);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongRepeatedTypeFail()
-    {
-        $m = new TestMessage();
-
-        $repeated_int32 = new RepeatedField(GPBType::UINT32);
-        $m->setRepeatedInt32($repeated_int32);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testRepeatedFieldWrongRepeatedMessageClassFail()
-    {
-        $m = new TestMessage();
-
-        $repeated_message = new RepeatedField(GPBType::MESSAGE,
-                                              TestMessage::class);
-        $m->setRepeatedMessage($repeated_message);
-    }
-
     #########################################################
     # Test map field.
     #########################################################
@@ -627,49 +444,6 @@
         $this->assertFalse($dict instanceof MapField);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongTypeFail()
-    {
-        $m = new TestMessage();
-        $a = 1;
-        $m->setMapInt32Int32($a);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongObjectFail()
-    {
-        $m = new TestMessage();
-        $m->setMapInt32Int32($m);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongRepeatedTypeFail()
-    {
-        $m = new TestMessage();
-
-        $map_uint32_uint32 = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $m->setMapInt32Int32($map_uint32_uint32);
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMapFieldWrongRepeatedMessageClassFail()
-    {
-        $m = new TestMessage();
-
-        $map_int32_message = new MapField(GPBType::INT32,
-                                          GPBType::MESSAGE,
-                                          TestMessage::class);
-        $m->setMapInt32Message($map_int32_message);
-    }
-
     #########################################################
     # Test oneof field.
     #########################################################
@@ -741,24 +515,44 @@
         $n->setOptionalInt32(100);
         $sub1 = new TestMessage_Sub();
         $sub1->setA(101);
-        $sub1->getB()[] = 102;
+
+        $b = $sub1->getB();
+        $b[] = 102;
+        $sub1->setB($b);
+
         $n->setOptionalMessage($sub1);
 
         // Repeated
-        $n->getRepeatedInt32()[] = 200;
-        $n->getRepeatedString()[] = 'abc';
+        $repeatedInt32 = $n->getRepeatedInt32();
+        $repeatedInt32[] = 200;
+        $n->setRepeatedInt32($repeatedInt32);
+
+        $repeatedString = $n->getRepeatedString();
+        $repeatedString[] = 'abc';
+        $n->setRepeatedString($repeatedString);
+
         $sub2 = new TestMessage_Sub();
         $sub2->setA(201);
-        $n->getRepeatedMessage()[] = $sub2;
+        $repeatedMessage = $n->getRepeatedMessage();
+        $repeatedMessage[] = $sub2;
+        $n->setRepeatedMessage($repeatedMessage);
 
         // Map
-        $n->getMapInt32Int32()[1] = 300;
-        $n->getMapInt32Int32()[-62] = 301;
-        $n->getMapStringString()['def'] = 'def';
-        $n->getMapInt32Message()[1] = new TestMessage_Sub();
-        $n->getMapInt32Message()[1]->setA(302);
-        $n->getMapInt32Message()[2] = new TestMessage_Sub();
-        $n->getMapInt32Message()[2]->setA(303);
+        $mapInt32Int32 = $n->getMapInt32Int32();
+        $mapInt32Int32[1] = 300;
+        $mapInt32Int32[-62] = 301;
+        $n->setMapInt32Int32($mapInt32Int32);
+
+        $mapStringString = $n->getMapStringString();
+        $mapStringString['def'] = 'def';
+        $n->setMapStringString($mapStringString);
+
+        $mapInt32Message = $n->getMapInt32Message();
+        $mapInt32Message[1] = new TestMessage_Sub();
+        $mapInt32Message[1]->setA(302);
+        $mapInt32Message[2] = new TestMessage_Sub();
+        $mapInt32Message[2]->setA(303);
+        $n->setMapInt32Message($mapInt32Message);
 
         $m->mergeFrom($n);
 
@@ -793,9 +587,16 @@
         // Check sub-messages are copied by value.
         $n->getOptionalMessage()->setA(-101);
         $this->assertSame(101, $m->getOptionalMessage()->getA());
-        $n->getRepeatedMessage()[0]->setA(-201);
+
+        $repeatedMessage = $n->getRepeatedMessage();
+        $repeatedMessage[0]->setA(-201);
+        $n->setRepeatedMessage($repeatedMessage);
         $this->assertSame(201, $m->getRepeatedMessage()[2]->getA());
-        $n->getMapInt32Message()[1]->setA(-302);
+
+        $mapInt32Message = $n->getMapInt32Message();
+        $mapInt32Message[1]->setA(-302);
+        $n->setMapInt32Message($mapInt32Message);
+
         $this->assertSame(302, $m->getMapInt32Message()[1]->getA());
 
         // Test merge oneof.
@@ -822,16 +623,6 @@
         $this->expectFields($n);
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageMergeFromInvalidTypeFail()
-    {
-        $m = new TestMessage();
-        $n = new TestMessage_Sub();
-        $m->mergeFrom($n);
-    }
-
     #########################################################
     # Test message/enum without namespace.
     #########################################################
@@ -841,7 +632,9 @@
         $m = new TestMessage();
         $sub = new NoNameSpaceMessage();
         $m->setOptionalNoNamespaceMessage($sub);
-        $m->getRepeatedNoNamespaceMessage()[] = new NoNameSpaceMessage();
+        $repeatedNoNamespaceMessage = $m->getRepeatedNoNamespaceMessage();
+        $repeatedNoNamespaceMessage[] = new NoNameSpaceMessage();
+        $m->setRepeatedNoNamespaceMessage($repeatedNoNamespaceMessage);
 
         $n = new NoNamespaceMessage();
         $n->setB(NoNamespaceMessage_NestedEnum::ZERO);
@@ -851,7 +644,9 @@
     {
         $m = new TestMessage();
         $m->setOptionalNoNamespaceEnum(NoNameSpaceEnum::VALUE_A);
-        $m->getRepeatedNoNamespaceEnum()[] = NoNameSpaceEnum::VALUE_A;
+        $repeatedNoNamespaceEnum = $m->getRepeatedNoNamespaceEnum();
+        $repeatedNoNamespaceEnum[] = NoNameSpaceEnum::VALUE_A;
+        $m->setRepeatedNoNamespaceEnum($repeatedNoNamespaceEnum);
     }
 
     #########################################################
@@ -868,6 +663,25 @@
     }
 
     #########################################################
+    # Test message with given namespace.
+    #########################################################
+
+    public function testNamespaceMessage()
+    {
+        $m = new TestIncludeNamespaceMessage();
+
+        $n = new TestNamespace();
+        $n->setA(1);
+        $m->setNamespaceMessage($n);
+        $this->assertSame(1, $m->getNamespaceMessage()->getA());
+
+        $n = new TestEmptyNamespace();
+        $n->setA(1);
+        $m->setEmptyNamespaceMessage($n);
+        $this->assertSame(1, $m->getEmptyNamespaceMessage()->getA());
+    }
+
+    #########################################################
     # Test prefix for reserved words.
     #########################################################
 
@@ -891,4 +705,26 @@
         $this->assertSame(1, $m->getOptionalInt32());
         $this->assertSame(2, $m->getOptionalUInt32());
     }
+
+    #########################################################
+    # Test Reverse Field Order.
+    #########################################################
+
+    public function testReverseFieldOrder()
+    {
+        $m = new TestReverseFieldOrder();
+        $m->setB("abc");
+        $this->assertSame("abc", $m->getB());
+        $this->assertNotSame("abc", $m->getA());
+    }
+
+    #########################################################
+    # Test Reverse Field Order.
+    #########################################################
+
+    public function testLowerCase()
+    {
+        $m = new testLowerCaseMessage();
+        $n = testLowerCaseEnum::VALUE;
+    }
 }
diff --git a/php/tests/generated_phpdoc_test.php b/php/tests/generated_phpdoc_test.php
new file mode 100644
index 0000000..6c1a26f
--- /dev/null
+++ b/php/tests/generated_phpdoc_test.php
@@ -0,0 +1,337 @@
+<?php
+
+require_once('generated/NoNamespaceEnum.php');
+require_once('generated/NoNamespaceMessage.php');
+require_once('test_base.php');
+require_once('test_util.php');
+
+use Foo\TestMessage;
+
+class GeneratedPhpdocTest extends TestBase
+{
+    public function testPhpDocForClass()
+    {
+        $class = new ReflectionClass('Foo\TestMessage');
+        $doc = $class->getDocComment();
+        $this->assertContains('foo.TestMessage', $doc);
+    }
+
+    /**
+     * @dataProvider providePhpDocForGettersAndSetters
+     */
+    public function testPhpDocForIntGetters($methods, $expectedDoc)
+    {
+        $class = new ReflectionClass('Foo\TestMessage');
+        foreach ($methods as $method) {
+            $doc = $class->getMethod($method)->getDocComment();
+            $this->assertContains($expectedDoc, $doc);
+        }
+    }
+
+    public function providePhpDocForGettersAndSetters()
+    {
+        return [
+            [
+                [
+                    'setOptionalInt32',
+                    'setOptionalUint32',
+                    'setOptionalSint32',
+                    'setOptionalFixed32',
+                    'setOptionalSfixed32',
+                    'setOneofInt32',
+                    'setOneofUint32',
+                    'setOneofSint32',
+                    'setOneofFixed32',
+                    'setOneofSfixed32',
+                    'setOptionalEnum',
+                    'setOptionalNoNamespaceEnum',
+                    'setOptionalNestedEnum',
+                    'setOneofEnum'
+                ],
+                '@param int $var'
+            ],
+            [
+                [
+                    'setOptionalInt64',
+                    'setOptionalUint64',
+                    'setOptionalSint64',
+                    'setOptionalFixed64',
+                    'setOptionalSfixed64',
+                    'setOneofInt64',
+                    'setOneofUint64',
+                    'setOneofSint64',
+                    'setOneofFixed64',
+                    'setOneofSfixed64',
+                ],
+                '@param int|string $var'
+            ],
+            [
+                [
+                    'getOptionalInt32',
+                    'getOptionalUint32',
+                    'getOptionalSint32',
+                    'getOptionalFixed32',
+                    'getOptionalSfixed32',
+                    'getOneofInt32',
+                    'getOneofUint32',
+                    'getOneofSint32',
+                    'getOneofFixed32',
+                    'getOneofSfixed32',
+                    'getOptionalEnum',
+                    'getOptionalNoNamespaceEnum',
+                    'getOptionalNestedEnum',
+                    'getOneofEnum',
+                ],
+                '@return int'
+            ],
+            [
+                [
+                    'setOptionalInt64',
+                    'setOptionalUint64',
+                    'setOptionalSint64',
+                    'setOptionalFixed64',
+                    'setOptionalSfixed64',
+                    'setOneofInt64',
+                    'setOneofUint64',
+                    'setOneofSint64',
+                    'setOneofFixed64',
+                    'setOneofSfixed64',
+                ],
+                '@param int|string $var'
+            ],
+            [
+                [
+                    'getRepeatedInt32',
+                    'getRepeatedInt64',
+                    'getRepeatedUint32',
+                    'getRepeatedUint64',
+                    'getRepeatedSint32',
+                    'getRepeatedSint64',
+                    'getRepeatedFixed32',
+                    'getRepeatedFixed64',
+                    'getRepeatedSfixed32',
+                    'getRepeatedSfixed64',
+                    'getRepeatedFloat',
+                    'getRepeatedDouble',
+                    'getRepeatedBool',
+                    'getRepeatedString',
+                    'getRepeatedBytes',
+                    'getRepeatedEnum',
+                    'getRepeatedMessage',
+                    'getRepeatedRecursive',
+                    'getRepeatedNoNamespaceMessage',
+                    'getRepeatedNoNamespaceEnum',
+                ],
+                '@return \Google\Protobuf\Internal\RepeatedField'
+            ],
+            [
+                [
+                    'getMapInt32Int32',
+                    'getMapInt64Int64',
+                    'getMapUint32Uint32',
+                    'getMapUint64Uint64',
+                    'getMapSint32Sint32',
+                    'getMapSint64Sint64',
+                    'getMapFixed32Fixed32',
+                    'getMapFixed64Fixed64',
+                    'getMapSfixed32Sfixed32',
+                    'getMapSfixed64Sfixed64',
+                    'getMapInt32Float',
+                    'getMapInt32Double',
+                    'getMapBoolBool',
+                    'getMapStringString',
+                    'getMapInt32Bytes',
+                    'getMapInt32Enum',
+                    'getMapInt32Message',
+                    'getMapRecursive',
+                ],
+                '@return \Google\Protobuf\Internal\MapField'
+            ],
+            [
+                [
+                    'setRepeatedInt32',
+                    'setRepeatedUint32',
+                    'setRepeatedSint32',
+                    'setRepeatedFixed32',
+                    'setRepeatedSfixed32',
+                    'setRepeatedEnum',
+                    'setRepeatedNoNamespaceEnum',
+                ],
+                '@param int[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedInt64',
+                    'setRepeatedUint64',
+                    'setRepeatedSint64',
+                    'setRepeatedFixed64',
+                    'setRepeatedSfixed64',
+                ],
+                '@param int[]|string[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedFloat',
+                    'setRepeatedDouble',
+                ],
+                '@param float[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedBool',
+                ],
+                '@param bool[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedString',
+                    'setRepeatedBytes',
+                ],
+                '@param string[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedMessage',
+                ],
+                '@param \Foo\TestMessage_Sub[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedRecursive',
+                ],
+                '@param \Foo\TestMessage[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setRepeatedNoNamespaceMessage',
+                ],
+                '@param \NoNamespaceMessage[]|\Google\Protobuf\Internal\RepeatedField $var'
+            ],
+            [
+                [
+                    'setMapInt32Int32',
+                    'setMapInt64Int64',
+                    'setMapUint32Uint32',
+                    'setMapUint64Uint64',
+                    'setMapSint32Sint32',
+                    'setMapSint64Sint64',
+                    'setMapFixed32Fixed32',
+                    'setMapFixed64Fixed64',
+                    'setMapSfixed32Sfixed32',
+                    'setMapSfixed64Sfixed64',
+                    'setMapInt32Float',
+                    'setMapInt32Double',
+                    'setMapBoolBool',
+                    'setMapStringString',
+                    'setMapInt32Bytes',
+                    'setMapInt32Enum',
+                    'setMapInt32Message',
+                    'setMapRecursive',
+                ],
+                '@param array|\Google\Protobuf\Internal\MapField $var'
+            ],
+            [
+                [
+                    'getOptionalFloat',
+                    'getOptionalDouble',
+                    'getOneofDouble',
+                    'getOneofFloat',
+                ],
+                '@return float'
+            ],
+            [
+                [
+                    'setOptionalFloat',
+                    'setOptionalDouble',
+                    'setOneofDouble',
+                    'setOneofFloat',
+                ],
+                '@param float $var'
+            ],
+            [
+                [
+                    'getOptionalBool',
+                    'getOneofBool',
+                ],
+                '@return bool'],
+            [
+                [
+                    'setOptionalBool',
+                    'setOneofBool',
+                ],
+                '@param bool $var'
+            ],
+            [
+                [
+                    'getOptionalString',
+                    'getOptionalBytes',
+                    'getOneofString',
+                    'getOneofBytes',
+                    'getMyOneof',
+                ],
+                '@return string'
+            ],
+            [
+                [
+                    'setOptionalString',
+                    'setOptionalBytes',
+                    'setOneofString',
+                    'setOneofBytes',
+                ],
+                '@param string $var'
+            ],
+
+            [
+                [
+                    'getOptionalMessage',
+                    'getOneofMessage'
+                ],
+                '@return \Foo\TestMessage_Sub'
+            ],
+            [
+                [
+                    'setOptionalMessage',
+                    'setOneofMessage'
+                ],
+                '@param \Foo\TestMessage_Sub $var'
+            ],
+            [
+                [
+                    'getOptionalIncludedMessage'
+                ],
+                '@return \Bar\TestInclude'
+            ],
+            [
+                [
+                    'setOptionalIncludedMessage'
+                ],
+                '@param \Bar\TestInclude $var'
+            ],
+            [
+                [
+                    'getRecursive'
+                ],
+                '@return \Foo\TestMessage'
+            ],
+            [
+                [
+                    'setRecursive'
+                ],
+                '@param \Foo\TestMessage $var'
+            ],
+
+            [
+                [
+                    'getOptionalNoNamespaceMessage'
+                ],
+                '@return \NoNamespaceMessage'
+            ],
+            [
+                [
+                    'setOptionalNoNamespaceMessage'
+                ],
+                '@param \NoNamespaceMessage $var'
+            ],
+        ];
+    }
+}
diff --git a/php/tests/generated_service_test.php b/php/tests/generated_service_test.php
new file mode 100644
index 0000000..5407db9
--- /dev/null
+++ b/php/tests/generated_service_test.php
@@ -0,0 +1,110 @@
+<?php
+
+require_once('test_base.php');
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\MapField;
+use Google\Protobuf\Internal\GPBType;
+use Foo\Greeter;
+use Foo\HelloRequest;
+use Foo\HelloReply;
+
+class GeneratedServiceTest extends TestBase
+{
+    /**
+     * @var \ReflectionClass
+     */
+    private $serviceClass;
+
+    /**
+     * @var \ReflectionClass
+     */
+    private $namespacedServiceClass;
+
+    /**
+     * @var array
+     */
+    private $methodNames = [
+        'sayHello',
+        'sayHelloAgain'
+    ];
+
+    public function setUp()
+    {
+        parent::setUp();
+
+        $this->serviceClass = new ReflectionClass('Foo\GreeterInterface');
+
+        $this->namespacedServiceClass = new ReflectionClass('Bar\OtherGreeterInterface');
+    }
+
+    public function testIsInterface()
+    {
+        $this->assertTrue($this->serviceClass->isInterface());
+    }
+
+    public function testPhpDocForClass()
+    {
+        $this->assertContains('foo.Greeter', $this->serviceClass->getDocComment());
+    }
+
+    public function testPhpDocForNamespacedClass()
+    {
+        $this->assertContains('foo.OtherGreeter', $this->namespacedServiceClass->getDocComment());
+    }
+
+    public function testServiceMethodsAreGenerated()
+    {
+        $this->assertCount(count($this->methodNames), $this->serviceClass->getMethods());
+        foreach ($this->methodNames as $methodName) {
+            $this->assertTrue($this->serviceClass->hasMethod($methodName));
+        }
+    }
+
+    public function testPhpDocForServiceMethod()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $docComment = $this->serviceClass->getMethod($methodName)->getDocComment();
+            $this->assertContains($methodName, $docComment);
+            $this->assertContains('@param \Foo\HelloRequest $request', $docComment);
+            $this->assertContains('@return \Foo\HelloReply', $docComment);
+        }
+    }
+
+    public function testPhpDocForServiceMethodInNamespacedClass()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $docComment = $this->namespacedServiceClass->getMethod($methodName)->getDocComment();
+            $this->assertContains($methodName, $docComment);
+            $this->assertContains('@param \Foo\HelloRequest $request', $docComment);
+            $this->assertContains('@return \Foo\HelloReply', $docComment);
+        }
+    }
+
+    public function testParamForServiceMethod()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $method = $this->serviceClass->getMethod($methodName);
+            $this->assertCount(1, $method->getParameters());
+            $param = $method->getParameters()[0];
+            $this->assertFalse($param->isOptional());
+            $this->assertSame('request', $param->getName());
+            // ReflectionParameter::getType only exists in PHP 7+, so get the type from __toString
+            $this->assertContains('Foo\HelloRequest $request', (string) $param);
+        }
+    }
+
+    public function testParamForServiceMethodInNamespacedClass()
+    {
+        foreach ($this->methodNames as $methodName) {
+            $method = $this->serviceClass->getMethod($methodName);
+            $this->assertCount(1, $method->getParameters());
+            $param = $method->getParameters()[0];
+            $this->assertFalse($param->isOptional());
+            $this->assertSame('request', $param->getName());
+            // ReflectionParameter::getType only exists in PHP 7+, so get the type from __toString
+            $this->assertContains('Foo\HelloRequest $request', (string) $param);
+        }
+    }
+}
diff --git a/php/tests/map_field_test.php b/php/tests/map_field_test.php
index 2fda913..cffa252 100644
--- a/php/tests/map_field_test.php
+++ b/php/tests/map_field_test.php
@@ -56,42 +56,23 @@
         unset($arr['3.1']);
         unset($arr[MAX_INT32_STRING]);
         $this->assertEquals(0, count($arr));
-    }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetStringKeyFail()
-    {
+        // Test foreach.
         $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr ['abc']= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr [new TestMessage_Sub()]= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt32SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr [0]= new TestMessage_Sub();
+        for ($i = 0; $i < 3; $i++) {
+          $arr[$i] = $i;
+        }
+        $i = 0;
+        $arr_test = [];
+        foreach ($arr as $key => $val) {
+          $this->assertSame($key, $val);
+          $arr_test[] = $key;
+          $i++;
+        }
+        $this->assertTrue(isset($arr_test[0]));
+        $this->assertTrue(isset($arr_test[1]));
+        $this->assertTrue(isset($arr_test[2]));
+        $this->assertSame(3, $i);
     }
 
     #########################################################
@@ -159,42 +140,6 @@
         $this->assertEquals(0, count($arr));
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr ['abc']= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr [new TestMessage_Sub()]= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint32SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test int64 field.
     #########################################################
@@ -252,42 +197,6 @@
         $this->assertEquals(0, count($arr));
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr ['abc']= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr [new TestMessage_Sub()]= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testInt64SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test uint64 field.
     #########################################################
@@ -339,42 +248,6 @@
         $this->assertEquals(0, count($arr));
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetStringKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr ['abc']= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetStringValueFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr [new TestMessage_Sub()]= 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testUint64SetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test float field.
     #########################################################
@@ -397,24 +270,6 @@
         $this->assertEquals(4, count($arr));
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatSetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::FLOAT);
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testFloatSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::FLOAT);
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test double field.
     #########################################################
@@ -437,24 +292,6 @@
         $this->assertEquals(4, count($arr));
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetStringValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
-        $arr [0]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testDoubleSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
-        $arr [0]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test bool field.
     #########################################################
@@ -515,24 +352,6 @@
         $this->assertEquals(0, count($arr));
     }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolSetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr [new TestMessage_Sub()]= true;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testBoolSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr [true]= new TestMessage_Sub();
-    }
-
     #########################################################
     # Test string field.
     #########################################################
@@ -564,42 +383,23 @@
         $this->assertEquals(1, count($arr));
         unset($arr[True]);
         $this->assertEquals(0, count($arr));
-    }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetInvalidUTF8KeyFail()
-    {
+        // Test foreach.
         $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr[hex2bin("ff")]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetInvalidUTF8ValueFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr ['abc']= hex2bin("ff");
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetMessageKeyFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr [new TestMessage_Sub()]= 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testStringSetMessageValueFail()
-    {
-        $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr ['abc']= new TestMessage_Sub();
+        for ($i = 0; $i < 3; $i++) {
+          $arr[$i] = $i;
+        }
+        $i = 0;
+        $arr_test = [];
+        foreach ($arr as $key => $val) {
+          $this->assertSame($key, $val);
+          $arr_test[] = $key;
+          $i++;
+        }
+        $this->assertTrue(isset($arr_test['0']));
+        $this->assertTrue(isset($arr_test['1']));
+        $this->assertTrue(isset($arr_test['2']));
+        $this->assertSame(3, $i);
     }
 
     #########################################################
@@ -617,47 +417,29 @@
         $this->assertSame(1, $arr[0]->getA());
 
         $this->assertEquals(1, count($arr));
-    }
 
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetIntValueFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = 0;
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetStringValueFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = 'abc';
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetOtherMessageValueFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = new TestMessage_Sub();
-    }
-
-    /**
-     * @expectedException PHPUnit_Framework_Error
-     */
-    public function testMessageSetNullFail()
-    {
-       $arr =
-           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $null = NULL;
-       $arr[0] = $null;
+        // Test foreach.
+        $arr = new MapField(GPBType::INT32,
+            GPBType::MESSAGE, TestMessage_Sub::class);
+        for ($i = 0; $i < 3; $i++) {
+          $arr[$i] = new TestMessage_Sub();;
+          $arr[$i]->setA($i);
+        }
+        $i = 0;
+        $key_test = [];
+        $value_test = [];
+        foreach ($arr as $key => $val) {
+          $key_test[] = $key;
+          $value_test[] = $val->getA();
+          $i++;
+        }
+        $this->assertTrue(isset($key_test['0']));
+        $this->assertTrue(isset($key_test['1']));
+        $this->assertTrue(isset($key_test['2']));
+        $this->assertTrue(isset($value_test['0']));
+        $this->assertTrue(isset($value_test['1']));
+        $this->assertTrue(isset($value_test['2']));
+        $this->assertSame(3, $i);
     }
 
     #########################################################
@@ -669,7 +451,7 @@
     // {
     //     $arr = new MapField(GPBType::INT32,
     //         GPBType::MESSAGE, TestMessage::class);
-    //     $arr [0]= new TestMessage;
+    //     $arr[0] = new TestMessage;
     //     $arr[0]->SetMapRecursive($arr);
 
     //     // Clean up memory before test.
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
index 5eac56f..7c3a180 100644
--- a/php/tests/memory_leak_test.php
+++ b/php/tests/memory_leak_test.php
@@ -7,10 +7,12 @@
 require_once('generated/NoNamespaceMessage_NestedEnum.php');
 require_once('generated/PrefixEmpty.php');
 require_once('generated/PrefixTestPrefix.php');
+require_once('generated/TestEmptyNamespace.php');
 require_once('generated/Bar/TestInclude.php');
 require_once('generated/Foo/PBARRAY.php');
 require_once('generated/Foo/PBEmpty.php');
 require_once('generated/Foo/TestEnum.php');
+require_once('generated/Foo/TestIncludeNamespaceMessage.php');
 require_once('generated/Foo/TestIncludePrefixMessage.php');
 require_once('generated/Foo/TestMessage.php');
 require_once('generated/Foo/TestMessage_Empty.php');
@@ -18,11 +20,18 @@
 require_once('generated/Foo/TestMessage_Sub.php');
 require_once('generated/Foo/TestPackedMessage.php');
 require_once('generated/Foo/TestPhpDoc.php');
+require_once('generated/Foo/TestRandomFieldOrder.php');
+require_once('generated/Foo/TestReverseFieldOrder.php');
 require_once('generated/Foo/TestUnpackedMessage.php');
+require_once('generated/Foo/testLowerCaseMessage.php');
+require_once('generated/Foo/testLowerCaseEnum.php');
 require_once('generated/GPBMetadata/Proto/Test.php');
+require_once('generated/GPBMetadata/Proto/TestEmptyPhpNamespace.php');
 require_once('generated/GPBMetadata/Proto/TestInclude.php');
 require_once('generated/GPBMetadata/Proto/TestNoNamespace.php');
+require_once('generated/GPBMetadata/Proto/TestPhpNamespace.php');
 require_once('generated/GPBMetadata/Proto/TestPrefix.php');
+require_once('generated/Php/Test/TestNamespace.php');
 require_once('test_util.php');
 
 use Google\Protobuf\Internal\RepeatedField;
@@ -44,7 +53,7 @@
 $from->setRecursive($from);
 
 $arr = new RepeatedField(GPBType::MESSAGE, TestMessage::class);
-$arr []= new TestMessage;
+$arr[] = new TestMessage;
 $arr[0]->SetRepeatedRecursive($arr);
 
 // Test oneof fields.
diff --git a/php/tests/php_implementation_test.php b/php/tests/php_implementation_test.php
index e124980..5dbc923 100644
--- a/php/tests/php_implementation_test.php
+++ b/php/tests/php_implementation_test.php
@@ -6,12 +6,12 @@
 use Foo\TestMessage;
 use Foo\TestMessage_Sub;
 use Foo\TestPackedMessage;
-use Google\Protobuf\Internal\InputStream;
+use Google\Protobuf\Internal\CodedInputStream;
 use Google\Protobuf\Internal\FileDescriptorSet;
 use Google\Protobuf\Internal\GPBLabel;
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
-use Google\Protobuf\Internal\OutputStream;
+use Google\Protobuf\Internal\CodedOutputStream;
 
 class ImplementationTest extends TestBase
 {
@@ -21,17 +21,17 @@
         $value = null;
 
         // Positive number.
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readInt32($input, $value);
         $this->assertSame(1, $value);
 
         // Negative number.
-        $input = new InputStream(hex2bin("ffffffff0f"));
+        $input = new CodedInputStream(hex2bin("ffffffff0f"));
         GPBWire::readInt32($input, $value);
         $this->assertSame(-1, $value);
 
         // Discard overflow bits.
-        $input = new InputStream(hex2bin("ffffffff7f"));
+        $input = new CodedInputStream(hex2bin("ffffffff7f"));
         GPBWire::readInt32($input, $value);
         $this->assertSame(-1, $value);
     }
@@ -41,17 +41,17 @@
         $value = null;
 
         // Positive number.
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readUint32($input, $value);
         $this->assertSame(1, $value);
 
         // Max uint32.
-        $input = new InputStream(hex2bin("ffffffff0f"));
+        $input = new CodedInputStream(hex2bin("ffffffff0f"));
         GPBWire::readUint32($input, $value);
         $this->assertSame(-1, $value);
 
         // Discard overflow bits.
-        $input = new InputStream(hex2bin("ffffffff7f"));
+        $input = new CodedInputStream(hex2bin("ffffffff7f"));
         GPBWire::readUint32($input, $value);
         $this->assertSame(-1, $value);
     }
@@ -61,17 +61,17 @@
         $value = null;
 
         // Positive number.
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readInt64($input, $value);
         $this->assertEquals(1, $value);
 
         // Negative number.
-        $input = new InputStream(hex2bin("ffffffffffffffffff01"));
+        $input = new CodedInputStream(hex2bin("ffffffffffffffffff01"));
         GPBWire::readInt64($input, $value);
         $this->assertEquals(-1, $value);
 
         // Discard overflow bits.
-        $input = new InputStream(hex2bin("ffffffffffffffffff0f"));
+        $input = new CodedInputStream(hex2bin("ffffffffffffffffff0f"));
         GPBWire::readInt64($input, $value);
         $this->assertEquals(-1, $value);
     }
@@ -81,17 +81,17 @@
         $value = null;
 
         // Positive number.
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readUint64($input, $value);
         $this->assertEquals(1, $value);
 
         // Negative number.
-        $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF01"));
+        $input = new CodedInputStream(hex2bin("FFFFFFFFFFFFFFFFFF01"));
         GPBWire::readUint64($input, $value);
         $this->assertEquals(-1, $value);
 
         // Discard overflow bits.
-        $input = new InputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F"));
+        $input = new CodedInputStream(hex2bin("FFFFFFFFFFFFFFFFFF0F"));
         GPBWire::readUint64($input, $value);
         $this->assertEquals(-1, $value);
     }
@@ -100,15 +100,15 @@
     {
         $value = null;
 
-        $input = new InputStream(hex2bin("00"));
+        $input = new CodedInputStream(hex2bin("00"));
         GPBWire::readSint32($input, $value);
         $this->assertSame(0, $value);
 
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readSint32($input, $value);
         $this->assertSame(-1, $value);
 
-        $input = new InputStream(hex2bin("02"));
+        $input = new CodedInputStream(hex2bin("02"));
         GPBWire::readSint32($input, $value);
         $this->assertSame(1, $value);
     }
@@ -117,15 +117,15 @@
     {
         $value = null;
 
-        $input = new InputStream(hex2bin("00"));
+        $input = new CodedInputStream(hex2bin("00"));
         GPBWire::readSint64($input, $value);
         $this->assertEquals(0, $value);
 
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readSint64($input, $value);
         $this->assertEquals(-1, $value);
 
-        $input = new InputStream(hex2bin("02"));
+        $input = new CodedInputStream(hex2bin("02"));
         GPBWire::readSint64($input, $value);
         $this->assertEquals(1, $value);
     }
@@ -133,7 +133,7 @@
     public function testReadFixed32()
     {
         $value = null;
-        $input = new InputStream(hex2bin("12345678"));
+        $input = new CodedInputStream(hex2bin("12345678"));
         GPBWire::readFixed32($input, $value);
         $this->assertSame(0x78563412, $value);
     }
@@ -141,7 +141,7 @@
     public function testReadFixed64()
     {
         $value = null;
-        $input = new InputStream(hex2bin("1234567812345678"));
+        $input = new CodedInputStream(hex2bin("1234567812345678"));
         GPBWire::readFixed64($input, $value);
         if (PHP_INT_SIZE == 4) {
             $this->assertSame("8671175386481439762", $value);
@@ -153,7 +153,7 @@
     public function testReadSfixed32()
     {
         $value = null;
-        $input = new InputStream(hex2bin("12345678"));
+        $input = new CodedInputStream(hex2bin("12345678"));
         GPBWire::readSfixed32($input, $value);
         $this->assertSame(0x78563412, $value);
     }
@@ -161,7 +161,7 @@
     public function testReadFloat()
     {
         $value = null;
-        $input = new InputStream(hex2bin("0000803F"));
+        $input = new CodedInputStream(hex2bin("0000803F"));
         GPBWire::readFloat($input, $value);
         $this->assertSame(1.0, $value);
     }
@@ -170,11 +170,11 @@
     {
         $value = null;
 
-        $input = new InputStream(hex2bin("00"));
+        $input = new CodedInputStream(hex2bin("00"));
         GPBWire::readBool($input, $value);
         $this->assertSame(false, $value);
 
-        $input = new InputStream(hex2bin("01"));
+        $input = new CodedInputStream(hex2bin("01"));
         GPBWire::readBool($input, $value);
         $this->assertSame(true, $value);
     }
@@ -182,7 +182,7 @@
     public function testReadDouble()
     {
         $value = null;
-        $input = new InputStream(hex2bin("000000000000F03F"));
+        $input = new CodedInputStream(hex2bin("000000000000F03F"));
         GPBWire::readDouble($input, $value);
         $this->assertSame(1.0, $value);
     }
@@ -190,7 +190,7 @@
     public function testReadSfixed64()
     {
         $value = null;
-        $input = new InputStream(hex2bin("1234567812345678"));
+        $input = new CodedInputStream(hex2bin("1234567812345678"));
         GPBWire::readSfixed64($input, $value);
         if (PHP_INT_SIZE == 4) {
             $this->assertSame("8671175386481439762", $value);
@@ -207,8 +207,7 @@
         $this->assertSame(3, GPBWire::zigZagEncode32(-2));
         $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode32(0x3FFFFFFF));
         $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(0xC0000000));
-        $this->assertSame(-2, GPBWire::zigZagEncode32(0x7FFFFFFF));
-        $this->assertSame(-1, GPBWire::zigZagEncode32(0x80000000));
+        $this->assertSame(0x7FFFFFFF, GPBWire::zigZagEncode32(-1073741824));
 
         $this->assertSame(0,  GPBWire::zigZagDecode32(0));
         $this->assertSame(-1, GPBWire::zigZagDecode32(1));
@@ -220,6 +219,8 @@
         $this->assertSame((int)-2147483648,GPBWire::zigZagDecode32(0xFFFFFFFF));
 
         if (PHP_INT_SIZE == 4) {
+            $this->assertSame(-2, GPBWire::zigZagEncode32(0x7FFFFFFF));
+            $this->assertSame(-1, GPBWire::zigZagEncode32(0x80000000));
             $this->assertSame('0', GPBWire::zigZagEncode64(0));
             $this->assertSame('1', GPBWire::zigZagEncode64(-1));
             $this->assertSame('2', GPBWire::zigZagEncode64(1));
@@ -250,6 +251,8 @@
             $this->assertSame('1', GPBWire::zigZagDecode64(2));
             $this->assertSame('-2', GPBWire::zigZagDecode64(3));
         } else {
+            $this->assertSame(4294967294, GPBWire::zigZagEncode32(0x7FFFFFFF));
+            $this->assertSame(4294967295, GPBWire::zigZagEncode32(0x80000000));
             $this->assertSame(0, GPBWire::zigZagEncode64(0));
             $this->assertSame(1, GPBWire::zigZagEncode64(-1));
             $this->assertSame(2, GPBWire::zigZagEncode64(1));
@@ -330,19 +333,19 @@
         $var = 0;
 
         // Empty buffer.
-        $input = new InputStream(hex2bin(''));
+        $input = new CodedInputStream(hex2bin(''));
         $this->assertFalse($input->readVarint64($var));
 
         // The largest varint is 10 bytes long.
-        $input = new InputStream(hex2bin('8080808080808080808001'));
+        $input = new CodedInputStream(hex2bin('8080808080808080808001'));
         $this->assertFalse($input->readVarint64($var));
 
         // Corrupted varint.
-        $input = new InputStream(hex2bin('808080'));
+        $input = new CodedInputStream(hex2bin('808080'));
         $this->assertFalse($input->readVarint64($var));
 
         // Normal case.
-        $input = new InputStream(hex2bin('808001'));
+        $input = new CodedInputStream(hex2bin('808001'));
         $this->assertTrue($input->readVarint64($var));
         if (PHP_INT_SIZE == 4) {
             $this->assertSame('16384', $var);
@@ -352,7 +355,7 @@
         $this->assertFalse($input->readVarint64($var));
 
         // Read two varint.
-        $input = new InputStream(hex2bin('808001808002'));
+        $input = new CodedInputStream(hex2bin('808001808002'));
         $this->assertTrue($input->readVarint64($var));
         if (PHP_INT_SIZE == 4) {
             $this->assertSame('16384', $var);
@@ -390,7 +393,7 @@
         );
 
         foreach ($testVals as $original => $encoded) {
-            $input = new InputStream(hex2bin($encoded));
+            $input = new CodedInputStream(hex2bin($encoded));
             $this->assertTrue($input->readVarint64($var));
             $this->assertEquals($original, $var);
         }
@@ -401,25 +404,25 @@
         $var = 0;
 
         // Empty buffer.
-        $input = new InputStream(hex2bin(''));
+        $input = new CodedInputStream(hex2bin(''));
         $this->assertFalse($input->readVarint32($var));
 
         // The largest varint is 10 bytes long.
-        $input = new InputStream(hex2bin('8080808080808080808001'));
+        $input = new CodedInputStream(hex2bin('8080808080808080808001'));
         $this->assertFalse($input->readVarint32($var));
 
         // Corrupted varint.
-        $input = new InputStream(hex2bin('808080'));
+        $input = new CodedInputStream(hex2bin('808080'));
         $this->assertFalse($input->readVarint32($var));
 
         // Normal case.
-        $input = new InputStream(hex2bin('808001'));
+        $input = new CodedInputStream(hex2bin('808001'));
         $this->assertTrue($input->readVarint32($var));
         $this->assertSame(16384, $var);
         $this->assertFalse($input->readVarint32($var));
 
         // Read two varint.
-        $input = new InputStream(hex2bin('808001808002'));
+        $input = new CodedInputStream(hex2bin('808001808002'));
         $this->assertTrue($input->readVarint32($var));
         $this->assertSame(16384, $var);
         $this->assertTrue($input->readVarint32($var));
@@ -427,7 +430,7 @@
         $this->assertFalse($input->readVarint32($var));
 
         // Read a 64-bit integer. High-order bits should be discarded.
-        $input = new InputStream(hex2bin('808081808001'));
+        $input = new CodedInputStream(hex2bin('808081808001'));
         $this->assertTrue($input->readVarint32($var));
         $this->assertSame(16384, $var);
         $this->assertFalse($input->readVarint32($var));
@@ -435,7 +438,7 @@
 
     public function testReadTag()
     {
-        $input = new InputStream(hex2bin('808001'));
+        $input = new CodedInputStream(hex2bin('808001'));
         $tag = $input->readTag();
         $this->assertSame(16384, $tag);
         $tag = $input->readTag();
@@ -444,7 +447,7 @@
 
     public function testPushPopLimit()
     {
-        $input = new InputStream(hex2bin('808001'));
+        $input = new CodedInputStream(hex2bin('808001'));
         $old_limit = $input->pushLimit(0);
         $tag = $input->readTag();
         $this->assertSame(0, $tag);
@@ -455,7 +458,7 @@
 
     public function testReadRaw()
     {
-        $input = new InputStream(hex2bin('808001'));
+        $input = new CodedInputStream(hex2bin('808001'));
         $buffer = null;
 
         $this->assertTrue($input->readRaw(3, $buffer));
@@ -466,33 +469,33 @@
 
     public function testWriteVarint32()
     {
-        $output = new OutputStream(3);
-        $output->writeVarint32(16384);
+        $output = new CodedOutputStream(3);
+        $output->writeVarint32(16384, true);
         $this->assertSame(hex2bin('808001'), $output->getData());
 
         // Negative numbers are padded to be compatible with int64.
-        $output = new OutputStream(10);
-        $output->writeVarint32(-43);
+        $output = new CodedOutputStream(10);
+        $output->writeVarint32(-43, false);
         $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData());
     }
 
     public function testWriteVarint64()
     {
-        $output = new OutputStream(10);
+        $output = new CodedOutputStream(10);
         $output->writeVarint64(-43);
         $this->assertSame(hex2bin('D5FFFFFFFFFFFFFFFF01'), $output->getData());
     }
 
     public function testWriteLittleEndian32()
     {
-        $output = new OutputStream(4);
+        $output = new CodedOutputStream(4);
         $output->writeLittleEndian32(46);
         $this->assertSame(hex2bin('2E000000'), $output->getData());
     }
 
     public function testWriteLittleEndian64()
     {
-        $output = new OutputStream(8);
+        $output = new CodedOutputStream(8);
         $output->writeLittleEndian64(47);
         $this->assertSame(hex2bin('2F00000000000000'), $output->getData());
     }
diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto
index 583bf8e..56cba44 100644
--- a/php/tests/proto/test.proto
+++ b/php/tests/proto/test.proto
@@ -2,6 +2,8 @@
 
 import 'proto/test_include.proto';
 import 'proto/test_no_namespace.proto';
+import 'proto/test_php_namespace.proto';
+import 'proto/test_empty_php_namespace.proto';
 import 'proto/test_prefix.proto';
 
 package foo;
@@ -174,3 +176,26 @@
 message TestIncludePrefixMessage {
   TestPrefix prefix_message = 1;
 }
+
+message TestIncludeNamespaceMessage {
+  TestNamespace namespace_message = 1;
+  TestEmptyNamespace empty_namespace_message = 2;
+}
+
+// This will cause upb fields not ordered by the order in the generated code.
+message TestRandomFieldOrder {
+  int64 tag13 = 150;
+  string tag14 = 160;
+}
+
+message TestReverseFieldOrder {
+  repeated int32 a = 2;
+  string b = 1;
+}
+
+message testLowerCaseMessage {
+}
+
+enum testLowerCaseEnum {
+  VALUE = 0;
+}
diff --git a/php/tests/proto/test_descriptors.proto b/php/tests/proto/test_descriptors.proto
new file mode 100644
index 0000000..d42aec7
--- /dev/null
+++ b/php/tests/proto/test_descriptors.proto
@@ -0,0 +1,35 @@
+syntax = "proto3";
+
+package descriptors;
+
+message TestDescriptorsMessage {
+  int32 optional_int32 = 1;
+  TestDescriptorsEnum optional_enum = 16;
+  Sub optional_message = 17;
+
+  // Repeated
+  repeated int32 repeated_int32 = 31;
+  repeated Sub repeated_message = 47;
+
+  oneof my_oneof {
+    int32 oneof_int32    = 51;
+  }
+
+  map<int32, EnumSub> map_int32_enum = 71;
+
+  message Sub {
+    int32 a = 1;
+    repeated int32 b = 2;
+  }
+
+  enum EnumSub {
+    ZERO = 0;
+    ONE = 1;
+  }
+}
+
+enum TestDescriptorsEnum {
+  ZERO = 0;
+  ONE  = 1;
+}
+
diff --git a/php/tests/proto/test_empty_php_namespace.proto b/php/tests/proto/test_empty_php_namespace.proto
new file mode 100644
index 0000000..7b4bc74
--- /dev/null
+++ b/php/tests/proto/test_empty_php_namespace.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+
+package foo;
+option php_namespace = "";
+
+message TestEmptyNamespace {
+  int32 a = 1;
+}
diff --git a/php/tests/proto/test_php_namespace.proto b/php/tests/proto/test_php_namespace.proto
new file mode 100644
index 0000000..713187b
--- /dev/null
+++ b/php/tests/proto/test_php_namespace.proto
@@ -0,0 +1,8 @@
+syntax = "proto3";
+
+package foo;
+option php_namespace = "Php\\Test";
+
+message TestNamespace {
+  int32 a = 1;
+}
diff --git a/php/tests/proto/test_service.proto b/php/tests/proto/test_service.proto
new file mode 100644
index 0000000..a03dbc4
--- /dev/null
+++ b/php/tests/proto/test_service.proto
@@ -0,0 +1,18 @@
+syntax = "proto3";
+
+package foo;
+
+option php_generic_services = true;
+
+service Greeter {
+  rpc SayHello (HelloRequest) returns (HelloReply) {}
+  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
+}
+
+message HelloRequest {
+  string name = 1;
+}
+
+message HelloReply {
+  string message = 1;
+}
diff --git a/php/tests/proto/test_service_namespace.proto b/php/tests/proto/test_service_namespace.proto
new file mode 100644
index 0000000..719aa48
--- /dev/null
+++ b/php/tests/proto/test_service_namespace.proto
@@ -0,0 +1,13 @@
+syntax = "proto3";
+
+import "proto/test_service.proto";
+
+package foo;
+
+option php_generic_services = true;
+option php_namespace = "Bar";
+
+service OtherGreeter {
+  rpc SayHello (HelloRequest) returns (HelloReply) {}
+  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
+}
diff --git a/php/tests/test.sh b/php/tests/test.sh
index 69849ab..c35372d 100755
--- a/php/tests/test.sh
+++ b/php/tests/test.sh
@@ -8,7 +8,7 @@
 phpize && ./configure CFLAGS='-g -O0' && make
 popd
 
-tests=( array_test.php encode_decode_test.php generated_class_test.php map_field_test.php well_known_test.php )
+tests=( array_test.php encode_decode_test.php generated_class_test.php generated_phpdoc_test.php map_field_test.php well_known_test.php generated_service_test.php descriptors_test.php )
 
 for t in "${tests[@]}"
 do
diff --git a/php/tests/test_base.php b/php/tests/test_base.php
index 67048f4..dc5e73f 100644
--- a/php/tests/test_base.php
+++ b/php/tests/test_base.php
@@ -19,6 +19,8 @@
 
     public function expectFields(TestMessage $m)
     {
+        $this->assertSame(-42,  $m->getOptionalInt32());
+        $this->assertSame(42,  $m->getOptionalUint32());
         $this->assertSame(-44,  $m->getOptionalSint32());
         $this->assertSame(46,   $m->getOptionalFixed32());
         $this->assertSame(-46,  $m->getOptionalSfixed32());
@@ -27,6 +29,7 @@
         $this->assertSame(true, $m->getOptionalBool());
         $this->assertSame('a',  $m->getOptionalString());
         $this->assertSame('b',  $m->getOptionalBytes());
+        $this->assertSame(TestEnum::ONE, $m->getOptionalEnum());
         $this->assertSame(33,   $m->getOptionalMessage()->getA());
         if (PHP_INT_SIZE == 4) {
             $this->assertSame('-43',  $m->getOptionalInt64());
diff --git a/php/tests/test_util.php b/php/tests/test_util.php
index 9dbcbb6..c8afdd3 100644
--- a/php/tests/test_util.php
+++ b/php/tests/test_util.php
@@ -71,61 +71,61 @@
         $m->setOptionalMessage($sub);
         $m->getOptionalMessage()->SetA(33);
 
-        $m->getRepeatedInt32()    []= -42;
-        $m->getRepeatedInt64()    []= -43;
-        $m->getRepeatedUint32()   []=  42;
-        $m->getRepeatedUint64()   []=  43;
-        $m->getRepeatedSint32()   []= -44;
-        $m->getRepeatedSint64()   []= -45;
-        $m->getRepeatedFixed32()  []=  46;
-        $m->getRepeatedFixed64()  []=  47;
-        $m->getRepeatedSfixed32() []= -46;
-        $m->getRepeatedSfixed64() []= -47;
-        $m->getRepeatedFloat()    []= 1.5;
-        $m->getRepeatedDouble()   []= 1.6;
-        $m->getRepeatedBool()     []= true;
-        $m->getRepeatedString()   []= 'a';
-        $m->getRepeatedBytes()    []= 'b';
-        $m->getRepeatedEnum()     []= TestEnum::ZERO;
-        $m->getRepeatedMessage()  []= new TestMessage_Sub();
+        self::appendHelper($m, 'RepeatedInt32',    -42);
+        self::appendHelper($m, 'RepeatedInt64',    -43);
+        self::appendHelper($m, 'RepeatedUint32',    42);
+        self::appendHelper($m, 'RepeatedUint64',    43);
+        self::appendHelper($m, 'RepeatedSint32',   -44);
+        self::appendHelper($m, 'RepeatedSint64',   -45);
+        self::appendHelper($m, 'RepeatedFixed32',   46);
+        self::appendHelper($m, 'RepeatedFixed64',   47);
+        self::appendHelper($m, 'RepeatedSfixed32', -46);
+        self::appendHelper($m, 'RepeatedSfixed64', -47);
+        self::appendHelper($m, 'RepeatedFloat',    1.5);
+        self::appendHelper($m, 'RepeatedDouble',   1.6);
+        self::appendHelper($m, 'RepeatedBool',     true);
+        self::appendHelper($m, 'RepeatedString',   'a');
+        self::appendHelper($m, 'RepeatedBytes',    'b');
+        self::appendHelper($m, 'RepeatedEnum',     TestEnum::ZERO);
+        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
         $m->getRepeatedMessage()[0]->setA(34);
 
-        $m->getRepeatedInt32()    []= -52;
-        $m->getRepeatedInt64()    []= -53;
-        $m->getRepeatedUint32()   []=  52;
-        $m->getRepeatedUint64()   []=  53;
-        $m->getRepeatedSint32()   []= -54;
-        $m->getRepeatedSint64()   []= -55;
-        $m->getRepeatedFixed32()  []=  56;
-        $m->getRepeatedFixed64()  []=  57;
-        $m->getRepeatedSfixed32() []= -56;
-        $m->getRepeatedSfixed64() []= -57;
-        $m->getRepeatedFloat()    []= 2.5;
-        $m->getRepeatedDouble()   []= 2.6;
-        $m->getRepeatedBool()     []= false;
-        $m->getRepeatedString()   []= 'c';
-        $m->getRepeatedBytes()    []= 'd';
-        $m->getRepeatedEnum()     []= TestEnum::ONE;
-        $m->getRepeatedMessage()  []= new TestMessage_Sub();
+        self::appendHelper($m, 'RepeatedInt32',    -52);
+        self::appendHelper($m, 'RepeatedInt64',    -53);
+        self::appendHelper($m, 'RepeatedUint32',    52);
+        self::appendHelper($m, 'RepeatedUint64',    53);
+        self::appendHelper($m, 'RepeatedSint32',   -54);
+        self::appendHelper($m, 'RepeatedSint64',   -55);
+        self::appendHelper($m, 'RepeatedFixed32',   56);
+        self::appendHelper($m, 'RepeatedFixed64',   57);
+        self::appendHelper($m, 'RepeatedSfixed32', -56);
+        self::appendHelper($m, 'RepeatedSfixed64', -57);
+        self::appendHelper($m, 'RepeatedFloat',    2.5);
+        self::appendHelper($m, 'RepeatedDouble',   2.6);
+        self::appendHelper($m, 'RepeatedBool',     false);
+        self::appendHelper($m, 'RepeatedString',   'c');
+        self::appendHelper($m, 'RepeatedBytes',    'd');
+        self::appendHelper($m, 'RepeatedEnum',     TestEnum::ONE);
+        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
         $m->getRepeatedMessage()[1]->SetA(35);
 
-        $m->getMapInt32Int32()[-62] = -62;
-        $m->getMapInt64Int64()[-63] = -63;
-        $m->getMapUint32Uint32()[62] = 62;
-        $m->getMapUint64Uint64()[63] = 63;
-        $m->getMapSint32Sint32()[-64] = -64;
-        $m->getMapSint64Sint64()[-65] = -65;
-        $m->getMapFixed32Fixed32()[66] = 66;
-        $m->getMapFixed64Fixed64()[67] = 67;
-        $m->getMapSfixed32Sfixed32()[-68] = -68;
-        $m->getMapSfixed64Sfixed64()[-69] = -69;
-        $m->getMapInt32Float()[1] = 3.5;
-        $m->getMapInt32Double()[1] = 3.6;
-        $m->getMapBoolBool()[true] = true;
-        $m->getMapStringString()['e'] = 'e';
-        $m->getMapInt32Bytes()[1] = 'f';
-        $m->getMapInt32Enum()[1] = TestEnum::ONE;
-        $m->getMapInt32Message()[1] = new TestMessage_Sub();
+        self::kvUpdateHelper($m, 'MapInt32Int32', -62, -62);
+        self::kvUpdateHelper($m, 'MapInt64Int64', -63, -63);
+        self::kvUpdateHelper($m, 'MapUint32Uint32', 62, 62);
+        self::kvUpdateHelper($m, 'MapUint64Uint64', 63, 63);
+        self::kvUpdateHelper($m, 'MapSint32Sint32', -64, -64);
+        self::kvUpdateHelper($m, 'MapSint64Sint64', -65, -65);
+        self::kvUpdateHelper($m, 'MapFixed32Fixed32', 66, 66);
+        self::kvUpdateHelper($m, 'MapFixed64Fixed64', 67, 67);
+        self::kvUpdateHelper($m, 'MapSfixed32Sfixed32', -68, -68);
+        self::kvUpdateHelper($m, 'MapSfixed64Sfixed64', -69, -69);
+        self::kvUpdateHelper($m, 'MapInt32Float', 1, 3.5);
+        self::kvUpdateHelper($m, 'MapInt32Double', 1, 3.6);
+        self::kvUpdateHelper($m, 'MapBoolBool', true, true);
+        self::kvUpdateHelper($m, 'MapStringString', 'e', 'e');
+        self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'f');
+        self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::ONE);
+        self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub());
         $m->getMapInt32Message()[1]->SetA(36);
     }
 
@@ -152,61 +152,61 @@
         $m->setOptionalMessage($sub);
         $m->getOptionalMessage()->SetA(133);
 
-        $m->getRepeatedInt32()    []= -142;
-        $m->getRepeatedInt64()    []= -143;
-        $m->getRepeatedUint32()   []=  142;
-        $m->getRepeatedUint64()   []=  143;
-        $m->getRepeatedSint32()   []= -144;
-        $m->getRepeatedSint64()   []= -145;
-        $m->getRepeatedFixed32()  []=  146;
-        $m->getRepeatedFixed64()  []=  147;
-        $m->getRepeatedSfixed32() []= -146;
-        $m->getRepeatedSfixed64() []= -147;
-        $m->getRepeatedFloat()    []= 11.5;
-        $m->getRepeatedDouble()   []= 11.6;
-        $m->getRepeatedBool()     []= false;
-        $m->getRepeatedString()   []= 'aa';
-        $m->getRepeatedBytes()    []= 'bb';
-        $m->getRepeatedEnum()     []= TestEnum::TWO;
-        $m->getRepeatedMessage()  []= new TestMessage_Sub();
+        self::appendHelper($m, 'RepeatedInt32',    -142);
+        self::appendHelper($m, 'RepeatedInt64',    -143);
+        self::appendHelper($m, 'RepeatedUint32',    142);
+        self::appendHelper($m, 'RepeatedUint64',    143);
+        self::appendHelper($m, 'RepeatedSint32',   -144);
+        self::appendHelper($m, 'RepeatedSint64',   -145);
+        self::appendHelper($m, 'RepeatedFixed32',   146);
+        self::appendHelper($m, 'RepeatedFixed64',   147);
+        self::appendHelper($m, 'RepeatedSfixed32', -146);
+        self::appendHelper($m, 'RepeatedSfixed64', -147);
+        self::appendHelper($m, 'RepeatedFloat',    11.5);
+        self::appendHelper($m, 'RepeatedDouble',   11.6);
+        self::appendHelper($m, 'RepeatedBool',     false);
+        self::appendHelper($m, 'RepeatedString',   'aa');
+        self::appendHelper($m, 'RepeatedBytes',    'bb');
+        self::appendHelper($m, 'RepeatedEnum',     TestEnum::TWO);
+        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
         $m->getRepeatedMessage()[0]->setA(134);
 
-        $m->getMapInt32Int32()[-62] = -162;
-        $m->getMapInt64Int64()[-63] = -163;
-        $m->getMapUint32Uint32()[62] = 162;
-        $m->getMapUint64Uint64()[63] = 163;
-        $m->getMapSint32Sint32()[-64] = -164;
-        $m->getMapSint64Sint64()[-65] = -165;
-        $m->getMapFixed32Fixed32()[66] = 166;
-        $m->getMapFixed64Fixed64()[67] = 167;
-        $m->getMapSfixed32Sfixed32()[-68] = -168;
-        $m->getMapSfixed64Sfixed64()[-69] = -169;
-        $m->getMapInt32Float()[1] = 13.5;
-        $m->getMapInt32Double()[1] = 13.6;
-        $m->getMapBoolBool()[true] = false;
-        $m->getMapStringString()['e'] = 'ee';
-        $m->getMapInt32Bytes()[1] = 'ff';
-        $m->getMapInt32Enum()[1] = TestEnum::TWO;
-        $m->getMapInt32Message()[1] = new TestMessage_Sub();
+        self::kvUpdateHelper($m, 'MapInt32Int32', -62, -162);
+        self::kvUpdateHelper($m, 'MapInt64Int64', -63, -163);
+        self::kvUpdateHelper($m, 'MapUint32Uint32', 62, 162);
+        self::kvUpdateHelper($m, 'MapUint64Uint64', 63, 163);
+        self::kvUpdateHelper($m, 'MapSint32Sint32', -64, -164);
+        self::kvUpdateHelper($m, 'MapSint64Sint64', -65, -165);
+        self::kvUpdateHelper($m, 'MapFixed32Fixed32', 66, 166);
+        self::kvUpdateHelper($m, 'MapFixed64Fixed64', 67, 167);
+        self::kvUpdateHelper($m, 'MapSfixed32Sfixed32', -68, -168);
+        self::kvUpdateHelper($m, 'MapSfixed64Sfixed64', -69, -169);
+        self::kvUpdateHelper($m, 'MapInt32Float', 1, 13.5);
+        self::kvUpdateHelper($m, 'MapInt32Double', 1, 13.6);
+        self::kvUpdateHelper($m, 'MapBoolBool', true, false);
+        self::kvUpdateHelper($m, 'MapStringString', 'e', 'ee');
+        self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'ff');
+        self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::TWO);
+        self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub());
         $m->getMapInt32Message()[1]->SetA(136);
 
-        $m->getMapInt32Int32()[-162] = -162;
-        $m->getMapInt64Int64()[-163] = -163;
-        $m->getMapUint32Uint32()[162] = 162;
-        $m->getMapUint64Uint64()[163] = 163;
-        $m->getMapSint32Sint32()[-164] = -164;
-        $m->getMapSint64Sint64()[-165] = -165;
-        $m->getMapFixed32Fixed32()[166] = 166;
-        $m->getMapFixed64Fixed64()[167] = 167;
-        $m->getMapSfixed32Sfixed32()[-168] = -168;
-        $m->getMapSfixed64Sfixed64()[-169] = -169;
-        $m->getMapInt32Float()[2] = 13.5;
-        $m->getMapInt32Double()[2] = 13.6;
-        $m->getMapBoolBool()[false] = false;
-        $m->getMapStringString()['ee'] = 'ee';
-        $m->getMapInt32Bytes()[2] = 'ff';
-        $m->getMapInt32Enum()[2] = TestEnum::TWO;
-        $m->getMapInt32Message()[2] = new TestMessage_Sub();
+        self::kvUpdateHelper($m, 'MapInt32Int32', -162, -162);
+        self::kvUpdateHelper($m, 'MapInt64Int64', -163, -163);
+        self::kvUpdateHelper($m, 'MapUint32Uint32', 162, 162);
+        self::kvUpdateHelper($m, 'MapUint64Uint64', 163, 163);
+        self::kvUpdateHelper($m, 'MapSint32Sint32', -164, -164);
+        self::kvUpdateHelper($m, 'MapSint64Sint64', -165, -165);
+        self::kvUpdateHelper($m, 'MapFixed32Fixed32', 166, 166);
+        self::kvUpdateHelper($m, 'MapFixed64Fixed64', 167, 167);
+        self::kvUpdateHelper($m, 'MapSfixed32Sfixed32', -168, -168);
+        self::kvUpdateHelper($m, 'MapSfixed64Sfixed64', -169, -169);
+        self::kvUpdateHelper($m, 'MapInt32Float', 2, 13.5);
+        self::kvUpdateHelper($m, 'MapInt32Double', 2, 13.6);
+        self::kvUpdateHelper($m, 'MapBoolBool', false, false);
+        self::kvUpdateHelper($m, 'MapStringString', 'ee', 'ee');
+        self::kvUpdateHelper($m, 'MapInt32Bytes', 2, 'ff');
+        self::kvUpdateHelper($m, 'MapInt32Enum', 2, TestEnum::TWO);
+        self::kvUpdateHelper($m, 'MapInt32Message', 2, new TestMessage_Sub());
         $m->getMapInt32Message()[2]->SetA(136);
     }
 
@@ -395,34 +395,34 @@
 
     public static function setTestPackedMessage($m)
     {
-        $m->getRepeatedInt32()[] = -42;
-        $m->getRepeatedInt32()[] = -52;
-        $m->getRepeatedInt64()[] = -43;
-        $m->getRepeatedInt64()[] = -53;
-        $m->getRepeatedUint32()[] = 42;
-        $m->getRepeatedUint32()[] = 52;
-        $m->getRepeatedUint64()[] = 43;
-        $m->getRepeatedUint64()[] = 53;
-        $m->getRepeatedSint32()[] = -44;
-        $m->getRepeatedSint32()[] = -54;
-        $m->getRepeatedSint64()[] = -45;
-        $m->getRepeatedSint64()[] = -55;
-        $m->getRepeatedFixed32()[] = 46;
-        $m->getRepeatedFixed32()[] = 56;
-        $m->getRepeatedFixed64()[] = 47;
-        $m->getRepeatedFixed64()[] = 57;
-        $m->getRepeatedSfixed32()[] = -46;
-        $m->getRepeatedSfixed32()[] = -56;
-        $m->getRepeatedSfixed64()[] = -47;
-        $m->getRepeatedSfixed64()[] = -57;
-        $m->getRepeatedFloat()[] = 1.5;
-        $m->getRepeatedFloat()[] = 2.5;
-        $m->getRepeatedDouble()[] = 1.6;
-        $m->getRepeatedDouble()[] = 2.6;
-        $m->getRepeatedBool()[] = true;
-        $m->getRepeatedBool()[] = false;
-        $m->getRepeatedEnum()[] = TestEnum::ONE;
-        $m->getRepeatedEnum()[] = TestEnum::ZERO;
+        self::appendHelper($m, 'RepeatedInt32', -42);
+        self::appendHelper($m, 'RepeatedInt32', -52);
+        self::appendHelper($m, 'RepeatedInt64', -43);
+        self::appendHelper($m, 'RepeatedInt64', -53);
+        self::appendHelper($m, 'RepeatedUint32', 42);
+        self::appendHelper($m, 'RepeatedUint32', 52);
+        self::appendHelper($m, 'RepeatedUint64', 43);
+        self::appendHelper($m, 'RepeatedUint64', 53);
+        self::appendHelper($m, 'RepeatedSint32', -44);
+        self::appendHelper($m, 'RepeatedSint32', -54);
+        self::appendHelper($m, 'RepeatedSint64', -45);
+        self::appendHelper($m, 'RepeatedSint64', -55);
+        self::appendHelper($m, 'RepeatedFixed32', 46);
+        self::appendHelper($m, 'RepeatedFixed32', 56);
+        self::appendHelper($m, 'RepeatedFixed64', 47);
+        self::appendHelper($m, 'RepeatedFixed64', 57);
+        self::appendHelper($m, 'RepeatedSfixed32', -46);
+        self::appendHelper($m, 'RepeatedSfixed32', -56);
+        self::appendHelper($m, 'RepeatedSfixed64', -47);
+        self::appendHelper($m, 'RepeatedSfixed64', -57);
+        self::appendHelper($m, 'RepeatedFloat', 1.5);
+        self::appendHelper($m, 'RepeatedFloat', 2.5);
+        self::appendHelper($m, 'RepeatedDouble', 1.6);
+        self::appendHelper($m, 'RepeatedDouble', 2.6);
+        self::appendHelper($m, 'RepeatedBool', true);
+        self::appendHelper($m, 'RepeatedBool', false);
+        self::appendHelper($m, 'RepeatedEnum', TestEnum::ONE);
+        self::appendHelper($m, 'RepeatedEnum', TestEnum::ZERO);
     }
 
     public static function assertTestPackedMessage($m)
@@ -524,4 +524,24 @@
             "B80601B80600"
         );
     }
+
+    private static function appendHelper($obj, $func_suffix, $value)
+    {
+        $getter_function = 'get'.$func_suffix;
+        $setter_function = 'set'.$func_suffix;
+
+        $arr = $obj->$getter_function();
+        $arr[] = $value;
+        $obj->$setter_function($arr);
+    }
+
+    private static function kvUpdateHelper($obj, $func_suffix, $key, $value)
+    {
+        $getter_function = 'get'.$func_suffix;
+        $setter_function = 'set'.$func_suffix;
+
+        $arr = $obj->$getter_function();
+        $arr[$key] = $value;
+        $obj->$setter_function($arr);
+    }
 }
diff --git a/php/tests/undefined_test.php b/php/tests/undefined_test.php
new file mode 100644
index 0000000..dc6b708
--- /dev/null
+++ b/php/tests/undefined_test.php
@@ -0,0 +1,920 @@
+<?php
+
+require_once('test_util.php');
+
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBType;
+use Foo\TestMessage;
+use Foo\TestMessage_Sub;
+
+class UndefinedTest extends PHPUnit_Framework_TestCase
+{
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32AppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32SetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[] = 0;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32AppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32SetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[] = 0;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32AppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT32);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32SetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT32);
+        $arr[] = 0;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32AppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT32);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32SetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT32);
+        $arr[] = 0;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64AppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::INT64);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64SetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::INT64);
+        $arr[] = 0;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64AppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::INT64);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64SetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::INT64);
+        $arr[] = 0;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64AppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT64);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64SetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT64);
+        $arr[] = 0;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64AppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT64);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64SetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::UINT64);
+        $arr[] = 0;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testFloatAppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::FLOAT);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testFloatSetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::FLOAT);
+        $arr[] = 0.0;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testFloatAppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::FLOAT);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testFloatSetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::FLOAT);
+        $arr[] = 0.0;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleAppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::DOUBLE);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleSetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::DOUBLE);
+        $arr[] = 0.0;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleAppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::DOUBLE);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleSetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::DOUBLE);
+        $arr[] = 0.0;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testBoolAppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::BOOL);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testBoolSetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::BOOL);
+        $arr[] = true;
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringAppendMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::STRING);
+        $arr[] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringSetMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::STRING);
+        $arr[] = 'abc';
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringAppendInvalidUTF8Fail()
+    {
+        $arr = new RepeatedField(GPBType::STRING);
+        $hex = hex2bin("ff");
+        $arr[] = $hex;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringSetInvalidUTF8Fail()
+    {
+        $arr = new RepeatedField(GPBType::STRING);
+        $arr[] = 'abc';
+        $hex = hex2bin("ff");
+        $arr[0] = $hex;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageAppendIntFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr[] = 1;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetIntFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr[] = new TestMessage_Sub;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageAppendStringFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr[] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetStringFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr[] = new TestMessage_Sub;
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageAppendOtherMessageFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr[] = new TestMessage;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageAppendNullFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $null = null;
+        $arr[] = $null;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetNullFail()
+    {
+        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr[] = new TestMessage_Sub();
+        $null = null;
+        $arr[0] = $null;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testRemoveMiddleFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+
+        $arr[] = 0;
+        $arr[] = 1;
+        $arr[] = 2;
+        $this->assertSame(3, count($arr));
+
+        unset($arr[1]);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testRemoveEmptyFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+
+        unset($arr[0]);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageOffsetFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[] = 0;
+        $arr[new TestMessage_Sub()] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringOffsetFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[] = 0;
+        $arr['abc'] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testSetNonExistedOffsetFail()
+    {
+        $arr = new RepeatedField(GPBType::INT32);
+        $arr[0] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32FieldInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalInt32(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32FieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalInt32('abc');
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32FieldInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalUint32(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32FieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalUint32('abc');
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64FieldInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalInt64(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64FieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalInt64('abc');
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64FieldInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalUint64(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64FieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalUint64('abc');
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testFloatFieldInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalFloat(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testFloatFieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalFloat('abc');
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleFieldInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalDouble(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleFieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalDouble('abc');
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testBoolFieldInvalidStringFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalBool(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringFieldInvalidUTF8Fail()
+    {
+        $m = new TestMessage();
+        $hex = hex2bin("ff");
+        $m->setOptionalString($hex);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageFieldWrongTypeFail()
+    {
+        $m = new TestMessage();
+        $a = 1;
+        $m->setOptionalMessage($a);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageFieldWrongClassFail()
+    {
+        $m = new TestMessage();
+        $m->setOptionalMessage(new TestMessage());
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testRepeatedFieldWrongTypeFail()
+    {
+        $m = new TestMessage();
+        $a = 1;
+        $m->setRepeatedInt32($a);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testRepeatedFieldWrongObjectFail()
+    {
+        $m = new TestMessage();
+        $m->setRepeatedInt32($m);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testRepeatedFieldWrongRepeatedTypeFail()
+    {
+        $m = new TestMessage();
+
+        $repeated_int32 = new RepeatedField(GPBType::UINT32);
+        $m->setRepeatedInt32($repeated_int32);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testRepeatedFieldWrongRepeatedMessageClassFail()
+    {
+        $m = new TestMessage();
+
+        $repeated_message = new RepeatedField(GPBType::MESSAGE,
+                                              TestMessage::class);
+        $m->setRepeatedMessage($repeated_message);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMapFieldWrongTypeFail()
+    {
+        $m = new TestMessage();
+        $a = 1;
+        $m->setMapInt32Int32($a);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMapFieldWrongObjectFail()
+    {
+        $m = new TestMessage();
+        $m->setMapInt32Int32($m);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMapFieldWrongRepeatedTypeFail()
+    {
+        $m = new TestMessage();
+
+        $map_uint32_uint32 = new MapField(GPBType::UINT32, GPBType::UINT32);
+        $m->setMapInt32Int32($map_uint32_uint32);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMapFieldWrongRepeatedMessageClassFail()
+    {
+        $m = new TestMessage();
+
+        $map_int32_message = new MapField(GPBType::INT32,
+                                          GPBType::MESSAGE,
+                                          TestMessage::class);
+        $m->setMapInt32Message($map_int32_message);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageMergeFromInvalidTypeFail()
+    {
+        $m = new TestMessage();
+        $n = new TestMessage_Sub();
+        $m->mergeFrom($n);
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32SetStringKeyFail()
+    {
+        $arr = new MapField(GPBType::INT32, GPBType::INT32);
+        $arr['abc'] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32SetStringValueFail()
+    {
+        $arr = new MapField(GPBType::INT32, GPBType::INT32);
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32SetMessageKeyFail()
+    {
+        $arr = new MapField(GPBType::INT32, GPBType::INT32);
+        $arr[new TestMessage_Sub()] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt32SetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::INT32, GPBType::INT32);
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32SetStringKeyFail()
+    {
+        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+        $arr['abc'] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32SetStringValueFail()
+    {
+        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32SetMessageKeyFail()
+    {
+        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+        $arr[new TestMessage_Sub()] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint32SetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64SetStringKeyFail()
+    {
+        $arr = new MapField(GPBType::INT64, GPBType::INT64);
+        $arr['abc'] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64SetStringValueFail()
+    {
+        $arr = new MapField(GPBType::INT64, GPBType::INT64);
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64SetMessageKeyFail()
+    {
+        $arr = new MapField(GPBType::INT64, GPBType::INT64);
+        $arr[new TestMessage_Sub()] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testInt64SetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::INT64, GPBType::INT64);
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64SetStringKeyFail()
+    {
+        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+        $arr['abc'] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64SetStringValueFail()
+    {
+        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64SetMessageKeyFail()
+    {
+        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+        $arr[new TestMessage_Sub()] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testUint64SetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleSetStringValueFail()
+    {
+        $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
+        $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testDoubleSetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
+        $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testBoolSetMessageKeyFail()
+    {
+        $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
+        $arr[new TestMessage_Sub()] = true;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testBoolSetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
+        $arr[true] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringSetInvalidUTF8KeyFail()
+    {
+        $arr = new MapField(GPBType::STRING, GPBType::STRING);
+        $arr[hex2bin("ff")] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringSetInvalidUTF8ValueFail()
+    {
+        $arr = new MapField(GPBType::STRING, GPBType::STRING);
+        $arr['abc'] = hex2bin("ff");
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringSetMessageKeyFail()
+    {
+        $arr = new MapField(GPBType::STRING, GPBType::STRING);
+        $arr[new TestMessage_Sub()] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testStringSetMessageValueFail()
+    {
+        $arr = new MapField(GPBType::STRING, GPBType::STRING);
+        $arr['abc'] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetIntValueFail()
+    {
+       $arr =
+           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+       $arr[0] = 0;
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetStringValueFail()
+    {
+       $arr =
+           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+       $arr[0] = 'abc';
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetOtherMessageValueFail()
+    {
+       $arr =
+           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+       $arr[0] = new TestMessage_Sub();
+    }
+
+    /**
+     * @expectedException PHPUnit_Framework_Error
+     */
+    public function testMessageSetNullFail()
+    {
+       $arr =
+           new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
+       $null = NULL;
+       $arr[0] = $null;
+    }
+
+}
diff --git a/php/tests/well_known_test.php b/php/tests/well_known_test.php
index 0c2aec1..690ce5f 100644
--- a/php/tests/well_known_test.php
+++ b/php/tests/well_known_test.php
@@ -1,8 +1,18 @@
 <?php
 
-use Google\Protobuf\GPBEmpty;
+require_once('test_base.php');
+require_once('test_util.php');
 
-class WellKnownTest extends PHPUnit_Framework_TestCase {
+use Google\Protobuf\GPBEmpty;
+use Google\Protobuf\Any;
+use Google\Protobuf\Duration;
+use Google\Protobuf\Timestamp;
+
+use Foo\TestMessage;
+
+class NotMessage {}
+
+class WellKnownTest extends TestBase {
 
     public function testNone()
     {
@@ -14,4 +24,98 @@
         $msg = new TestImportDescriptorProto();
     }
 
+    public function testAny()
+    {
+        // Create embed message
+        $embed = new TestMessage();
+        $this->setFields($embed);
+        $data = $embed->serializeToString();
+
+        // Set any via normal setter.
+        $any = new Any();
+
+        $this->assertSame(
+            $any, $any->setTypeUrl("type.googleapis.com/foo.TestMessage"));
+        $this->assertSame("type.googleapis.com/foo.TestMessage",
+                          $any->getTypeUrl());
+
+        $this->assertSame($any, $any->setValue($data));
+        $this->assertSame($data, $any->getValue());
+
+        // Test unpack.
+        $msg = $any->unpack();
+        $this->assertTrue($msg instanceof TestMessage);
+        $this->expectFields($msg);
+
+        // Test pack.
+        $any = new Any();
+        $any->pack($embed);
+        $this->assertSame($data, $any->getValue());
+        $this->assertSame("type.googleapis.com/foo.TestMessage", $any->getTypeUrl());
+
+        // Test is.
+        $this->assertTrue($any->is(TestMessage::class));
+        $this->assertFalse($any->is(Any::class));
+    }
+
+    /**
+     * @expectedException Exception
+     */
+    public function testAnyUnpackInvalidTypeUrl()
+    {
+        $any = new Any();
+        $any->setTypeUrl("invalid");
+        $any->unpack();
+    }
+
+    /**
+     * @expectedException Exception
+     */
+    public function testAnyUnpackMessageNotAdded()
+    {
+        $any = new Any();
+        $any->setTypeUrl("type.googleapis.com/MessageNotAdded");
+        $any->unpack();
+    }
+
+    /**
+     * @expectedException Exception
+     */
+    public function testAnyUnpackDecodeError()
+    {
+        $any = new Any();
+        $any->setTypeUrl("type.googleapis.com/foo.TestMessage");
+        $any->setValue("abc");
+        $any->unpack();
+    }
+
+    public function testTimestamp()
+    {
+        $timestamp = new Timestamp();
+
+        $timestamp->setSeconds(1);
+        $timestamp->setNanos(2);
+        $this->assertEquals(1, $timestamp->getSeconds());
+        $this->assertSame(2, $timestamp->getNanos());
+
+        date_default_timezone_set('UTC');
+        $from = new DateTime('2011-01-01T15:03:01.012345UTC');
+        $timestamp->fromDateTime($from);
+        $this->assertEquals($from->format('U'), $timestamp->getSeconds());
+        $this->assertSame(0, $timestamp->getNanos());
+
+        $to = $timestamp->toDateTime();
+        $this->assertSame(\DateTime::class, get_class($to));
+        $this->assertSame($from->format('U'), $to->format('U'));
+    }
+
+    public function testDuration()
+    {
+        $duration = new Duration();
+
+        $duration->setSeconds(1);
+        $duration->setNanos(2);
+        $this->assertEquals(1, $duration->getSeconds());
+        $this->assertSame(2, $duration->getNanos());
+    }
 }
diff --git a/protobuf.bzl b/protobuf.bzl
index 9cb17f0..23380ba 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -245,9 +245,9 @@
   )
 
   if default_runtime and not default_runtime in cc_libs:
-    cc_libs += [default_runtime]
+    cc_libs = cc_libs + [default_runtime]
   if use_grpc_plugin:
-    cc_libs += ["//external:grpc_lib"]
+    cc_libs = cc_libs + ["//external:grpc_lib"]
 
   native.cc_library(
       name=name,
@@ -371,7 +371,7 @@
   )
 
   if default_runtime and not default_runtime in py_libs + deps:
-    py_libs += [default_runtime]
+    py_libs = py_libs + [default_runtime]
 
   native.py_library(
       name=name,
diff --git a/protoc-artifacts/Dockerfile b/protoc-artifacts/Dockerfile
index 5143b02..43e6863 100644
--- a/protoc-artifacts/Dockerfile
+++ b/protoc-artifacts/Dockerfile
@@ -15,9 +15,10 @@
 
 # Install Java 8
 RUN wget -q --no-cookies --no-check-certificate \
-    --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz" \
+    --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" \
+    "http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz" \
     -O - | tar xz -C /var/local
-ENV JAVA_HOME /var/local/jdk1.8.0_45
+ENV JAVA_HOME /var/local/jdk1.8.0_131
 ENV PATH $JAVA_HOME/bin:$PATH
 
 # Install Maven
@@ -30,7 +31,7 @@
 RUN bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-1.1.repo'
 RUN bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-1.1.repo > /etc/yum.repos.d/devtools-i386-1.1.repo"
 RUN sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-1.1.repo
-RUN yum install -y devtoolset-1.1 \
+RUN rpm --rebuilddb && yum install -y devtoolset-1.1 \
                    devtoolset-1.1-libstdc++-devel \
                    devtoolset-1.1-libstdc++-devel.i686
 
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
index 5062920..17eb77f 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -72,6 +72,7 @@
 - Windows (x86_32 and x86_64) with
  - Cygwin64 with MinGW compilers (x86_64)
  - MSYS with MinGW32 (x86_32)
+ - Cross compile in Linux with MinGW-w64 (x86_32, x86_64)
 - MacOSX (x86_32 and x86_64)
 
 As for MSYS2/MinGW64 for Windows: protoc will build, but it insists on
@@ -98,6 +99,9 @@
 A 32-bit artifact can be deployed from a 64-bit host with
 ``-Dos.detected.arch=x86_32``
 
+A windows artifact can be deployed from a linux machine with
+``-Dos.detected.name=windows``
+
 When you have done deployment for all platforms, go to
 https://oss.sonatype.org/#stagingRepositories, verify that the staging
 repository has all the binaries, close and release this repository.
@@ -173,5 +177,7 @@
  - Centos 6.6 (within Docker 1.6.1)
  - Ubuntu 14.04.2 64-bit
 - Windows x86_32: MSYS with ``mingw32-gcc-g++ 4.8.1-4`` on Windows 7 64-bit
+- Windows x86_32: Cross compile with ``i686-w64-mingw32-g++ 4.8.2`` on Ubuntu 14.04.2 64-bit
 - Windows x86_64: Cygwin64 with ``mingw64-x86_64-gcc-g++ 4.8.3-1`` on Windows 7 64-bit
+- Windows x86_64: Cross compile with ``x86_64-w64-mingw32-g++ 4.8.2`` on Ubuntu 14.04.2 64-bit
 - Mac OS X x86_32 and x86_64: Mac OS X 10.9.5
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index e31948e..57523a4 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/build-protoc.sh
@@ -185,8 +185,6 @@
     fi
   elif [[ "$OS" == windows ]]; then
     # Cross-compilation for Windows
-    # TODO(zhangkun83) MinGW 64 always adds dependency on libwinpthread-1.dll,
-    # which is undesirable for repository deployment.
     CONFIGURE_ARGS="$CONFIGURE_ARGS"
     if [[ "$ARCH" == x86_64 ]]; then
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=x86_64-w64-mingw32"
@@ -215,8 +213,11 @@
 
 # Statically link libgcc and libstdc++.
 # -s to produce stripped binary.
-# And they don't work under Mac.
-if [[ "$OS" != osx ]]; then
+if [[ "$OS" == windows ]]; then
+  # Also static link libpthread required by mingw64
+  LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -s"
+elif [[ "$OS" != osx ]]; then
+  # And they don't work under Mac.
   LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -s"
 fi
 
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
index 3c5e887..a124ed7 100755
--- a/protoc-artifacts/build-zip.sh
+++ b/protoc-artifacts/build-zip.sh
@@ -73,6 +73,10 @@
 Buffers in languages other than C++ but do not want to compile protoc
 themselves. To install, simply place this binary somewhere in your PATH.
 
+If you intend to use the included well known types then don't forget to
+copy the contents of the 'include' directory somewhere as well, for example
+into '/usr/local/include/'.
+
 Please refer to our official github site for more installation instructions:
   https://github.com/google/protobuf
 EOF
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index a06c999..d68709e 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -10,7 +10,7 @@
   </parent>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protoc</artifactId>
-  <version>3.3.0</version>
+  <version>3.4.0</version>
   <packaging>pom</packaging>
   <name>Protobuf Compiler</name>
   <description>
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py
index 53e9d50..e71b295 100755
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py
+++ b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/message_test.py
@@ -55,6 +55,11 @@
 from google.protobuf.internal import test_util
 from google.protobuf import message
 
+try:
+  cmp                                   # Python 2
+except NameError:
+  cmp = lambda x, y: (x > y) - (x < y)  # Python 3
+
 # Python pre-2.6 does not have isinf() or isnan() functions, so we have
 # to provide our own.
 def isnan(val):
diff --git a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py
index 6bf7bef..8267cd2 100755
--- a/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py
+++ b/python/compatibility_tests/v2.5.0/tests/google/protobuf/internal/text_format_test.py
@@ -370,9 +370,8 @@
   def testMergeBadExtension(self):
     message = unittest_pb2.TestAllExtensions()
     text = '[unknown_extension]: 8\n'
-    self.assertRaisesWithMessage(
+    self.assertRaises(
         text_format.ParseError,
-        '1:2 : Extension "unknown_extension" not registered.',
         text_format.Merge, text, message)
     message = unittest_pb2.TestAllTypes()
     self.assertRaisesWithMessage(
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index 0375d72..d26da0d 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -30,7 +30,7 @@
 
 # Copyright 2007 Google Inc. All Rights Reserved.
 
-__version__ = '3.3.0'
+__version__ = '3.4.0'
 
 if __name__ != '__main__':
   try:
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
index e1f2e3b..b1f3ca3 100755
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -406,6 +406,8 @@
 
     containing_oneof: (OneofDescriptor) If the field is a member of a oneof
       union, contains its descriptor. Otherwise, None.
+
+    file: (FileDescriptor) Reference to file descriptor.
   """
 
   # Must be consistent with C++ FieldDescriptor::Type enum in
@@ -490,7 +492,8 @@
     def __new__(cls, name, full_name, index, number, type, cpp_type, label,
                 default_value, message_type, enum_type, containing_type,
                 is_extension, extension_scope, options=None,
-                has_default_value=True, containing_oneof=None, json_name=None):
+                has_default_value=True, containing_oneof=None, json_name=None,
+                file=None):
       _message.Message._CheckCalledFromGeneratedFile()
       if is_extension:
         return _message.default_pool.FindExtensionByName(full_name)
@@ -500,7 +503,8 @@
   def __init__(self, name, full_name, index, number, type, cpp_type, label,
                default_value, message_type, enum_type, containing_type,
                is_extension, extension_scope, options=None,
-               has_default_value=True, containing_oneof=None, json_name=None):
+               has_default_value=True, containing_oneof=None, json_name=None,
+               file=None):
     """The arguments are as described in the description of FieldDescriptor
     attributes above.
 
@@ -511,6 +515,7 @@
     super(FieldDescriptor, self).__init__(options, 'FieldOptions')
     self.name = name
     self.full_name = full_name
+    self.file = file
     self._camelcase_name = None
     if json_name is None:
       self.json_name = _ToJsonName(name)
diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py
index 40bcdd7..eb45e12 100644
--- a/python/google/protobuf/descriptor_database.py
+++ b/python/google/protobuf/descriptor_database.py
@@ -134,8 +134,7 @@
   Yields:
     The fully qualified name found in the descriptor.
   """
-
-  message_name = '.'.join((package, desc_proto.name))
+  message_name = package + '.' + desc_proto.name if package else desc_proto.name
   yield message_name
   for nested_type in desc_proto.nested_type:
     for symbol in _ExtractSymbols(nested_type, message_name):
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index 29e9f1e..3dbe0fd 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -329,6 +329,11 @@
       pass
 
     try:
+      return self._service_descriptors[symbol].file
+    except KeyError:
+      pass
+
+    try:
       return self._FindFileContainingSymbolInDb(symbol)
     except KeyError:
       pass
@@ -344,7 +349,6 @@
       message = self.FindMessageTypeByName(message_name)
       assert message.extensions_by_name[extension_name]
       return message.file
-
     except KeyError:
       raise KeyError('Cannot find a file containing %s' % symbol)
 
@@ -557,7 +561,8 @@
 
       for index, extension_proto in enumerate(file_proto.extension):
         extension_desc = self._MakeFieldDescriptor(
-            extension_proto, file_proto.package, index, is_extension=True)
+            extension_proto, file_proto.package, index, file_descriptor,
+            is_extension=True)
         extension_desc.containing_type = self._GetTypeFromScope(
             file_descriptor.package, extension_proto.extendee, scope)
         self._SetFieldType(extension_proto, extension_desc,
@@ -623,10 +628,10 @@
     enums = [
         self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
         for enum in desc_proto.enum_type]
-    fields = [self._MakeFieldDescriptor(field, desc_name, index)
+    fields = [self._MakeFieldDescriptor(field, desc_name, index, file_desc)
               for index, field in enumerate(desc_proto.field)]
     extensions = [
-        self._MakeFieldDescriptor(extension, desc_name, index,
+        self._MakeFieldDescriptor(extension, desc_name, index, file_desc,
                                   is_extension=True)
         for index, extension in enumerate(desc_proto.extension)]
     oneofs = [
@@ -708,7 +713,7 @@
     return desc
 
   def _MakeFieldDescriptor(self, field_proto, message_name, index,
-                           is_extension=False):
+                           file_desc, is_extension=False):
     """Creates a field descriptor from a FieldDescriptorProto.
 
     For message and enum type fields, this method will do a look up
@@ -721,6 +726,7 @@
       field_proto: The proto describing the field.
       message_name: The name of the containing message.
       index: Index of the field
+      file_desc: The file containing the field descriptor.
       is_extension: Indication that this field is for an extension.
 
     Returns:
@@ -747,7 +753,8 @@
         default_value=None,
         is_extension=is_extension,
         extension_scope=None,
-        options=_OptionsOrNone(field_proto))
+        options=_OptionsOrNone(field_proto),
+        file=file_desc)
 
   def _SetAllFieldTypes(self, package, desc_proto, scope):
     """Sets all the descriptor's fields's types.
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
index 460a4a6..422af59 100755
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -100,6 +100,27 @@
 _implementation_version = int(_implementation_version_str)
 
 
+# Detect if serialization should be deterministic by default
+try:
+  # The presence of this module in a build allows the proto implementation to
+  # be upgraded merely via build deps.
+  #
+  # NOTE: Merely importing this automatically enables deterministic proto
+  # serialization for C++ code, but we still need to export it as a boolean so
+  # that we can do the same for `_implementation_type == 'python'`.
+  #
+  # NOTE2: It is possible for C++ code to enable deterministic serialization by
+  # default _without_ affecting Python code, if the C++ implementation is not in
+  # use by this module.  That is intended behavior, so we don't actually expose
+  # this boolean outside of this module.
+  #
+  # pylint: disable=g-import-not-at-top,unused-import
+  from google.protobuf import enable_deterministic_proto_serialization
+  _python_deterministic_proto_serialization = True
+except ImportError:
+  _python_deterministic_proto_serialization = False
+
+
 # Usage of this function is discouraged. Clients shouldn't care which
 # implementation of the API is in use. Note that there is no guarantee
 # that differences between APIs will be maintained.
@@ -111,3 +132,8 @@
 # See comment on 'Type' above.
 def Version():
   return _implementation_version
+
+
+# For internal use only
+def IsPythonDefaultSerializationDeterministic():
+  return _python_deterministic_proto_serialization
diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py
index c1733a4..6015e6f 100644
--- a/python/google/protobuf/internal/descriptor_pool_test.py
+++ b/python/google/protobuf/internal/descriptor_pool_test.py
@@ -131,11 +131,19 @@
     self.assertEqual('google/protobuf/internal/factory_test2.proto',
                      file_desc4.name)
 
+    file_desc5 = self.pool.FindFileContainingSymbol(
+        'protobuf_unittest.TestService')
+    self.assertIsInstance(file_desc5, descriptor.FileDescriptor)
+    self.assertEqual('google/protobuf/unittest.proto',
+                     file_desc5.name)
+
     # Tests the generated pool.
     assert descriptor_pool.Default().FindFileContainingSymbol(
         'google.protobuf.python.internal.Factory2Message.one_more_field')
     assert descriptor_pool.Default().FindFileContainingSymbol(
         'google.protobuf.python.internal.another_field')
+    assert descriptor_pool.Default().FindFileContainingSymbol(
+        'protobuf_unittest.TestService')
 
   def testFindFileContainingSymbolFailure(self):
     with self.assertRaises(KeyError):
@@ -506,10 +514,10 @@
       subtype.CheckType(test, desc, name, file_desc)
 
     for index, (name, field) in enumerate(self.field_list):
-      field.CheckField(test, desc, name, index)
+      field.CheckField(test, desc, name, index, file_desc)
 
     for index, (name, field) in enumerate(self.extensions):
-      field.CheckField(test, desc, name, index)
+      field.CheckField(test, desc, name, index, file_desc)
 
 
 class EnumField(object):
@@ -519,7 +527,7 @@
     self.type_name = type_name
     self.default_value = default_value
 
-  def CheckField(self, test, msg_desc, name, index):
+  def CheckField(self, test, msg_desc, name, index, file_desc):
     field_desc = msg_desc.fields_by_name[name]
     enum_desc = msg_desc.enum_types_by_name[self.type_name]
     test.assertEqual(name, field_desc.name)
@@ -536,6 +544,7 @@
     test.assertFalse(enum_desc.values_by_name[self.default_value].has_options)
     test.assertEqual(msg_desc, field_desc.containing_type)
     test.assertEqual(enum_desc, field_desc.enum_type)
+    test.assertEqual(file_desc, enum_desc.file)
 
 
 class MessageField(object):
@@ -544,7 +553,7 @@
     self.number = number
     self.type_name = type_name
 
-  def CheckField(self, test, msg_desc, name, index):
+  def CheckField(self, test, msg_desc, name, index, file_desc):
     field_desc = msg_desc.fields_by_name[name]
     field_type_desc = msg_desc.nested_types_by_name[self.type_name]
     test.assertEqual(name, field_desc.name)
@@ -558,6 +567,7 @@
     test.assertFalse(field_desc.has_default_value)
     test.assertEqual(msg_desc, field_desc.containing_type)
     test.assertEqual(field_type_desc, field_desc.message_type)
+    test.assertEqual(file_desc, field_desc.file)
 
 
 class StringField(object):
@@ -566,7 +576,7 @@
     self.number = number
     self.default_value = default_value
 
-  def CheckField(self, test, msg_desc, name, index):
+  def CheckField(self, test, msg_desc, name, index, file_desc):
     field_desc = msg_desc.fields_by_name[name]
     test.assertEqual(name, field_desc.name)
     expected_field_full_name = '.'.join([msg_desc.full_name, name])
@@ -578,6 +588,7 @@
                      field_desc.cpp_type)
     test.assertTrue(field_desc.has_default_value)
     test.assertEqual(self.default_value, field_desc.default_value)
+    test.assertEqual(file_desc, field_desc.file)
 
 
 class ExtensionField(object):
@@ -586,7 +597,7 @@
     self.number = number
     self.extended_type = extended_type
 
-  def CheckField(self, test, msg_desc, name, index):
+  def CheckField(self, test, msg_desc, name, index, file_desc):
     field_desc = msg_desc.extensions_by_name[name]
     test.assertEqual(name, field_desc.name)
     expected_field_full_name = '.'.join([msg_desc.full_name, name])
@@ -601,6 +612,7 @@
     test.assertEqual(msg_desc, field_desc.extension_scope)
     test.assertEqual(msg_desc, field_desc.message_type)
     test.assertEqual(self.extended_type, field_desc.containing_type.name)
+    test.assertEqual(file_desc, field_desc.file)
 
 
 class AddDescriptorTest(unittest.TestCase):
@@ -746,15 +758,10 @@
     self.assertIs(options, file_descriptor.GetOptions())
 
 
[email protected](
-    api_implementation.Type() != 'cpp',
-    'default_pool is only supported by the C++ implementation')
 class DefaultPoolTest(unittest.TestCase):
 
   def testFindMethods(self):
-    # pylint: disable=g-import-not-at-top
-    from google.protobuf.pyext import _message
-    pool = _message.default_pool
+    pool = descriptor_pool.Default()
     self.assertIs(
         pool.FindFileByName('google/protobuf/unittest.proto'),
         unittest_pb2.DESCRIPTOR)
@@ -765,19 +772,22 @@
         pool.FindFieldByName('protobuf_unittest.TestAllTypes.optional_int32'),
         unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32'])
     self.assertIs(
+        pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'),
+        unittest_pb2.ForeignEnum.DESCRIPTOR)
+    if api_implementation.Type() != 'cpp':
+      self.skipTest('Only the C++ implementation correctly indexes all types')
+    self.assertIs(
         pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'),
         unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension'])
     self.assertIs(
-        pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'),
-        unittest_pb2.ForeignEnum.DESCRIPTOR)
-    self.assertIs(
         pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'),
         unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field'])
+    self.assertIs(
+        pool.FindServiceByName('protobuf_unittest.TestService'),
+        unittest_pb2.DESCRIPTOR.services_by_name['TestService'])
 
   def testAddFileDescriptor(self):
-    # pylint: disable=g-import-not-at-top
-    from google.protobuf.pyext import _message
-    pool = _message.default_pool
+    pool = descriptor_pool.Default()
     file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto')
     pool.Add(file_desc)
     pool.AddSerializedFile(file_desc.SerializeToString())
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 1f148ab..c001008 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -521,6 +521,12 @@
     del enum
     self.assertEqual('FOO', next(values_iter).name)
 
+  def testServiceDescriptor(self):
+    service_descriptor = unittest_pb2.DESCRIPTOR.services_by_name['TestService']
+    self.assertEqual(service_descriptor.name, 'TestService')
+    self.assertEqual(service_descriptor.methods[0].name, 'Foo')
+    self.assertIs(service_descriptor.file, unittest_pb2.DESCRIPTOR)
+
 
 class DescriptorCopyToProtoTest(unittest.TestCase):
   """Tests for CopyTo functions of Descriptor."""
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
index 80e59ca..ebec42e 100755
--- a/python/google/protobuf/internal/encoder.py
+++ b/python/google/protobuf/internal/encoder.py
@@ -372,7 +372,7 @@
 def _VarintEncoder():
   """Return an encoder for a basic varint value (does not include tag)."""
 
-  def EncodeVarint(write, value):
+  def EncodeVarint(write, value, unused_deterministic):
     bits = value & 0x7f
     value >>= 7
     while value:
@@ -388,7 +388,7 @@
   """Return an encoder for a basic signed varint value (does not include
   tag)."""
 
-  def EncodeSignedVarint(write, value):
+  def EncodeSignedVarint(write, value, unused_deterministic):
     if value < 0:
       value += (1 << 64)
     bits = value & 0x7f
@@ -411,7 +411,7 @@
   called at startup time so it doesn't need to be fast."""
 
   pieces = []
-  _EncodeVarint(pieces.append, value)
+  _EncodeVarint(pieces.append, value, True)
   return b"".join(pieces)
 
 
@@ -440,27 +440,27 @@
     if is_packed:
       tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
       local_EncodeVarint = _EncodeVarint
-      def EncodePackedField(write, value):
+      def EncodePackedField(write, value, deterministic):
         write(tag_bytes)
         size = 0
         for element in value:
           size += compute_value_size(element)
-        local_EncodeVarint(write, size)
+        local_EncodeVarint(write, size, deterministic)
         for element in value:
-          encode_value(write, element)
+          encode_value(write, element, deterministic)
       return EncodePackedField
     elif is_repeated:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeRepeatedField(write, value):
+      def EncodeRepeatedField(write, value, deterministic):
         for element in value:
           write(tag_bytes)
-          encode_value(write, element)
+          encode_value(write, element, deterministic)
       return EncodeRepeatedField
     else:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeField(write, value):
+      def EncodeField(write, value, deterministic):
         write(tag_bytes)
-        return encode_value(write, value)
+        return encode_value(write, value, deterministic)
       return EncodeField
 
   return SpecificEncoder
@@ -474,27 +474,27 @@
     if is_packed:
       tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
       local_EncodeVarint = _EncodeVarint
-      def EncodePackedField(write, value):
+      def EncodePackedField(write, value, deterministic):
         write(tag_bytes)
         size = 0
         for element in value:
           size += compute_value_size(modify_value(element))
-        local_EncodeVarint(write, size)
+        local_EncodeVarint(write, size, deterministic)
         for element in value:
-          encode_value(write, modify_value(element))
+          encode_value(write, modify_value(element), deterministic)
       return EncodePackedField
     elif is_repeated:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeRepeatedField(write, value):
+      def EncodeRepeatedField(write, value, deterministic):
         for element in value:
           write(tag_bytes)
-          encode_value(write, modify_value(element))
+          encode_value(write, modify_value(element), deterministic)
       return EncodeRepeatedField
     else:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeField(write, value):
+      def EncodeField(write, value, deterministic):
         write(tag_bytes)
-        return encode_value(write, modify_value(value))
+        return encode_value(write, modify_value(value), deterministic)
       return EncodeField
 
   return SpecificEncoder
@@ -515,22 +515,22 @@
     if is_packed:
       tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
       local_EncodeVarint = _EncodeVarint
-      def EncodePackedField(write, value):
+      def EncodePackedField(write, value, deterministic):
         write(tag_bytes)
-        local_EncodeVarint(write, len(value) * value_size)
+        local_EncodeVarint(write, len(value) * value_size, deterministic)
         for element in value:
           write(local_struct_pack(format, element))
       return EncodePackedField
     elif is_repeated:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeRepeatedField(write, value):
+      def EncodeRepeatedField(write, value, unused_deterministic):
         for element in value:
           write(tag_bytes)
           write(local_struct_pack(format, element))
       return EncodeRepeatedField
     else:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeField(write, value):
+      def EncodeField(write, value, unused_deterministic):
         write(tag_bytes)
         return write(local_struct_pack(format, value))
       return EncodeField
@@ -581,9 +581,9 @@
     if is_packed:
       tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
       local_EncodeVarint = _EncodeVarint
-      def EncodePackedField(write, value):
+      def EncodePackedField(write, value, deterministic):
         write(tag_bytes)
-        local_EncodeVarint(write, len(value) * value_size)
+        local_EncodeVarint(write, len(value) * value_size, deterministic)
         for element in value:
           # This try/except block is going to be faster than any code that
           # we could write to check whether element is finite.
@@ -594,7 +594,7 @@
       return EncodePackedField
     elif is_repeated:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeRepeatedField(write, value):
+      def EncodeRepeatedField(write, value, unused_deterministic):
         for element in value:
           write(tag_bytes)
           try:
@@ -604,7 +604,7 @@
       return EncodeRepeatedField
     else:
       tag_bytes = TagBytes(field_number, wire_type)
-      def EncodeField(write, value):
+      def EncodeField(write, value, unused_deterministic):
         write(tag_bytes)
         try:
           write(local_struct_pack(format, value))
@@ -650,9 +650,9 @@
   if is_packed:
     tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
     local_EncodeVarint = _EncodeVarint
-    def EncodePackedField(write, value):
+    def EncodePackedField(write, value, deterministic):
       write(tag_bytes)
-      local_EncodeVarint(write, len(value))
+      local_EncodeVarint(write, len(value), deterministic)
       for element in value:
         if element:
           write(true_byte)
@@ -661,7 +661,7 @@
     return EncodePackedField
   elif is_repeated:
     tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
-    def EncodeRepeatedField(write, value):
+    def EncodeRepeatedField(write, value, unused_deterministic):
       for element in value:
         write(tag_bytes)
         if element:
@@ -671,7 +671,7 @@
     return EncodeRepeatedField
   else:
     tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
-    def EncodeField(write, value):
+    def EncodeField(write, value, unused_deterministic):
       write(tag_bytes)
       if value:
         return write(true_byte)
@@ -687,18 +687,18 @@
   local_len = len
   assert not is_packed
   if is_repeated:
-    def EncodeRepeatedField(write, value):
+    def EncodeRepeatedField(write, value, deterministic):
       for element in value:
         encoded = element.encode('utf-8')
         write(tag)
-        local_EncodeVarint(write, local_len(encoded))
+        local_EncodeVarint(write, local_len(encoded), deterministic)
         write(encoded)
     return EncodeRepeatedField
   else:
-    def EncodeField(write, value):
+    def EncodeField(write, value, deterministic):
       encoded = value.encode('utf-8')
       write(tag)
-      local_EncodeVarint(write, local_len(encoded))
+      local_EncodeVarint(write, local_len(encoded), deterministic)
       return write(encoded)
     return EncodeField
 
@@ -711,16 +711,16 @@
   local_len = len
   assert not is_packed
   if is_repeated:
-    def EncodeRepeatedField(write, value):
+    def EncodeRepeatedField(write, value, deterministic):
       for element in value:
         write(tag)
-        local_EncodeVarint(write, local_len(element))
+        local_EncodeVarint(write, local_len(element), deterministic)
         write(element)
     return EncodeRepeatedField
   else:
-    def EncodeField(write, value):
+    def EncodeField(write, value, deterministic):
       write(tag)
-      local_EncodeVarint(write, local_len(value))
+      local_EncodeVarint(write, local_len(value), deterministic)
       return write(value)
     return EncodeField
 
@@ -732,16 +732,16 @@
   end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
   assert not is_packed
   if is_repeated:
-    def EncodeRepeatedField(write, value):
+    def EncodeRepeatedField(write, value, deterministic):
       for element in value:
         write(start_tag)
-        element._InternalSerialize(write)
+        element._InternalSerialize(write, deterministic)
         write(end_tag)
     return EncodeRepeatedField
   else:
-    def EncodeField(write, value):
+    def EncodeField(write, value, deterministic):
       write(start_tag)
-      value._InternalSerialize(write)
+      value._InternalSerialize(write, deterministic)
       return write(end_tag)
     return EncodeField
 
@@ -753,17 +753,17 @@
   local_EncodeVarint = _EncodeVarint
   assert not is_packed
   if is_repeated:
-    def EncodeRepeatedField(write, value):
+    def EncodeRepeatedField(write, value, deterministic):
       for element in value:
         write(tag)
-        local_EncodeVarint(write, element.ByteSize())
-        element._InternalSerialize(write)
+        local_EncodeVarint(write, element.ByteSize(), deterministic)
+        element._InternalSerialize(write, deterministic)
     return EncodeRepeatedField
   else:
-    def EncodeField(write, value):
+    def EncodeField(write, value, deterministic):
       write(tag)
-      local_EncodeVarint(write, value.ByteSize())
-      return value._InternalSerialize(write)
+      local_EncodeVarint(write, value.ByteSize(), deterministic)
+      return value._InternalSerialize(write, deterministic)
     return EncodeField
 
 
@@ -790,10 +790,10 @@
   end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
   local_EncodeVarint = _EncodeVarint
 
-  def EncodeField(write, value):
+  def EncodeField(write, value, deterministic):
     write(start_bytes)
-    local_EncodeVarint(write, value.ByteSize())
-    value._InternalSerialize(write)
+    local_EncodeVarint(write, value.ByteSize(), deterministic)
+    value._InternalSerialize(write, deterministic)
     return write(end_bytes)
 
   return EncodeField
@@ -818,9 +818,10 @@
   message_type = field_descriptor.message_type
   encode_message = MessageEncoder(field_descriptor.number, False, False)
 
-  def EncodeField(write, value):
-    for key in value:
+  def EncodeField(write, value, deterministic):
+    value_keys = sorted(value.keys()) if deterministic else value.keys()
+    for key in value_keys:
       entry_msg = message_type._concrete_class(key=key, value=value[key])
-      encode_message(write, entry_msg)
+      encode_message(write, entry_msg, deterministic)
 
   return EncodeField
diff --git a/python/google/protobuf/internal/factory_test2.proto b/python/google/protobuf/internal/factory_test2.proto
index bb1b54a..5fcbc5a 100644
--- a/python/google/protobuf/internal/factory_test2.proto
+++ b/python/google/protobuf/internal/factory_test2.proto
@@ -97,3 +97,8 @@
 extend Factory1Message {
   optional string another_field = 1002;
 }
+
+message MessageWithOption {
+  option no_standard_descriptor_accessor = true;
+  optional int32 field1 = 1;
+}
diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py
index 5ed6562..077b64d 100644
--- a/python/google/protobuf/internal/json_format_test.py
+++ b/python/google/protobuf/internal/json_format_test.py
@@ -49,6 +49,7 @@
 from google.protobuf import struct_pb2
 from google.protobuf import timestamp_pb2
 from google.protobuf import wrappers_pb2
+from google.protobuf import unittest_mset_pb2
 from google.protobuf.internal import well_known_types
 from google.protobuf import json_format
 from google.protobuf.util import json_format_proto3_pb2
@@ -158,6 +159,84 @@
     json_format.Parse(text, parsed_message)
     self.assertEqual(message, parsed_message)
 
+  def testExtensionToJsonAndBack(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    message_text = json_format.MessageToJson(
+        message
+    )
+    parsed_message = unittest_mset_pb2.TestMessageSetContainer()
+    json_format.Parse(message_text, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def testExtensionToDictAndBack(self):
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    message_dict = json_format.MessageToDict(
+        message
+    )
+    parsed_message = unittest_mset_pb2.TestMessageSetContainer()
+    json_format.ParseDict(message_dict, parsed_message)
+    self.assertEqual(message, parsed_message)
+
+  def testExtensionSerializationDictMatchesProto3Spec(self):
+    """See go/proto3-json-spec for spec.
+    """
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    message_dict = json_format.MessageToDict(
+        message
+    )
+    golden_dict = {
+        'messageSet': {
+            '[protobuf_unittest.'
+            'TestMessageSetExtension1.messageSetExtension]': {
+                'i': 23,
+            },
+            '[protobuf_unittest.'
+            'TestMessageSetExtension2.messageSetExtension]': {
+                'str': u'foo',
+            },
+        },
+    }
+    self.assertEqual(golden_dict, message_dict)
+
+
+  def testExtensionSerializationJsonMatchesProto3Spec(self):
+    """See go/proto3-json-spec for spec.
+    """
+    message = unittest_mset_pb2.TestMessageSetContainer()
+    ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension
+    ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension
+    message.message_set.Extensions[ext1].i = 23
+    message.message_set.Extensions[ext2].str = 'foo'
+    message_text = json_format.MessageToJson(
+        message
+    )
+    ext1_text = ('protobuf_unittest.TestMessageSetExtension1.'
+                 'messageSetExtension')
+    ext2_text = ('protobuf_unittest.TestMessageSetExtension2.'
+                 'messageSetExtension')
+    golden_text = ('{"messageSet": {'
+                   '    "[%s]": {'
+                   '        "i": 23'
+                   '    },'
+                   '    "[%s]": {'
+                   '        "str": "foo"'
+                   '    }'
+                   '}}') % (ext1_text, ext2_text)
+    self.assertEqual(json.loads(golden_text), json.loads(message_text))
+
+
   def testJsonEscapeString(self):
     message = json_format_proto3_pb2.TestMessage()
     if sys.version_info[0] < 3:
@@ -768,7 +847,7 @@
     text = '{"value": "0000-01-01T00:00:00Z"}'
     self.assertRaisesRegexp(
         json_format.ParseError,
-        'Failed to parse value field: year is out of range.',
+        'Failed to parse value field: year (0 )?is out of range.',
         json_format.Parse, text, message)
     # Time bigger than maxinum time.
     message.value.seconds = 253402300800
@@ -840,6 +919,12 @@
     json_format.Parse('{"int32_value": 12345}', message)
     self.assertEqual(12345, message.int32_value)
 
+  def testIndent(self):
+    message = json_format_proto3_pb2.TestMessage()
+    message.int32_value = 12345
+    self.assertEqual('{\n"int32Value": 12345\n}',
+                     json_format.MessageToJson(message, indent=0))
+
   def testParseDict(self):
     expected = 12345
     js_dict = {'int32Value': expected}
@@ -862,6 +947,22 @@
     parsed_message = json_format_proto3_pb2.TestCustomJsonName()
     self.CheckParseBack(message, parsed_message)
 
+  def testSortKeys(self):
+    # Testing sort_keys is not perfectly working, as by random luck we could
+    # get the output sorted. We just use a selection of names.
+    message = json_format_proto3_pb2.TestMessage(bool_value=True,
+                                                 int32_value=1,
+                                                 int64_value=3,
+                                                 uint32_value=4,
+                                                 string_value='bla')
+    self.assertEqual(
+        json_format.MessageToJson(message, sort_keys=True),
+        # We use json.dumps() instead of a hardcoded string due to differences
+        # between Python 2 and Python 3.
+        json.dumps({'boolValue': True, 'int32Value': 1, 'int64Value': '3',
+                    'uint32Value': 4, 'stringValue': 'bla'},
+                   indent=2, sort_keys=True))
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py
index 4caa244..aa7af2d 100644
--- a/python/google/protobuf/internal/message_factory_test.py
+++ b/python/google/protobuf/internal/message_factory_test.py
@@ -183,7 +183,14 @@
     with self.assertRaises(Exception) as cm:
       factory.GetMessages([f.name])
 
-    self.assertIsInstance(cm.exception, (AssertionError, ValueError))
+    self.assertIn(str(cm.exception),
+                  ['Extensions '
+                   '"google.protobuf.python.internal.Duplicate.extension_field" and'
+                   ' "google.protobuf.python.internal.Extension.extension_field"'
+                   ' both try to extend message type'
+                   ' "google.protobuf.python.internal.Container"'
+                   ' with field number 2.',
+                   'Double registration of Extensions'])
 
 
 if __name__ == '__main__':
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index e8b794f..dda72cd 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -53,9 +53,13 @@
 import sys
 
 try:
-  import unittest2 as unittest  #PY26
+  import unittest2 as unittest  # PY26
 except ImportError:
   import unittest
+try:
+  cmp                                   # Python 2
+except NameError:
+  cmp = lambda x, y: (x > y) - (x < y)  # Python 3
 
 from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_pb2
@@ -136,6 +140,42 @@
     golden_copy = copy.deepcopy(golden_message)
     self.assertEqual(golden_data, golden_copy.SerializeToString())
 
+  def testDeterminismParameters(self, message_module):
+    # This message is always deterministically serialized, even if determinism
+    # is disabled, so we can use it to verify that all the determinism
+    # parameters work correctly.
+    golden_data = (b'\xe2\x02\nOne string'
+                   b'\xe2\x02\nTwo string'
+                   b'\xe2\x02\nRed string'
+                   b'\xe2\x02\x0bBlue string')
+    golden_message = message_module.TestAllTypes()
+    golden_message.repeated_string.extend([
+        'One string',
+        'Two string',
+        'Red string',
+        'Blue string',
+    ])
+    self.assertEqual(golden_data,
+                     golden_message.SerializeToString(deterministic=None))
+    self.assertEqual(golden_data,
+                     golden_message.SerializeToString(deterministic=False))
+    self.assertEqual(golden_data,
+                     golden_message.SerializeToString(deterministic=True))
+
+    class BadArgError(Exception):
+      pass
+
+    class BadArg(object):
+
+      def __nonzero__(self):
+        raise BadArgError()
+
+      def __bool__(self):
+        raise BadArgError()
+
+    with self.assertRaises(BadArgError):
+      golden_message.SerializeToString(deterministic=BadArg())
+
   def testPickleSupport(self, message_module):
     golden_data = test_util.GoldenFileData('golden_message')
     golden_message = message_module.TestAllTypes()
@@ -377,6 +417,7 @@
     self.assertEqual(message.repeated_int32[0], 1)
     self.assertEqual(message.repeated_int32[1], 2)
     self.assertEqual(message.repeated_int32[2], 3)
+    self.assertEqual(str(message.repeated_int32), str([1, 2, 3]))
 
     message.repeated_float.append(1.1)
     message.repeated_float.append(1.3)
@@ -393,6 +434,7 @@
     self.assertEqual(message.repeated_string[0], 'a')
     self.assertEqual(message.repeated_string[1], 'b')
     self.assertEqual(message.repeated_string[2], 'c')
+    self.assertEqual(str(message.repeated_string), str([u'a', u'b', u'c']))
 
     message.repeated_bytes.append(b'a')
     message.repeated_bytes.append(b'c')
@@ -401,6 +443,7 @@
     self.assertEqual(message.repeated_bytes[0], b'a')
     self.assertEqual(message.repeated_bytes[1], b'b')
     self.assertEqual(message.repeated_bytes[2], b'c')
+    self.assertEqual(str(message.repeated_bytes), str([b'a', b'b', b'c']))
 
   def testSortingRepeatedScalarFieldsCustomComparator(self, message_module):
     """Check some different types with custom comparator."""
@@ -439,6 +482,8 @@
     self.assertEqual(message.repeated_nested_message[3].bb, 4)
     self.assertEqual(message.repeated_nested_message[4].bb, 5)
     self.assertEqual(message.repeated_nested_message[5].bb, 6)
+    self.assertEqual(str(message.repeated_nested_message),
+                     '[bb: 1\n, bb: 2\n, bb: 3\n, bb: 4\n, bb: 5\n, bb: 6\n]')
 
   def testSortingRepeatedCompositeFieldsStable(self, message_module):
     """Check passing a custom comparator to sort a repeated composite field."""
@@ -1266,6 +1311,14 @@
     self.assertEqual(1234567, m2.optional_nested_enum)
     self.assertEqual(7654321, m2.repeated_nested_enum[0])
 
+    # ParseFromString in Proto2 should accept unknown enums too.
+    m3 = unittest_pb2.TestAllTypes()
+    m3.ParseFromString(serialized)
+    m2.Clear()
+    m2.ParseFromString(m3.SerializeToString())
+    self.assertEqual(1234567, m2.optional_nested_enum)
+    self.assertEqual(7654321, m2.repeated_nested_enum[0])
+
   # Map isn't really a proto3-only feature. But there is no proto2 equivalent
   # of google/protobuf/map_unittest.proto right now, so it's not easy to
   # test both with the same test like we do for the other proto2/proto3 tests.
@@ -1437,6 +1490,23 @@
     self.assertIn(-456, msg2.map_int32_foreign_message)
     self.assertEqual(2, len(msg2.map_int32_foreign_message))
 
+  def testNestedMessageMapItemDelete(self):
+    msg = map_unittest_pb2.TestMap()
+    msg.map_int32_all_types[1].optional_nested_message.bb = 1
+    del msg.map_int32_all_types[1]
+    msg.map_int32_all_types[2].optional_nested_message.bb = 2
+    self.assertEqual(1, len(msg.map_int32_all_types))
+    msg.map_int32_all_types[1].optional_nested_message.bb = 1
+    self.assertEqual(2, len(msg.map_int32_all_types))
+
+    serialized = msg.SerializeToString()
+    msg2 = map_unittest_pb2.TestMap()
+    msg2.ParseFromString(serialized)
+    keys = [1, 2]
+    # The loop triggers PyErr_Occurred() in c extension.
+    for key in keys:
+      del msg2.map_int32_all_types[key]
+
   def testMapByteSize(self):
     msg = map_unittest_pb2.TestMap()
     msg.map_int32_int32[1] = 1
@@ -1651,6 +1721,35 @@
     items2 = msg.map_string_string.items()
     self.assertEqual(items1, items2)
 
+  def testMapDeterministicSerialization(self):
+    golden_data = (b'r\x0c\n\x07init_op\x12\x01d'
+                   b'r\n\n\x05item1\x12\x01e'
+                   b'r\n\n\x05item2\x12\x01f'
+                   b'r\n\n\x05item3\x12\x01g'
+                   b'r\x0b\n\x05item4\x12\x02QQ'
+                   b'r\x12\n\rlocal_init_op\x12\x01a'
+                   b'r\x0e\n\tsummaries\x12\x01e'
+                   b'r\x18\n\x13trainable_variables\x12\x01b'
+                   b'r\x0e\n\tvariables\x12\x01c')
+    msg = map_unittest_pb2.TestMap()
+    msg.map_string_string['local_init_op'] = 'a'
+    msg.map_string_string['trainable_variables'] = 'b'
+    msg.map_string_string['variables'] = 'c'
+    msg.map_string_string['init_op'] = 'd'
+    msg.map_string_string['summaries'] = 'e'
+    msg.map_string_string['item1'] = 'e'
+    msg.map_string_string['item2'] = 'f'
+    msg.map_string_string['item3'] = 'g'
+    msg.map_string_string['item4'] = 'QQ'
+
+    # If deterministic serialization is not working correctly, this will be
+    # "flaky" depending on the exact python dict hash seed.
+    #
+    # Fortunately, there are enough items in this map that it is extremely
+    # unlikely to ever hit the "right" in-order combination, so the test
+    # itself should fail reliably.
+    self.assertEqual(golden_data, msg.SerializeToString(deterministic=True))
+
   def testMapIterationClearMessage(self):
     # Iterator needs to work even if message and map are deleted.
     msg = map_unittest_pb2.TestMap()
@@ -1832,8 +1931,9 @@
     self.assertEqual(golden_data, message.SerializeToString())
 
 
[email protected](api_implementation.Type() != 'cpp',
-                 'explicit tests of the C++ implementation')
[email protected](api_implementation.Type() != 'cpp' or
+                 sys.version_info < (2, 7),
+                 'explicit tests of the C++ implementation for PY27 and above')
 class OversizeProtosTest(BaseTestCase):
 
   @classmethod
diff --git a/python/google/protobuf/internal/more_extensions_dynamic.proto b/python/google/protobuf/internal/more_extensions_dynamic.proto
index 11f85ef..98fcbcb 100644
--- a/python/google/protobuf/internal/more_extensions_dynamic.proto
+++ b/python/google/protobuf/internal/more_extensions_dynamic.proto
@@ -47,4 +47,5 @@
 extend ExtendedMessage {
   optional int32 dynamic_int32_extension = 100;
   optional DynamicMessageType dynamic_message_extension = 101;
+  repeated DynamicMessageType repeated_dynamic_message_extension = 102;
 }
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index cb97cb2..c363d84 100755
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -58,6 +58,7 @@
 import six
 
 # We use "as" to avoid name collisions with variables.
+from google.protobuf.internal import api_implementation
 from google.protobuf.internal import containers
 from google.protobuf.internal import decoder
 from google.protobuf.internal import encoder
@@ -1026,29 +1027,34 @@
 def _AddSerializeToStringMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
 
-  def SerializeToString(self):
+  def SerializeToString(self, **kwargs):
     # Check if the message has all of its required fields set.
     errors = []
     if not self.IsInitialized():
       raise message_mod.EncodeError(
           'Message %s is missing required fields: %s' % (
           self.DESCRIPTOR.full_name, ','.join(self.FindInitializationErrors())))
-    return self.SerializePartialToString()
+    return self.SerializePartialToString(**kwargs)
   cls.SerializeToString = SerializeToString
 
 
 def _AddSerializePartialToStringMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
 
-  def SerializePartialToString(self):
+  def SerializePartialToString(self, **kwargs):
     out = BytesIO()
-    self._InternalSerialize(out.write)
+    self._InternalSerialize(out.write, **kwargs)
     return out.getvalue()
   cls.SerializePartialToString = SerializePartialToString
 
-  def InternalSerialize(self, write_bytes):
+  def InternalSerialize(self, write_bytes, deterministic=None):
+    if deterministic is None:
+      deterministic = (
+          api_implementation.IsPythonDefaultSerializationDeterministic())
+    else:
+      deterministic = bool(deterministic)
     for field_descriptor, field_value in self.ListFields():
-      field_descriptor._encoder(write_bytes, field_value)
+      field_descriptor._encoder(write_bytes, field_value, deterministic)
     for tag_bytes, value_bytes in self._unknown_fields:
       write_bytes(tag_bytes)
       write_bytes(value_bytes)
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 55b0d72..5ab5225 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -40,6 +40,7 @@
 import operator
 import six
 import struct
+import sys
 
 try:
   import unittest2 as unittest  #PY26
@@ -686,8 +687,8 @@
       self.assertEqual(expected_min, getattr(pb, field_name))
       setattr(pb, field_name, expected_max)
       self.assertEqual(expected_max, getattr(pb, field_name))
-      self.assertRaises(ValueError, setattr, pb, field_name, expected_min - 1)
-      self.assertRaises(ValueError, setattr, pb, field_name, expected_max + 1)
+      self.assertRaises(Exception, setattr, pb, field_name, expected_min - 1)
+      self.assertRaises(Exception, setattr, pb, field_name, expected_max + 1)
 
     TestMinAndMaxIntegers('optional_int32', -(1 << 31), (1 << 31) - 1)
     TestMinAndMaxIntegers('optional_uint32', 0, 0xffffffff)
@@ -696,7 +697,7 @@
     # A bit of white-box testing since -1 is an int and not a long in C++ and
     # so goes down a different path.
     pb = unittest_pb2.TestAllTypes()
-    with self.assertRaises(ValueError):
+    with self.assertRaises(Exception):
       pb.optional_uint64 = integer_fn(-(1 << 63))
 
     pb = unittest_pb2.TestAllTypes()
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
index 269d0e2..9434b7b 100755
--- a/python/google/protobuf/internal/test_util.py
+++ b/python/google/protobuf/internal/test_util.py
@@ -39,11 +39,15 @@
 import numbers
 import operator
 import os.path
-import sys
 
 from google.protobuf import unittest_import_pb2
 from google.protobuf import unittest_pb2
-from google.protobuf import descriptor_pb2
+
+try:
+    long        # Python 2
+except NameError:
+    long = int  # Python 3
+
 
 # Tests whether the given TestAllTypes message is proto2 or not.
 # This is used to gate several fields/features that only exist
@@ -51,6 +55,7 @@
 def IsProto2(message):
   return message.DESCRIPTOR.syntax == "proto2"
 
+
 def SetAllNonLazyFields(message):
   """Sets every non-lazy field in the message to a unique value.
 
@@ -707,8 +712,8 @@
   NonStandardInteger is the minimal legal specification for a custom Integral.
   As such, it does not support 0 < x < 5 and it is not hashable.
 
-  Note: This is added here instead of relying on numpy or a similar library with
-  custom integers to limit dependencies.
+  Note: This is added here instead of relying on numpy or a similar library
+  with custom integers to limit dependencies.
   """
 
   def __init__(self, val, error_string_on_conversion=None):
@@ -845,4 +850,3 @@
 
   def __repr__(self):
     return 'NonStandardInteger(%s)' % self.val
-
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 188310b..424b29c 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -452,16 +452,18 @@
     text_format.Parse(text_format.MessageToString(m), m2)
     self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field'))
 
+  def testMergeMultipleOneof(self, message_module):
+    m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"'])
+    m2 = message_module.TestAllTypes()
+    text_format.Merge(m_string, m2)
+    self.assertEqual('oneof_string', m2.WhichOneof('oneof_field'))
+
   def testParseMultipleOneof(self, message_module):
     m_string = '\n'.join(['oneof_uint32: 11', 'oneof_string: "foo"'])
     m2 = message_module.TestAllTypes()
-    if message_module is unittest_pb2:
-      with self.assertRaisesRegexp(text_format.ParseError,
-                                   ' is specified along with field '):
-        text_format.Parse(m_string, m2)
-    else:
+    with self.assertRaisesRegexp(text_format.ParseError,
+                                 ' is specified along with field '):
       text_format.Parse(m_string, m2)
-      self.assertEqual('oneof_string', m2.WhichOneof('oneof_field'))
 
 
 # These are tests that aren't fundamentally specific to proto2, but are at
@@ -1026,8 +1028,7 @@
     packed_message.data = 'string1'
     message.repeated_any_value.add().Pack(packed_message)
     self.assertEqual(
-        text_format.MessageToString(message,
-                                    descriptor_pool=descriptor_pool.Default()),
+        text_format.MessageToString(message),
         'repeated_any_value {\n'
         '  [type.googleapis.com/protobuf_unittest.OneString] {\n'
         '    data: "string0"\n'
@@ -1039,18 +1040,6 @@
         '  }\n'
         '}\n')
 
-  def testPrintMessageExpandAnyNoDescriptorPool(self):
-    packed_message = unittest_pb2.OneString()
-    packed_message.data = 'string'
-    message = any_test_pb2.TestAny()
-    message.any_value.Pack(packed_message)
-    self.assertEqual(
-        text_format.MessageToString(message, descriptor_pool=None),
-        'any_value {\n'
-        '  type_url: "type.googleapis.com/protobuf_unittest.OneString"\n'
-        '  value: "\\n\\006string"\n'
-        '}\n')
-
   def testPrintMessageExpandAnyDescriptorPoolMissingType(self):
     packed_message = unittest_pb2.OneString()
     packed_message.data = 'string'
@@ -1071,8 +1060,7 @@
     message.any_value.Pack(packed_message)
     self.assertEqual(
         text_format.MessageToString(message,
-                                    pointy_brackets=True,
-                                    descriptor_pool=descriptor_pool.Default()),
+                                    pointy_brackets=True),
         'any_value <\n'
         '  [type.googleapis.com/protobuf_unittest.OneString] <\n'
         '    data: "string"\n'
@@ -1086,8 +1074,7 @@
     message.any_value.Pack(packed_message)
     self.assertEqual(
         text_format.MessageToString(message,
-                                    as_one_line=True,
-                                    descriptor_pool=descriptor_pool.Default()),
+                                    as_one_line=True),
         'any_value {'
         ' [type.googleapis.com/protobuf_unittest.OneString]'
         ' { data: "string" } '
@@ -1115,12 +1102,12 @@
             '    data: "string"\n'
             '  }\n'
             '}\n')
-    text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default())
+    text_format.Merge(text, message)
     packed_message = unittest_pb2.OneString()
     message.any_value.Unpack(packed_message)
     self.assertEqual('string', packed_message.data)
     message.Clear()
-    text_format.Parse(text, message, descriptor_pool=descriptor_pool.Default())
+    text_format.Parse(text, message)
     packed_message = unittest_pb2.OneString()
     message.any_value.Unpack(packed_message)
     self.assertEqual('string', packed_message.data)
@@ -1137,7 +1124,7 @@
             '    data: "string1"\n'
             '  }\n'
             '}\n')
-    text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default())
+    text_format.Merge(text, message)
     packed_message = unittest_pb2.OneString()
     message.repeated_any_value[0].Unpack(packed_message)
     self.assertEqual('string0', packed_message.data)
@@ -1151,22 +1138,22 @@
             '    data: "string"\n'
             '  >\n'
             '}\n')
-    text_format.Merge(text, message, descriptor_pool=descriptor_pool.Default())
+    text_format.Merge(text, message)
     packed_message = unittest_pb2.OneString()
     message.any_value.Unpack(packed_message)
     self.assertEqual('string', packed_message.data)
 
-  def testMergeExpandedAnyNoDescriptorPool(self):
+  def testMergeAlternativeUrl(self):
     message = any_test_pb2.TestAny()
     text = ('any_value {\n'
-            '  [type.googleapis.com/protobuf_unittest.OneString] {\n'
+            '  [type.otherapi.com/protobuf_unittest.OneString] {\n'
             '    data: "string"\n'
             '  }\n'
             '}\n')
-    with self.assertRaises(text_format.ParseError) as e:
-      text_format.Merge(text, message, descriptor_pool=None)
-    self.assertEqual(str(e.exception),
-                     'Descriptor pool required to parse expanded Any field')
+    text_format.Merge(text, message)
+    packed_message = unittest_pb2.OneString()
+    self.assertEqual('type.otherapi.com/protobuf_unittest.OneString',
+                     message.any_value.type_url)
 
   def testMergeExpandedAnyDescriptorPoolMissingType(self):
     message = any_test_pb2.TestAny()
@@ -1425,5 +1412,101 @@
                      tokenizer.ConsumeCommentOrTrailingComment())
     self.assertTrue(tokenizer.AtEnd())
 
+
+# Tests for pretty printer functionality.
+@_parameterized.Parameters((unittest_pb2), (unittest_proto3_arena_pb2))
+class PrettyPrinterTest(TextFormatBase):
+
+  def testPrettyPrintNoMatch(self, message_module):
+
+    def printer(message, indent, as_one_line):
+      del message, indent, as_one_line
+      return None
+
+    message = message_module.TestAllTypes()
+    msg = message.repeated_nested_message.add()
+    msg.bb = 42
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=True, message_formatter=printer),
+        'repeated_nested_message { bb: 42 }')
+
+  def testPrettyPrintOneLine(self, message_module):
+
+    def printer(m, indent, as_one_line):
+      del indent, as_one_line
+      if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR:
+        return 'My lucky number is %s' % m.bb
+
+    message = message_module.TestAllTypes()
+    msg = message.repeated_nested_message.add()
+    msg.bb = 42
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=True, message_formatter=printer),
+        'repeated_nested_message { My lucky number is 42 }')
+
+  def testPrettyPrintMultiLine(self, message_module):
+
+    def printer(m, indent, as_one_line):
+      if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR:
+        line_deliminator = (' ' if as_one_line else '\n') + ' ' * indent
+        return 'My lucky number is:%s%s' % (line_deliminator, m.bb)
+      return None
+
+    message = message_module.TestAllTypes()
+    msg = message.repeated_nested_message.add()
+    msg.bb = 42
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=True, message_formatter=printer),
+        'repeated_nested_message { My lucky number is: 42 }')
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=False, message_formatter=printer),
+        'repeated_nested_message {\n  My lucky number is:\n  42\n}\n')
+
+  def testPrettyPrintEntireMessage(self, message_module):
+
+    def printer(m, indent, as_one_line):
+      del indent, as_one_line
+      if m.DESCRIPTOR == message_module.TestAllTypes.DESCRIPTOR:
+        return 'The is the message!'
+      return None
+
+    message = message_module.TestAllTypes()
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=False, message_formatter=printer),
+        'The is the message!\n')
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=True, message_formatter=printer),
+        'The is the message!')
+
+  def testPrettyPrintMultipleParts(self, message_module):
+
+    def printer(m, indent, as_one_line):
+      del indent, as_one_line
+      if m.DESCRIPTOR == message_module.TestAllTypes.NestedMessage.DESCRIPTOR:
+        return 'My lucky number is %s' % m.bb
+      return None
+
+    message = message_module.TestAllTypes()
+    message.optional_int32 = 61
+    msg = message.repeated_nested_message.add()
+    msg.bb = 42
+    msg = message.repeated_nested_message.add()
+    msg.bb = 99
+    msg = message.optional_nested_message
+    msg.bb = 1
+    self.CompareToGoldenText(
+        text_format.MessageToString(
+            message, as_one_line=True, message_formatter=printer),
+        ('optional_int32: 61 '
+         'optional_nested_message { My lucky number is 1 } '
+         'repeated_nested_message { My lucky number is 42 } '
+         'repeated_nested_message { My lucky number is 99 }'))
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py
index d631abe..d0c7ffd 100644
--- a/python/google/protobuf/internal/well_known_types.py
+++ b/python/google/protobuf/internal/well_known_types.py
@@ -350,12 +350,12 @@
             self.nanos, _NANOS_PER_MICROSECOND))
 
   def FromTimedelta(self, td):
-    """Convertd timedelta to Duration."""
+    """Converts timedelta to Duration."""
     self._NormalizeDuration(td.seconds + td.days * _SECONDS_PER_DAY,
                             td.microseconds * _NANOS_PER_MICROSECOND)
 
   def _NormalizeDuration(self, seconds, nanos):
-    """Set Duration by seconds and nonas."""
+    """Set Duration by seconds and nanos."""
     # Force nanos to be negative if the duration is negative.
     if seconds < 0 and nanos > 0:
       seconds += 1
diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py
index 077f630..123a537 100644
--- a/python/google/protobuf/internal/well_known_types_test.py
+++ b/python/google/protobuf/internal/well_known_types_test.py
@@ -284,7 +284,7 @@
         '1972-01-01T01:00:00.01+08',)
     self.assertRaisesRegexp(
         ValueError,
-        'year is out of range',
+        'year (0 )?is out of range',
         message.FromJsonString,
         '0000-01-01T00:00:00Z')
     message.seconds = 253402300800
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index d02cb09..801eed6 100644
--- a/python/google/protobuf/json_format.py
+++ b/python/google/protobuf/json_format.py
@@ -74,6 +74,9 @@
     r'[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]'
 ))
 
+_VALID_EXTENSION_NAME = re.compile(r'\[[a-zA-Z0-9\._]*\]$')
+
+
 class Error(Exception):
   """Top-level module error for json_format."""
 
@@ -88,7 +91,9 @@
 
 def MessageToJson(message,
                   including_default_value_fields=False,
-                  preserving_proto_field_name=False):
+                  preserving_proto_field_name=False,
+                  indent=2,
+                  sort_keys=False):
   """Converts protobuf message to JSON format.
 
   Args:
@@ -100,19 +105,24 @@
     preserving_proto_field_name: If True, use the original proto field
         names as defined in the .proto file. If False, convert the field
         names to lowerCamelCase.
+    indent: The JSON object will be pretty-printed with this indent level.
+        An indent level of 0 or negative will only insert newlines.
+    sort_keys: If True, then the output will be sorted by field names.
 
   Returns:
     A string containing the JSON formatted protocol buffer message.
   """
   printer = _Printer(including_default_value_fields,
                      preserving_proto_field_name)
-  return printer.ToJsonString(message)
+  return printer.ToJsonString(message, indent, sort_keys)
 
 
 def MessageToDict(message,
                   including_default_value_fields=False,
                   preserving_proto_field_name=False):
-  """Converts protobuf message to a JSON dictionary.
+  """Converts protobuf message to a dictionary.
+
+  When the dictionary is encoded to JSON, it conforms to proto3 JSON spec.
 
   Args:
     message: The protocol buffers message instance to serialize.
@@ -125,7 +135,7 @@
         names to lowerCamelCase.
 
   Returns:
-    A dict representation of the JSON formatted protocol buffer message.
+    A dict representation of the protocol buffer message.
   """
   printer = _Printer(including_default_value_fields,
                      preserving_proto_field_name)
@@ -148,9 +158,9 @@
     self.including_default_value_fields = including_default_value_fields
     self.preserving_proto_field_name = preserving_proto_field_name
 
-  def ToJsonString(self, message):
+  def ToJsonString(self, message, indent, sort_keys):
     js = self._MessageToJsonObject(message)
-    return json.dumps(js, indent=2)
+    return json.dumps(js, indent=indent, sort_keys=sort_keys)
 
   def _MessageToJsonObject(self, message):
     """Converts message to an object according to Proto3 JSON Specification."""
@@ -192,6 +202,14 @@
           # Convert a repeated field.
           js[name] = [self._FieldToJsonObject(field, k)
                       for k in value]
+        elif field.is_extension:
+          f = field
+          if (f.containing_type.GetOptions().message_set_wire_format and
+              f.type == descriptor.FieldDescriptor.TYPE_MESSAGE and
+              f.label == descriptor.FieldDescriptor.LABEL_OPTIONAL):
+            f = f.message_type
+          name = '[%s.%s]' % (f.full_name, name)
+          js[name] = self._FieldToJsonObject(field, value)
         else:
           js[name] = self._FieldToJsonObject(field, value)
 
@@ -433,12 +451,23 @@
         field = fields_by_json_name.get(name, None)
         if not field:
           field = message_descriptor.fields_by_name.get(name, None)
+        if not field and _VALID_EXTENSION_NAME.match(name):
+          if not message_descriptor.is_extendable:
+            raise ParseError('Message type {0} does not have extensions'.format(
+                message_descriptor.full_name))
+          identifier = name[1:-1]  # strip [] brackets
+          identifier = '.'.join(identifier.split('.')[:-1])
+          # pylint: disable=protected-access
+          field = message.Extensions._FindExtensionByName(identifier)
+          # pylint: enable=protected-access
         if not field:
           if self.ignore_unknown_fields:
             continue
           raise ParseError(
-              'Message type "{0}" has no field named "{1}".'.format(
-                  message_descriptor.full_name, name))
+              ('Message type "{0}" has no field named "{1}".\n'
+               ' Available Fields(except extensions): {2}').format(
+                   message_descriptor.full_name, name,
+                   message_descriptor.fields))
         if name in names:
           raise ParseError('Message type "{0}" should not have multiple '
                            '"{1}" fields.'.format(
@@ -491,7 +520,10 @@
               getattr(message, field.name).append(
                   _ConvertScalarFieldValue(item, field))
         elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
-          sub_message = getattr(message, field.name)
+          if field.is_extension:
+            sub_message = message.Extensions[field]
+          else:
+            sub_message = getattr(message, field.name)
           sub_message.SetInParent()
           self.ConvertMessage(value, sub_message)
         else:
@@ -532,8 +564,8 @@
 
   def _ConvertGenericMessage(self, value, message):
     """Convert a JSON representation into message with FromJsonString."""
-    # Durantion, Timestamp, FieldMask have FromJsonString method to do the
-    # convert. Users can also call the method directly.
+    # Duration, Timestamp, FieldMask have a FromJsonString method to do the
+    # conversion. Users can also call the method directly.
     message.FromJsonString(value)
 
   def _ConvertValueMessage(self, value, message):
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index aab250e..eeb0d57 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -184,9 +184,15 @@
     self.Clear()
     self.MergeFromString(serialized)
 
-  def SerializeToString(self):
+  def SerializeToString(self, **kwargs):
     """Serializes the protocol message to a binary string.
 
+    Arguments:
+      **kwargs: Keyword arguments to the serialize method, accepts
+        the following keyword args:
+        deterministic: If true, requests deterministic serialization of the
+          protobuf, with predictable ordering of map keys.
+
     Returns:
       A binary string representation of the message if all of the required
       fields in the message are set (i.e. the message is initialized).
@@ -196,12 +202,18 @@
     """
     raise NotImplementedError
 
-  def SerializePartialToString(self):
+  def SerializePartialToString(self, **kwargs):
     """Serializes the protocol message to a binary string.
 
     This method is similar to SerializeToString but doesn't check if the
     message is initialized.
 
+    Arguments:
+      **kwargs: Keyword arguments to the serialize method, accepts
+        the following keyword args:
+        deterministic: If true, requests deterministic serialization of the
+          protobuf, with predictable ordering of map keys.
+
     Returns:
       A string representation of the partial message.
     """
diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py
index 8ab1c51..1574028 100644
--- a/python/google/protobuf/message_factory.py
+++ b/python/google/protobuf/message_factory.py
@@ -66,7 +66,7 @@
     Returns:
       A class describing the passed in descriptor.
     """
-    if descriptor.full_name not in self._classes:
+    if descriptor not in self._classes:
       descriptor_name = descriptor.name
       if str is bytes:  # PY2
         descriptor_name = descriptor.name.encode('ascii', 'ignore')
@@ -75,16 +75,16 @@
           (message.Message,),
           {'DESCRIPTOR': descriptor, '__module__': None})
           # If module not set, it wrongly points to the reflection.py module.
-      self._classes[descriptor.full_name] = result_class
+      self._classes[descriptor] = result_class
       for field in descriptor.fields:
         if field.message_type:
           self.GetPrototype(field.message_type)
       for extension in result_class.DESCRIPTOR.extensions:
-        if extension.containing_type.full_name not in self._classes:
+        if extension.containing_type not in self._classes:
           self.GetPrototype(extension.containing_type)
-        extended_class = self._classes[extension.containing_type.full_name]
+        extended_class = self._classes[extension.containing_type]
         extended_class.RegisterExtension(extension)
-    return self._classes[descriptor.full_name]
+    return self._classes[descriptor]
 
   def GetMessages(self, files):
     """Gets all the messages from a specified file.
@@ -116,9 +116,9 @@
       # an error if they were different.
 
       for extension in file_desc.extensions_by_name.values():
-        if extension.containing_type.full_name not in self._classes:
+        if extension.containing_type not in self._classes:
           self.GetPrototype(extension.containing_type)
-        extended_class = self._classes[extension.containing_type.full_name]
+        extended_class = self._classes[extension.containing_type]
         extended_class.RegisterExtension(extension)
     return result
 
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index f13e1bc..9634ea0 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -709,6 +709,10 @@
   return PyString_FromCppString(_GetDescriptor(self)->json_name());
 }
 
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+  return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
+}
+
 static PyObject* GetType(PyBaseDescriptor *self, void *closure) {
   return PyInt_FromLong(_GetDescriptor(self)->type());
 }
@@ -899,6 +903,7 @@
   { "name", (getter)GetName, NULL, "Unqualified name"},
   { "camelcase_name", (getter)GetCamelcaseName, NULL, "Camelcase name"},
   { "json_name", (getter)GetJsonName, NULL, "Json name"},
+  { "file", (getter)GetFile, NULL, "File Descriptor"},
   { "type", (getter)GetType, NULL, "C++ Type"},
   { "cpp_type", (getter)GetCppType, NULL, "C++ Type"},
   { "label", (getter)GetLabel, NULL, "Label"},
@@ -1570,6 +1575,10 @@
   return PyString_FromCppString(_GetDescriptor(self)->full_name());
 }
 
+static PyObject* GetFile(PyBaseDescriptor *self, void *closure) {
+  return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file());
+}
+
 static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) {
   return PyInt_FromLong(_GetDescriptor(self)->index());
 }
@@ -1611,6 +1620,7 @@
 static PyGetSetDef Getters[] = {
   { "name", (getter)GetName, NULL, "Name", NULL},
   { "full_name", (getter)GetFullName, NULL, "Full name", NULL},
+  { "file", (getter)GetFile, NULL, "File descriptor"},
   { "index", (getter)GetIndex, NULL, "Index", NULL},
 
   { "methods", (getter)GetMethods, NULL, "Methods", NULL},
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index 088ddf9..43be070 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -712,8 +712,30 @@
   }
 
   // Delete key from map.
-  if (reflection->DeleteMapValue(message, self->parent_field_descriptor,
+  if (reflection->ContainsMapKey(*message, self->parent_field_descriptor,
                                  map_key)) {
+    // Delete key from CMessage dict.
+    MapValueRef value;
+    reflection->InsertOrLookupMapValue(message, self->parent_field_descriptor,
+                                       map_key, &value);
+    ScopedPyObjectPtr key(PyLong_FromVoidPtr(value.MutableMessageValue()));
+
+    // PyDict_DelItem will have key error if the key is not in the map. We do
+    // not want to call PyErr_Clear() which may clear other errors. Thus
+    // PyDict_Contains() check is called before delete.
+    int contains = PyDict_Contains(self->message_dict, key.get());
+    if (contains < 0) {
+      return -1;
+    }
+    if (contains) {
+      if (PyDict_DelItem(self->message_dict, key.get()) < 0) {
+        return -1;
+      }
+    }
+
+    // Delete key from map.
+    reflection->DeleteMapValue(message, self->parent_field_descriptor,
+                               map_key);
     return 0;
   } else {
     PyErr_Format(PyExc_KeyError, "Key not present in map");
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 85aaa46..43482c5 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -52,6 +52,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/util/message_differencer.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/message.h>
@@ -66,7 +67,6 @@
 #include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/pyext/safe_numerics.h>
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#include <google/protobuf/stubs/strutil.h>
 
 #if PY_MAJOR_VERSION >= 3
   #define PyInt_AsLong PyLong_AsLong
@@ -101,6 +101,17 @@
 
 static int InsertEmptyWeakref(PyTypeObject* base);
 
+namespace {
+// Copied oveer from internal 'google/protobuf/stubs/strutil.h'.
+inline void UpperString(string * s) {
+  string::iterator end = s->end();
+  for (string::iterator i = s->begin(); i != end; ++i) {
+    // toupper() changes based on locale.  We don't want this!
+    if ('a' <= *i && *i <= 'z') *i += 'A' - 'a';
+  }
+}
+}
+
 // Add the number of a field descriptor to the containing message class.
 // Equivalent to:
 //   _cls.<field>_FIELD_NUMBER = <number>
@@ -1055,13 +1066,15 @@
 
   if (PySlice_Check(slice)) {
     from = to = step = slice_length = 0;
-    PySlice_GetIndicesEx(
 #if PY_MAJOR_VERSION < 3
+    PySlice_GetIndicesEx(
         reinterpret_cast<PySliceObject*>(slice),
-#else
-        slice,
-#endif
         length, &from, &to, &step, &slice_length);
+#else
+    PySlice_GetIndicesEx(
+        slice,
+        length, &from, &to, &step, &slice_length);
+#endif
     if (from < to) {
       min = from;
       max = to - 1;
@@ -1808,8 +1821,25 @@
   }
 }
 
-static PyObject* SerializeToString(CMessage* self, PyObject* args) {
-  if (!self->message->IsInitialized()) {
+static PyObject* InternalSerializeToString(
+    CMessage* self, PyObject* args, PyObject* kwargs,
+    bool require_initialized) {
+  // Parse the "deterministic" kwarg; defaults to False.
+  static char* kwlist[] = { "deterministic", 0 };
+  PyObject* deterministic_obj = Py_None;
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
+                                   &deterministic_obj)) {
+    return NULL;
+  }
+  // Preemptively convert to a bool first, so we don't need to back out of
+  // allocating memory if this raises an exception.
+  // NOTE: This is unused later if deterministic == Py_None, but that's fine.
+  int deterministic = PyObject_IsTrue(deterministic_obj);
+  if (deterministic < 0) {
+    return NULL;
+  }
+
+  if (require_initialized && !self->message->IsInitialized()) {
     ScopedPyObjectPtr errors(FindInitializationErrors(self));
     if (errors == NULL) {
       return NULL;
@@ -1847,24 +1877,36 @@
                  GetMessageName(self).c_str(), PyString_AsString(joined.get()));
     return NULL;
   }
-  int size = self->message->ByteSize();
-  if (size <= 0) {
+
+  // Ok, arguments parsed and errors checked, now encode to a string
+  const size_t size = self->message->ByteSizeLong();
+  if (size == 0) {
     return PyBytes_FromString("");
   }
   PyObject* result = PyBytes_FromStringAndSize(NULL, size);
   if (result == NULL) {
     return NULL;
   }
-  char* buffer = PyBytes_AS_STRING(result);
-  self->message->SerializeWithCachedSizesToArray(
-      reinterpret_cast<uint8*>(buffer));
+  io::ArrayOutputStream out(PyBytes_AS_STRING(result), size);
+  io::CodedOutputStream coded_out(&out);
+  if (deterministic_obj != Py_None) {
+    coded_out.SetSerializationDeterministic(deterministic);
+  }
+  self->message->SerializeWithCachedSizes(&coded_out);
+  GOOGLE_CHECK(!coded_out.HadError());
   return result;
 }
 
-static PyObject* SerializePartialToString(CMessage* self) {
-  string contents;
-  self->message->SerializePartialToString(&contents);
-  return PyBytes_FromStringAndSize(contents.c_str(), contents.size());
+static PyObject* SerializeToString(
+    CMessage* self, PyObject* args, PyObject* kwargs) {
+  return InternalSerializeToString(self, args, kwargs,
+                                   /*require_initialized=*/true);
+}
+
+static PyObject* SerializePartialToString(
+    CMessage* self, PyObject* args, PyObject* kwargs) {
+  return InternalSerializeToString(self, args, kwargs,
+                                   /*require_initialized=*/false);
 }
 
 // Formats proto fields for ascii dumps using python formatting functions where
@@ -2535,7 +2577,10 @@
   if (state == NULL) {
     return  NULL;
   }
-  ScopedPyObjectPtr serialized(SerializePartialToString(self));
+  string contents;
+  self->message->SerializePartialToString(&contents);
+  ScopedPyObjectPtr serialized(
+      PyBytes_FromStringAndSize(contents.c_str(), contents.size()));
   if (serialized == NULL) {
     return NULL;
   }
@@ -2656,9 +2701,10 @@
   { "RegisterExtension", (PyCFunction)RegisterExtension, METH_O | METH_CLASS,
     "Registers an extension with the current message." },
   { "SerializePartialToString", (PyCFunction)SerializePartialToString,
-    METH_NOARGS,
+    METH_VARARGS | METH_KEYWORDS,
     "Serializes the message to a string, even if it isn't initialized." },
-  { "SerializeToString", (PyCFunction)SerializeToString, METH_NOARGS,
+  { "SerializeToString", (PyCFunction)SerializeToString,
+    METH_VARARGS | METH_KEYWORDS,
     "Serializes the message to a string, only for initialized messages." },
   { "SetInParent", (PyCFunction)SetInParent, METH_NOARGS,
     "Sets the has bit of the given field in its parent message." },
diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc
index e0b45bf..571bae2 100644
--- a/python/google/protobuf/pyext/message_factory.cc
+++ b/python/google/protobuf/pyext/message_factory.cc
@@ -133,11 +133,7 @@
 CMessageClass* GetOrCreateMessageClass(PyMessageFactory* self,
                                        const Descriptor* descriptor) {
   // This is the same implementation as MessageFactory.GetPrototype().
-  ScopedPyObjectPtr py_descriptor(
-      PyMessageDescriptor_FromDescriptor(descriptor));
-  if (py_descriptor == NULL) {
-    return NULL;
-  }
+
   // Do not create a MessageClass that already exists.
   hash_map<const Descriptor*, CMessageClass*>::iterator it =
       self->classes_by_descriptor->find(descriptor);
@@ -145,6 +141,11 @@
     Py_INCREF(it->second);
     return it->second;
   }
+  ScopedPyObjectPtr py_descriptor(
+      PyMessageDescriptor_FromDescriptor(descriptor));
+  if (py_descriptor == NULL) {
+    return NULL;
+  }
   // Create a new message class.
   ScopedPyObjectPtr args(Py_BuildValue(
       "s(){sOsOsO}", descriptor->name().c_str(),
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 9cb4e9a..5ad71db 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -46,6 +46,7 @@
 #include <google/protobuf/pyext/descriptor.h>
 #include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
 #include <google/protobuf/reflection.h>
 
@@ -137,9 +138,12 @@
   if (cmessage::AssureWritable(self->parent) == -1)
     return NULL;
   Message* message = self->message;
+
   Message* sub_message =
-      message->GetReflection()->AddMessage(message,
-                                           self->parent_field_descriptor);
+      message->GetReflection()->AddMessage(
+          message,
+          self->parent_field_descriptor,
+          self->child_message_class->py_message_factory->message_factory);
   CMessage* cmsg = cmessage::NewEmptyMessage(self->child_message_class);
   if (cmsg == NULL)
     return NULL;
@@ -266,10 +270,11 @@
     if (PySlice_Check(slice)) {
 #if PY_MAJOR_VERSION >= 3
       if (PySlice_GetIndicesEx(slice,
+                               length, &from, &to, &step, &slicelength) == -1) {
 #else
       if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
-#endif
                                length, &from, &to, &step, &slicelength) == -1) {
+#endif
         return -1;
       }
       return PySequence_DelSlice(self->child_messages, from, to);
@@ -335,6 +340,18 @@
   }
 }
 
+static PyObject* ToStr(RepeatedCompositeContainer* self) {
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  if (full_slice == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
+  if (list == NULL) {
+    return NULL;
+  }
+  return PyObject_Repr(list.get());
+}
+
 // ---------------------------------------------------------------------
 // sort()
 
@@ -607,7 +624,7 @@
   0,                                   //  tp_getattr
   0,                                   //  tp_setattr
   0,                                   //  tp_compare
-  0,                                   //  tp_repr
+  (reprfunc)repeated_composite_container::ToStr,      //  tp_repr
   0,                                   //  tp_as_number
   &repeated_composite_container::SqMethods,   //  tp_as_sequence
   &repeated_composite_container::MpMethods,   //  tp_as_mapping
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 95da85f..5499880 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -305,10 +305,12 @@
     length = Len(self);
 #if PY_MAJOR_VERSION >= 3
     if (PySlice_GetIndicesEx(slice,
+                             length, &from, &to, &step, &slicelength) == -1) {
 #else
     if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
-#endif
                              length, &from, &to, &step, &slicelength) == -1) {
+
+#endif
       return NULL;
     }
     return_list = true;
@@ -458,10 +460,11 @@
     length = reflection->FieldSize(*message, field_descriptor);
 #if PY_MAJOR_VERSION >= 3
     if (PySlice_GetIndicesEx(slice,
+                             length, &from, &to, &step, &slicelength) == -1) {
 #else
     if (PySlice_GetIndicesEx(reinterpret_cast<PySliceObject*>(slice),
-#endif
                              length, &from, &to, &step, &slicelength) == -1) {
+#endif
       return -1;
     }
     create_list = true;
@@ -656,6 +659,18 @@
   return item;
 }
 
+static PyObject* ToStr(RepeatedScalarContainer* self) {
+  ScopedPyObjectPtr full_slice(PySlice_New(NULL, NULL, NULL));
+  if (full_slice == NULL) {
+    return NULL;
+  }
+  ScopedPyObjectPtr list(Subscript(self, full_slice.get()));
+  if (list == NULL) {
+    return NULL;
+  }
+  return PyObject_Repr(list.get());
+}
+
 // The private constructor of RepeatedScalarContainer objects.
 PyObject *NewContainer(
     CMessage* parent, const FieldDescriptor* parent_field_descriptor) {
@@ -778,7 +793,7 @@
   0,                                   //  tp_getattr
   0,                                   //  tp_setattr
   0,                                   //  tp_compare
-  0,                                   //  tp_repr
+  (reprfunc)repeated_scalar_container::ToStr,      //  tp_repr
   0,                                   //  tp_as_number
   &repeated_scalar_container::SqMethods,   //  tp_as_sequence
   &repeated_scalar_container::MpMethods,   //  tp_as_mapping
diff --git a/python/google/protobuf/symbol_database.py b/python/google/protobuf/symbol_database.py
index 07341ef..5ad869f 100644
--- a/python/google/protobuf/symbol_database.py
+++ b/python/google/protobuf/symbol_database.py
@@ -78,10 +78,18 @@
     """
 
     desc = message.DESCRIPTOR
-    self._classes[desc.full_name] = message
-    self.pool.AddDescriptor(desc)
+    self._classes[desc] = message
+    self.RegisterMessageDescriptor(desc)
     return message
 
+  def RegisterMessageDescriptor(self, message_descriptor):
+    """Registers the given message descriptor in the local database.
+
+    Args:
+      message_descriptor: a descriptor.MessageDescriptor.
+    """
+    self.pool.AddDescriptor(message_descriptor)
+
   def RegisterEnumDescriptor(self, enum_descriptor):
     """Registers the given enum descriptor in the local database.
 
@@ -132,7 +140,7 @@
       KeyError: if the symbol could not be found.
     """
 
-    return self._classes[symbol]
+    return self._classes[self.pool.FindMessageTypeByName(symbol)]
 
   def GetMessages(self, files):
     # TODO(amauryfa): Fix the differences with MessageFactory.
@@ -153,20 +161,20 @@
       KeyError: if a file could not be found.
     """
 
-    def _GetAllMessageNames(desc):
+    def _GetAllMessages(desc):
       """Walk a message Descriptor and recursively yields all message names."""
-      yield desc.full_name
+      yield desc
       for msg_desc in desc.nested_types:
-        for full_name in _GetAllMessageNames(msg_desc):
-          yield full_name
+        for nested_desc in _GetAllMessages(msg_desc):
+          yield nested_desc
 
     result = {}
     for file_name in files:
       file_desc = self.pool.FindFileByName(file_name)
       for msg_desc in file_desc.message_types_by_name.values():
-        for full_name in _GetAllMessageNames(msg_desc):
+        for desc in _GetAllMessages(msg_desc):
           try:
-            result[full_name] = self._classes[full_name]
+            result[desc.full_name] = self._classes[desc]
           except KeyError:
             # This descriptor has no registered class, skip it.
             pass
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index c216e09..aaca78a 100755
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -126,7 +126,8 @@
                     float_format=None,
                     use_field_number=False,
                     descriptor_pool=None,
-                    indent=0):
+                    indent=0,
+                    message_formatter=None):
   """Convert protobuf message to text format.
 
   Floating point values can be formatted compactly with 15 digits of
@@ -148,6 +149,9 @@
     use_field_number: If True, print field numbers instead of names.
     descriptor_pool: A DescriptorPool used to resolve Any types.
     indent: The indent level, in terms of spaces, for pretty print.
+    message_formatter: A function(message, indent, as_one_line): unicode|None
+      to custom format selected sub-messages (usually based on message type).
+      Use to pretty print parts of the protobuf for easier diffing.
 
   Returns:
     A string of the text formatted protocol buffer message.
@@ -155,7 +159,7 @@
   out = TextWriter(as_utf8)
   printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets,
                      use_index_order, float_format, use_field_number,
-                     descriptor_pool)
+                     descriptor_pool, message_formatter)
   printer.PrintMessage(message)
   result = out.getvalue()
   out.close()
@@ -179,10 +183,11 @@
                  use_index_order=False,
                  float_format=None,
                  use_field_number=False,
-                 descriptor_pool=None):
+                 descriptor_pool=None,
+                 message_formatter=None):
   printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets,
                      use_index_order, float_format, use_field_number,
-                     descriptor_pool)
+                     descriptor_pool, message_formatter)
   printer.PrintMessage(message)
 
 
@@ -194,10 +199,11 @@
                as_one_line=False,
                pointy_brackets=False,
                use_index_order=False,
-               float_format=None):
+               float_format=None,
+               message_formatter=None):
   """Print a single field name/value pair."""
   printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets,
-                     use_index_order, float_format)
+                     use_index_order, float_format, message_formatter)
   printer.PrintField(field, value)
 
 
@@ -209,10 +215,11 @@
                     as_one_line=False,
                     pointy_brackets=False,
                     use_index_order=False,
-                    float_format=None):
+                    float_format=None,
+                    message_formatter=None):
   """Print a single field value (not including name)."""
   printer = _Printer(out, indent, as_utf8, as_one_line, pointy_brackets,
-                     use_index_order, float_format)
+                     use_index_order, float_format, message_formatter)
   printer.PrintFieldValue(field, value)
 
 
@@ -228,6 +235,9 @@
     wasn't found matching type_name.
   """
   # pylint: disable=g-import-not-at-top
+  if descriptor_pool is None:
+    from google.protobuf import descriptor_pool as pool_mod
+    descriptor_pool = pool_mod.Default()
   from google.protobuf import symbol_database
   database = symbol_database.Default()
   try:
@@ -250,7 +260,8 @@
                use_index_order=False,
                float_format=None,
                use_field_number=False,
-               descriptor_pool=None):
+               descriptor_pool=None,
+               message_formatter=None):
     """Initialize the Printer.
 
     Floating point values can be formatted compactly with 15 digits of
@@ -273,6 +284,9 @@
         used.
       use_field_number: If True, print field numbers instead of names.
       descriptor_pool: A DescriptorPool used to resolve Any types.
+      message_formatter: A function(message, indent, as_one_line): unicode|None
+        to custom format selected sub-messages (usually based on message type).
+        Use to pretty print parts of the protobuf for easier diffing.
     """
     self.out = out
     self.indent = indent
@@ -283,6 +297,7 @@
     self.float_format = float_format
     self.use_field_number = use_field_number
     self.descriptor_pool = descriptor_pool
+    self.message_formatter = message_formatter
 
   def _TryPrintAsAnyMessage(self, message):
     """Serializes if message is a google.protobuf.Any field."""
@@ -297,14 +312,27 @@
     else:
       return False
 
+  def _TryCustomFormatMessage(self, message):
+    formatted = self.message_formatter(message, self.indent, self.as_one_line)
+    if formatted is None:
+      return False
+
+    out = self.out
+    out.write(' ' * self.indent)
+    out.write(formatted)
+    out.write(' ' if self.as_one_line else '\n')
+    return True
+
   def PrintMessage(self, message):
     """Convert protobuf message to text format.
 
     Args:
       message: The protocol buffers message.
     """
+    if self.message_formatter and self._TryCustomFormatMessage(message):
+      return
     if (message.DESCRIPTOR.full_name == _ANY_FULL_TYPE_NAME and
-        self.descriptor_pool and self._TryPrintAsAnyMessage(message)):
+        self._TryPrintAsAnyMessage(message)):
       return
     fields = message.ListFields()
     if self.use_index_order:
@@ -426,6 +454,22 @@
           descriptor_pool=None):
   """Parses a text representation of a protocol message into a message.
 
+  NOTE: for historical reasons this function does not clear the input
+  message. This is different from what the binary msg.ParseFrom(...) does.
+
+  Example
+    a = MyProto()
+    a.repeated_field.append('test')
+    b = MyProto()
+
+    text_format.Parse(repr(a), b)
+    text_format.Parse(repr(a), b) # repeated_field contains ["test", "test"]
+
+    # Binary version:
+    b.ParseFromString(a.SerializeToString()) # repeated_field is now "test"
+
+  Caller is responsible for clearing the message as needed.
+
   Args:
     text: Message text representation.
     message: A protocol buffer message to merge into.
@@ -593,11 +637,6 @@
       ParseError: In case of text parsing problems.
     """
     message_descriptor = message.DESCRIPTOR
-    if (hasattr(message_descriptor, 'syntax') and
-        message_descriptor.syntax == 'proto3'):
-      # Proto3 doesn't represent presence so we can't test if multiple
-      # scalars have occurred.  We have to allow them.
-      self._allow_multiple_scalars = True
     if tokenizer.TryConsume('['):
       name = [tokenizer.ConsumeIdentifier()]
       while tokenizer.TryConsume('.'):
@@ -616,7 +655,11 @@
           field = None
         else:
           raise tokenizer.ParseErrorPreviousToken(
-              'Extension "%s" not registered.' % name)
+              'Extension "%s" not registered. '
+              'Did you import the _pb2 module which defines it? '
+              'If you are trying to place the extension in the MessageSet '
+              'field of another message that is in an Any or MessageSet field, '
+              'that message\'s _pb2 module must be imported as well' % name)
       elif message_descriptor != field.containing_type:
         raise tokenizer.ParseErrorPreviousToken(
             'Extension "%s" does not extend message type "%s".' %
@@ -695,17 +738,17 @@
   def _ConsumeAnyTypeUrl(self, tokenizer):
     """Consumes a google.protobuf.Any type URL and returns the type name."""
     # Consume "type.googleapis.com/".
-    tokenizer.ConsumeIdentifier()
+    prefix = [tokenizer.ConsumeIdentifier()]
     tokenizer.Consume('.')
-    tokenizer.ConsumeIdentifier()
+    prefix.append(tokenizer.ConsumeIdentifier())
     tokenizer.Consume('.')
-    tokenizer.ConsumeIdentifier()
+    prefix.append(tokenizer.ConsumeIdentifier())
     tokenizer.Consume('/')
     # Consume the fully-qualified type name.
     name = [tokenizer.ConsumeIdentifier()]
     while tokenizer.TryConsume('.'):
       name.append(tokenizer.ConsumeIdentifier())
-    return '.'.join(name)
+    return '.'.join(prefix), '.'.join(name)
 
   def _MergeMessageField(self, tokenizer, message, field):
     """Merges a single scalar field into a message.
@@ -728,7 +771,7 @@
 
     if (field.message_type.full_name == _ANY_FULL_TYPE_NAME and
         tokenizer.TryConsume('[')):
-      packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)
+      type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)
       tokenizer.Consume(']')
       tokenizer.TryConsume(':')
       if tokenizer.TryConsume('<'):
@@ -736,8 +779,6 @@
       else:
         tokenizer.Consume('{')
         expanded_any_end_token = '}'
-      if not self.descriptor_pool:
-        raise ParseError('Descriptor pool required to parse expanded Any field')
       expanded_any_sub_message = _BuildMessageFromTypeName(packed_type_name,
                                                            self.descriptor_pool)
       if not expanded_any_sub_message:
@@ -752,7 +793,8 @@
         any_message = getattr(message, field.name).add()
       else:
         any_message = getattr(message, field.name)
-      any_message.Pack(expanded_any_sub_message)
+      any_message.Pack(expanded_any_sub_message,
+                       type_url_prefix=type_url_prefix)
     elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
       if field.is_extension:
         sub_message = message.Extensions[field].add()
@@ -780,6 +822,12 @@
       else:
         getattr(message, field.name)[sub_message.key] = sub_message.value
 
+  @staticmethod
+  def _IsProto3Syntax(message):
+    message_descriptor = message.DESCRIPTOR
+    return (hasattr(message_descriptor, 'syntax') and
+            message_descriptor.syntax == 'proto3')
+
   def _MergeScalarField(self, tokenizer, message, field):
     """Merges a single scalar field into a message.
 
@@ -829,15 +877,20 @@
       else:
         getattr(message, field.name).append(value)
     else:
+      # Proto3 doesn't represent presence so we can't test if multiple scalars
+      # have occurred. We have to allow them.
+      can_check_presence = not self._IsProto3Syntax(message)
       if field.is_extension:
-        if not self._allow_multiple_scalars and message.HasExtension(field):
+        if (not self._allow_multiple_scalars and can_check_presence and
+            message.HasExtension(field)):
           raise tokenizer.ParseErrorPreviousToken(
               'Message type "%s" should not have multiple "%s" extensions.' %
               (message.DESCRIPTOR.full_name, field.full_name))
         else:
           message.Extensions[field] = value
       else:
-        if not self._allow_multiple_scalars and message.HasField(field.name):
+        if (not self._allow_multiple_scalars and can_check_presence and
+            message.HasField(field.name)):
           raise tokenizer.ParseErrorPreviousToken(
               'Message type "%s" should not have multiple "%s" fields.' %
               (message.DESCRIPTOR.full_name, field.name))
@@ -1088,7 +1141,7 @@
     """
     result = self.token
     if not self._IDENTIFIER_OR_NUMBER.match(result):
-      raise self.ParseError('Expected identifier or number.')
+      raise self.ParseError('Expected identifier or number, got %s.' % result)
     self.NextToken()
     return result
 
diff --git a/python/mox.py b/python/mox.py
index 257468e..43db021 100755
--- a/python/mox.py
+++ b/python/mox.py
@@ -778,7 +778,7 @@
       rhs: any python object
     """
 
-    raise NotImplementedError, 'method must be implemented by a subclass.'
+    raise NotImplementedError('method must be implemented by a subclass.')
 
   def __eq__(self, rhs):
     return self.equals(rhs)
diff --git a/python/release.sh b/python/release.sh
new file mode 100755
index 0000000..b0bf3b3
--- /dev/null
+++ b/python/release.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+
+set -ex
+
+function get_source_version() {
+  grep "__version__ = '.*'" python/google/protobuf/__init__.py | sed -r "s/__version__ = '(.*)'/\1/"
+}
+
+function run_install_test() {
+  local VERSION=$1
+  local PYTHON=$2
+  local PYPI=$3
+
+  virtualenv --no-site-packages -p `which $PYTHON` test-venv
+
+  # Intentionally put a broken protoc in the path to make sure installation
+  # doesn't require protoc installed.
+  touch test-venv/bin/protoc
+  chmod +x test-venv/bin/protoc
+
+  source test-venv/bin/activate
+  pip install -i ${PYPI} protobuf==${VERSION}
+  deactivate
+  rm -fr test-venv
+}
+
+
+[ $# -lt 1 ] && {
+  echo "Usage: $0 VERSION ["
+  echo ""
+  echo "Examples:"
+  echo "  Test 3.3.0 release using version number 3.3.0.dev1:"
+  echo "    $0 3.0.0 dev1"
+  echo "  Actually release 3.3.0 to PyPI:"
+  echo "    $0 3.3.0"
+  exit 1
+}
+VERSION=$1
+DEV=$2
+
+# Make sure we are in a protobuf source tree.
+[ -f "python/google/protobuf/__init__.py" ] || {
+  echo "This script must be ran under root of protobuf source tree."
+  exit 1
+}
+
+# Make sure all files are world-readable.
+find python -type d -exec chmod a+r,a+x {} +
+find python -type f -exec chmod a+r {} +
+
+# Check that the supplied version number matches what's inside the source code.
+SOURCE_VERSION=`get_source_version`
+
+[ "${VERSION}" == "${SOURCE_VERSION}" -o "${VERSION}.${DEV}" == "${SOURCE_VERSION}" ] || {
+  echo "Version number specified on the command line ${VERSION} doesn't match"
+  echo "the actual version number in the source code: ${SOURCE_VERSION}"
+  exit 1
+}
+
+TESTING_ONLY=1
+TESTING_VERSION=${VERSION}.${DEV}
+if [ -z "${DEV}" ]; then
+  read -p "You are releasing ${VERSION} to PyPI. Are you sure? [y/n]" -r
+  echo
+  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+    exit 1
+  fi
+  TESTING_ONLY=0
+  TESTING_VERSION=${VERSION}
+else
+  # Use dev version number for testing.
+  sed -i -r "s/__version__ = '.*'/__version__ = '${VERSION}.${DEV}'/" python/google/protobuf/__init__.py
+fi
+
+cd python
+
+# Run tests locally.
+python setup.py build
+python setup.py test
+
+# Deploy source package to testing PyPI
+python setup.py sdist upload -r https://test.pypi.org/legacy/
+
+# Test locally with different python versions.
+run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple
+run_install_test ${TESTING_VERSION} python3.4 https://test.pypi.org/simple
+
+# Deploy egg/wheel packages to testing PyPI and test again.
+python setup.py bdist_egg bdist_wheel upload -r https://test.pypi.org/legacy/
+run_install_test ${TESTING_VERSION} python2.7 https://test.pypi.org/simple
+run_install_test ${TESTING_VERSION} python3.4 https://test.pypi.org/simple
+
+echo "All install tests have passed using testing PyPI."
+
+if [ $TESTING_ONLY -eq 0 ]; then
+  read -p "Publish to PyPI? [y/n]" -r
+  echo
+  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
+    exit 1
+  fi
+  echo "Publishing to PyPI..."
+  # Be sure to run build before sdist, because otherwise sdist will not include
+  # well-known types.
+  python setup.py clean build sdist upload
+  # Be sure to run clean before bdist_xxx, because otherwise bdist_xxx will
+  # include files you may not want in the package. E.g., if you have built
+  # and tested with --cpp_implemenation, bdist_xxx will include the _message.so
+  # file even when you no longer pass the --cpp_implemenation flag. See:
+  #   https://github.com/google/protobuf/issues/3042
+  python setup.py clean build bdist_egg bdist_wheel upload
+else
+  # Set the version number back (i.e., remove dev suffix).
+  sed -i -r "s/__version__ = '.*'/__version__ = '${VERSION}'/" google/protobuf/__init__.py
+fi
diff --git a/python/release/wheel/Dockerfile b/python/release/wheel/Dockerfile
new file mode 100644
index 0000000..f38ec2f
--- /dev/null
+++ b/python/release/wheel/Dockerfile
@@ -0,0 +1,6 @@
+FROM quay.io/pypa/manylinux1_x86_64
+
+RUN yum install -y libtool
+RUN /opt/python/cp27-cp27mu/bin/pip install twine
+
+COPY protobuf_optimized_pip.sh /
diff --git a/python/release/wheel/README.md b/python/release/wheel/README.md
new file mode 100644
index 0000000..edda2cd
--- /dev/null
+++ b/python/release/wheel/README.md
@@ -0,0 +1,17 @@
+Description
+------------------------------
+This directory is used to build released wheels according to PEP513 and upload
+them to pypi.
+
+Usage
+------------------------------
+For example, to release 3.3.0:
+    ./protobuf_optimized_pip.sh 3.3.0 PYPI_USERNAME PYPI_PASSWORD
+
+Structure
+------------------------------
+| Source                    | Source                                                       |
+|--------------------------------------|---------------------------------------------------|
+| protobuf_optimized_pip.sh | Entry point. Calling Dockerfile and build_wheel_manylinux.sh |
+| Dockerfile                | Build docker image according to PEP513.                      |
+| build_wheel_manylinux.sh  | Build wheel packages in the docker container.                |
diff --git a/python/release/wheel/build_wheel_manylinux.sh b/python/release/wheel/build_wheel_manylinux.sh
new file mode 100755
index 0000000..39fd8c1
--- /dev/null
+++ b/python/release/wheel/build_wheel_manylinux.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# Print usage and fail.
+function usage() {
+  echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION PYPI_USERNAME PYPI_PASSWORD" >&2
+  exit 1   # Causes caller to exit because we use -e.
+}
+
+# Validate arguments.
+if [ $0 != ./build_wheel_manylinux.sh ]; then
+  echo "Please run this script from the directory in which it is located." >&2
+  exit 1
+fi
+
+if [ $# -lt 3 ]; then
+  usage
+  exit 1
+fi
+
+PROTOBUF_VERSION=$1
+PYPI_USERNAME=$2
+PYPI_PASSWORD=$3
+
+docker rmi protobuf-python-wheel
+docker build . -t protobuf-python-wheel
+docker run --rm protobuf-python-wheel ./protobuf_optimized_pip.sh $PROTOBUF_VERSION $PYPI_USERNAME $PYPI_PASSWORD
+docker rmi protobuf-python-wheel
diff --git a/python/release/wheel/protobuf_optimized_pip.sh b/python/release/wheel/protobuf_optimized_pip.sh
new file mode 100755
index 0000000..064d1d2
--- /dev/null
+++ b/python/release/wheel/protobuf_optimized_pip.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+
+# DO NOT use this script manually! Called by docker.
+
+set -ex
+
+# Print usage and fail.
+function usage() {
+  echo "Usage: protobuf_optimized_pip.sh PROTOBUF_VERSION PYPI_USERNAME PYPI_PASSWORD" >&2
+  exit 1   # Causes caller to exit because we use -e.
+}
+
+# Build wheel
+function build_wheel() {
+  PYTHON_VERSION=$1
+  PYTHON_BIN=/opt/python/${PYTHON_VERSION}/bin/python
+
+  $PYTHON_BIN setup.py bdist_wheel --cpp_implementation --compile_static_extension
+  auditwheel repair dist/protobuf-${PROTOBUF_VERSION}-${PYTHON_VERSION}-linux_x86_64.whl
+}
+
+# Validate arguments.
+if [ $0 != ./protobuf_optimized_pip.sh ]; then
+  echo "Please run this script from the directory in which it is located." >&2
+  exit 1
+fi
+
+if [ $# -lt 3 ]; then
+  usage
+  exit 1
+fi
+
+PROTOBUF_VERSION=$1
+PYPI_USERNAME=$2
+PYPI_PASSWORD=$3
+
+DIR=${PWD}/'protobuf-python-build'
+PYTHON_VERSIONS=('cp27-cp27mu' 'cp33-cp33m' 'cp34-cp34m' 'cp35-cp35m' 'cp36-cp36m')
+
+mkdir -p ${DIR}
+cd ${DIR}
+curl -SsL -O https://github.com/google/protobuf/archive/v${PROTOBUF_VERSION}.tar.gz
+tar xzf v${PROTOBUF_VERSION}.tar.gz
+cd $DIR/protobuf-${PROTOBUF_VERSION}
+
+# Autoconf on centos 5.11 cannot recognize AC_PROG_OBJC.
+sed -i '/AC_PROG_OBJC/d' configure.ac
+sed -i 's/conformance\/Makefile//g' configure.ac
+
+# Use the /usr/bin/autoconf and related tools to pick the correct aclocal macros
+export PATH="/usr/bin:$PATH"
+
+# Build protoc
+./autogen.sh
+CXXFLAGS="-fPIC -g -O2" ./configure
+make -j8
+export PROTOC=$DIR/src/protoc
+
+cd python
+
+for PYTHON_VERSION in "${PYTHON_VERSIONS[@]}"
+do
+  build_wheel $PYTHON_VERSION
+done
+
+/opt/python/cp27-cp27mu/bin/twine upload wheelhouse/* <<!
+$PYPI_USERNAME
+$PYPI_PASSWORD
+!
diff --git a/python/setup.py b/python/setup.py
index a202670..70b7de5 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -80,6 +80,7 @@
   generate_proto("../src/google/protobuf/any_test.proto", False)
   generate_proto("../src/google/protobuf/map_unittest.proto", False)
   generate_proto("../src/google/protobuf/test_messages_proto3.proto", False)
+  generate_proto("../src/google/protobuf/test_messages_proto2.proto", False)
   generate_proto("../src/google/protobuf/unittest_arena.proto", False)
   generate_proto("../src/google/protobuf/unittest_no_arena.proto", False)
   generate_proto("../src/google/protobuf/unittest_no_arena_import.proto", False)
diff --git a/python/tox.ini b/python/tox.ini
index 1600db2..38a81b4 100644
--- a/python/tox.ini
+++ b/python/tox.ini
@@ -1,6 +1,6 @@
 [tox]
 envlist =
-    py{26,27,33,34}-{cpp,python}
+    py{27,33,34,35,36}-{cpp,python}
 
 [testenv]
 usedevelop=true
@@ -9,6 +9,7 @@
     cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs
     cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs
     cpp: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
+    python: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
 commands =
     python setup.py -q build_py
     python: python setup.py -q build
diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c
index 6ce6d08..edbbe6a 100644
--- a/ruby/ext/google/protobuf_c/encode_decode.c
+++ b/ruby/ext/google/protobuf_c/encode_decode.c
@@ -280,11 +280,6 @@
   { MapParseFrame_mark, MapParseFrame_free, NULL },
 };
 
-// Array of Ruby objects wrapping map_parse_frame_t.
-// We don't allow multiple concurrent decodes, so we assume that this global
-// variable is specific to the "current" decode.
-VALUE map_parse_frames;
-
 static map_parse_frame_t* map_push_frame(VALUE map,
                                          const map_handlerdata_t* handlerdata) {
   map_parse_frame_t* frame = ALLOC(map_parse_frame_t);
@@ -293,16 +288,12 @@
   native_slot_init(handlerdata->key_field_type, &frame->key_storage);
   native_slot_init(handlerdata->value_field_type, &frame->value_storage);
 
-  rb_ary_push(map_parse_frames,
+  Map_set_frame(map,
               TypedData_Wrap_Struct(rb_cObject, &MapParseFrame_type, frame));
 
   return frame;
 }
 
-static void map_pop_frame() {
-  rb_ary_pop(map_parse_frames);
-}
-
 // Handler to begin a map entry: allocates a temporary frame. This is the
 // 'startsubmsg' handler on the msgdef that contains the map field.
 static void *startmapentry_handler(void *closure, const void *hd) {
@@ -336,7 +327,7 @@
       &frame->value_storage);
 
   Map_index_set(frame->map, key, value);
-  map_pop_frame();
+  Map_set_frame(frame->map, Qnil);
 
   return true;
 }
@@ -775,10 +766,6 @@
   msg_rb = rb_class_new_instance(0, NULL, msgklass);
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
 
-  // We generally expect this to be clear already, but clear it in case parsing
-  // previously got interrupted somehow.
-  rb_ary_clear(map_parse_frames);
-
   {
     const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
     const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
@@ -823,10 +810,6 @@
   msg_rb = rb_class_new_instance(0, NULL, msgklass);
   TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
 
-  // We generally expect this to be clear already, but clear it in case parsing
-  // previously got interrupted somehow.
-  rb_ary_clear(map_parse_frames);
-
   {
     const upb_json_parsermethod* method = msgdef_jsonparsermethod(desc);
     stackenv se;
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 4be54c3..26e22dc 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -146,6 +146,7 @@
   Map* self = _self;
 
   rb_gc_mark(self->value_type_class);
+  rb_gc_mark(self->parse_frame);
 
   if (self->value_type == UPB_TYPE_STRING ||
       self->value_type == UPB_TYPE_BYTES ||
@@ -174,6 +175,12 @@
   return TypedData_Wrap_Struct(klass, &Map_type, self);
 }
 
+VALUE Map_set_frame(VALUE map, VALUE val) {
+  Map* self = ruby_to_Map(map);
+  self->parse_frame = val;
+  return val;
+}
+
 static bool needs_typeclass(upb_fieldtype_t type) {
   switch (type) {
     case UPB_TYPE_MESSAGE:
@@ -227,6 +234,7 @@
 
   self->key_type = ruby_to_fieldtype(argv[0]);
   self->value_type = ruby_to_fieldtype(argv[1]);
+  self->parse_frame = Qnil;
 
   // Check that the key type is an allowed type.
   switch (self->key_type) {
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index 9896366..7cde4ae 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -112,6 +112,4 @@
 
   upb_def_to_ruby_obj_map = rb_hash_new();
   rb_gc_register_address(&upb_def_to_ruby_obj_map);
-  map_parse_frames = rb_ary_new();
-  rb_gc_register_address(&map_parse_frames);
 }
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index 520e9d9..f4b110f 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -166,8 +166,6 @@
 extern VALUE cError;
 extern VALUE cParseError;
 
-extern VALUE map_parse_frames;
-
 // We forward-declare all of the Ruby method implementations here because we
 // sometimes call the methods directly across .c files, rather than going
 // through Ruby's method dispatching (e.g. during message parse). It's cleaner
@@ -397,6 +395,7 @@
   upb_fieldtype_t key_type;
   upb_fieldtype_t value_type;
   VALUE value_type_class;
+  VALUE parse_frame;
   upb_strtable table;
 } Map;
 
@@ -405,6 +404,7 @@
 VALUE Map_alloc(VALUE klass);
 VALUE Map_init(int argc, VALUE* argv, VALUE self);
 void Map_register(VALUE module);
+VALUE Map_set_frame(VALUE self, VALUE val);
 
 extern const rb_data_type_t Map_type;
 extern VALUE cMap;
diff --git a/ruby/ext/google/protobuf_c/upb.c b/ruby/ext/google/protobuf_c/upb.c
index e0c56f8..90d1f0c 100644
--- a/ruby/ext/google/protobuf_c/upb.c
+++ b/ruby/ext/google/protobuf_c/upb.c
@@ -377,13 +377,14 @@
     } else if (def->type == UPB_DEF_FIELD) {
       upb_status_seterrmsg(s, "standalone fielddefs can not be frozen");
       goto err;
-    } else if (def->type == UPB_DEF_ENUM) {
-      if (!upb_validate_enumdef(upb_dyncast_enumdef(def), s)) {
-        goto err;
-      }
     } else {
       /* Set now to detect transitive closure in the second pass. */
       def->came_from_user = true;
+
+      if (def->type == UPB_DEF_ENUM &&
+          !upb_validate_enumdef(upb_dyncast_enumdef(def), s)) {
+        goto err;
+      }
     }
   }
 
@@ -710,43 +711,6 @@
   return f;
 }
 
-static upb_fielddef *upb_fielddef_dup(const upb_fielddef *f,
-                                      const void *owner) {
-  const char *srcname;
-  upb_fielddef *newf = upb_fielddef_new(owner);
-  if (!newf) return NULL;
-  upb_fielddef_settype(newf, upb_fielddef_type(f));
-  upb_fielddef_setlabel(newf, upb_fielddef_label(f));
-  upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
-  upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
-  if (f->default_is_string && f->defaultval.bytes) {
-    str_t *s = f->defaultval.bytes;
-    upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
-  } else {
-    newf->default_is_string = f->default_is_string;
-    newf->defaultval = f->defaultval;
-  }
-
-  if (f->subdef_is_symbolic) {
-    srcname = f->sub.name;  /* Might be NULL. */
-  } else {
-    srcname = f->sub.def ? upb_def_fullname(f->sub.def) : NULL;
-  }
-  if (srcname) {
-    char *newname = upb_gmalloc(strlen(f->sub.def->fullname) + 2);
-    if (!newname) {
-      upb_fielddef_unref(newf, owner);
-      return NULL;
-    }
-    strcpy(newname, ".");
-    strcat(newname, f->sub.def->fullname);
-    upb_fielddef_setsubdefname(newf, newname, NULL);
-    upb_gfree(newname);
-  }
-
-  return newf;
-}
-
 bool upb_fielddef_typeisset(const upb_fielddef *f) {
   return f->type_is_set_;
 }
@@ -1426,44 +1390,6 @@
   return NULL;
 }
 
-static upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner);
-
-static upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
-  bool ok;
-  upb_msg_field_iter i;
-  upb_msg_oneof_iter o;
-
-  upb_msgdef *newm = upb_msgdef_new(owner);
-  if (!newm) return NULL;
-  ok = upb_def_setfullname(upb_msgdef_upcast_mutable(newm),
-                           upb_def_fullname(upb_msgdef_upcast(m)),
-                           NULL);
-  newm->map_entry = m->map_entry;
-  newm->syntax = m->syntax;
-  UPB_ASSERT(ok);
-  for(upb_msg_field_begin(&i, m);
-      !upb_msg_field_done(&i);
-      upb_msg_field_next(&i)) {
-    upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f);
-    /* Fields in oneofs are dup'd below. */
-    if (upb_fielddef_containingoneof(f)) continue;
-    if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
-      upb_msgdef_unref(newm, owner);
-      return NULL;
-    }
-  }
-  for(upb_msg_oneof_begin(&o, m);
-      !upb_msg_oneof_done(&o);
-      upb_msg_oneof_next(&o)) {
-    upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f);
-    if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) {
-      upb_msgdef_unref(newm, owner);
-      return NULL;
-    }
-  }
-  return newm;
-}
-
 bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) {
   upb_def *d = upb_msgdef_upcast_mutable(m);
   return upb_def_freeze(&d, 1, status);
@@ -1764,24 +1690,6 @@
   return NULL;
 }
 
-static upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o,
-                                      const void *owner) {
-  bool ok;
-  upb_oneof_iter i;
-  upb_oneofdef *newo = upb_oneofdef_new(owner);
-  if (!newo) return NULL;
-  ok = upb_oneofdef_setname(newo, upb_oneofdef_name(o), NULL);
-  UPB_ASSERT(ok);
-  for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) {
-    upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f);
-    if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) {
-      upb_oneofdef_unref(newo, owner);
-      return NULL;
-    }
-  }
-  return newo;
-}
-
 const char *upb_oneofdef_name(const upb_oneofdef *o) { return o->name; }
 
 bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s) {
@@ -1950,6 +1858,8 @@
   upb_inttable_uninit(&f->deps);
   upb_gfree((void*)f->name);
   upb_gfree((void*)f->package);
+  upb_gfree((void*)f->phpprefix);
+  upb_gfree((void*)f->phpnamespace);
   upb_gfree(f);
 }
 
@@ -1964,6 +1874,8 @@
 
   f->package = NULL;
   f->name = NULL;
+  f->phpprefix = NULL;
+  f->phpnamespace = NULL;
   f->syntax = UPB_SYNTAX_PROTO2;
 
   if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl,
@@ -1998,6 +1910,14 @@
   return f->package;
 }
 
+const char *upb_filedef_phpprefix(const upb_filedef *f) {
+  return f->phpprefix;
+}
+
+const char *upb_filedef_phpnamespace(const upb_filedef *f) {
+  return f->phpnamespace;
+}
+
 upb_syntax_t upb_filedef_syntax(const upb_filedef *f) {
   return f->syntax;
 }
@@ -2054,6 +1974,30 @@
   return true;
 }
 
+bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix,
+                              upb_status *s) {
+  phpprefix = upb_gstrdup(phpprefix);
+  if (!phpprefix) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+  upb_gfree((void*)f->phpprefix);
+  f->phpprefix = phpprefix;
+  return true;
+}
+
+bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace,
+                                 upb_status *s) {
+  phpnamespace = upb_gstrdup(phpnamespace);
+  if (!phpnamespace) {
+    upb_upberr_setoom(s);
+    return false;
+  }
+  upb_gfree((void*)f->phpnamespace);
+  f->phpnamespace = phpnamespace;
+  return true;
+}
+
 bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax,
                            upb_status *s) {
   UPB_UNUSED(s);
@@ -2240,57 +2184,14 @@
                            fullname);
         goto err;
       }
-      upb_def_donateref(def, ref_donor, s);
       if (!upb_strtable_insert(&addtab, fullname, upb_value_ptr(def)))
         goto oom_err;
-      def->came_from_user = true;
-    }
-  }
-
-  /* Add standalone fielddefs (ie. extensions) to the appropriate messages.
-   * If the appropriate message only exists in the existing symtab, duplicate
-   * it so we have a mutable copy we can add the fields to. */
-  for (i = 0; i < n; i++) {
-    upb_def *def = defs[i];
-    upb_fielddef *f = upb_dyncast_fielddef_mutable(def);
-    const char *msgname;
-    upb_value v;
-    upb_msgdef *m;
-
-    if (!f) continue;
-    msgname = upb_fielddef_containingtypename(f);
-    /* We validated this earlier in this function. */
-    UPB_ASSERT(msgname);
-
-    /* If the extendee name is absolutely qualified, move past the initial ".".
-     * TODO(haberman): it is not obvious what it would mean if this was not
-     * absolutely qualified. */
-    if (msgname[0] == '.') {
-      msgname++;
+      upb_def_donateref(def, ref_donor, s);
     }
 
-    if (upb_strtable_lookup(&addtab, msgname, &v)) {
-      /* Extendee is in the set of defs the user asked us to add. */
-      m = upb_value_getptr(v);
-    } else {
-      /* Need to find and dup the extendee from the existing symtab. */
-      const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname);
-      if (!frozen_m) {
-        upb_status_seterrf(status,
-                           "Tried to extend message %s that does not exist "
-                           "in this SymbolTable.",
-                           msgname);
-        goto err;
-      }
-      m = upb_msgdef_dup(frozen_m, s);
-      if (!m) goto oom_err;
-      if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) {
-        upb_msgdef_unref(m, s);
-        goto oom_err;
-      }
-    }
-
-    if (!upb_msgdef_addfield(m, f, ref_donor, status)) {
+    if (upb_dyncast_fielddef_mutable(def)) {
+      /* TODO(haberman): allow adding extensions attached to files. */
+      upb_status_seterrf(status, "Can't add extensions to symtab.\n");
       goto err;
     }
   }
@@ -2372,15 +2273,9 @@
   for (i = 0; i < add_n; i++) {
     upb_def *def = (upb_def*)add_objs[i];
     const char *name = upb_def_fullname(def);
-    upb_value v;
     bool success;
-
-    if (upb_strtable_remove(&s->symtab, name, &v)) {
-      const upb_def *def = upb_value_getptr(v);
-      upb_def_unref(def, s);
-    }
     success = upb_strtable_insert(&s->symtab, name, upb_value_ptr(def));
-    UPB_ASSERT(success == true);
+    UPB_ASSERT(success);
   }
   upb_gfree(add_defs);
   return true;
@@ -3737,8 +3632,7 @@
           CHECK_TRUE(upb_sink_putfloat(sink, sel, upb_msgval_getfloat(val)));
           break;
         case UPB_TYPE_DOUBLE:
-          CHECK_TRUE(
-              upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val)));
+          CHECK_TRUE(upb_sink_putdouble(sink, sel, upb_msgval_getdouble(val)));
           break;
         case UPB_TYPE_BOOL:
           CHECK_TRUE(upb_sink_putbool(sink, sel, upb_msgval_getbool(val)));
@@ -3748,15 +3642,13 @@
           CHECK_TRUE(upb_sink_putint32(sink, sel, upb_msgval_getint32(val)));
           break;
         case UPB_TYPE_UINT32:
-          CHECK_TRUE(
-              upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val)));
+          CHECK_TRUE(upb_sink_putuint32(sink, sel, upb_msgval_getuint32(val)));
           break;
         case UPB_TYPE_INT64:
           CHECK_TRUE(upb_sink_putint64(sink, sel, upb_msgval_getint64(val)));
           break;
         case UPB_TYPE_UINT64:
-          CHECK_TRUE(
-              upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val)));
+          CHECK_TRUE(upb_sink_putuint64(sink, sel, upb_msgval_getuint64(val)));
           break;
         case UPB_TYPE_STRING:
         case UPB_TYPE_BYTES:
@@ -6545,14 +6437,14 @@
 
 
 static const upb_msgdef msgs[22];
-static const upb_fielddef fields[105];
+static const upb_fielddef fields[107];
 static const upb_enumdef enums[5];
 static const upb_tabent strentries[236];
 static const upb_tabent intentries[18];
-static const upb_tabval arrays[184];
+static const upb_tabval arrays[187];
 
 #ifdef UPB_DEBUG_REFS
-static upb_inttable reftables[264];
+static upb_inttable reftables[268];
 #endif
 
 static const upb_msgdef msgs[22] = {
@@ -6567,20 +6459,20 @@
   UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 12, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[42], 11, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[56]), false, UPB_SYNTAX_PROTO2, &reftables[16], &reftables[17]),
   UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 42, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[53], 13, 12), UPB_STRTABLE_INIT(12, 15, UPB_CTYPE_PTR, 4, &strentries[72]), false, UPB_SYNTAX_PROTO2, &reftables[18], &reftables[19]),
   UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[66], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[88]), false, UPB_SYNTAX_PROTO2, &reftables[20], &reftables[21]),
-  UPB_MSGDEF_INIT("google.protobuf.FileOptions", 31, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 39, 15), UPB_STRTABLE_INIT(16, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]),
-  UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[107], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]),
-  UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[115], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]),
-  UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[122], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]),
-  UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[123], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]),
-  UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[125], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]),
-  UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[129], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]),
-  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[130], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]),
-  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[132], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]),
-  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[139], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]),
-  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[148], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]),
+  UPB_MSGDEF_INIT("google.protobuf.FileOptions", 37, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[68], 42, 17), UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_PTR, 5, &strentries[92]), false, UPB_SYNTAX_PROTO2, &reftables[22], &reftables[23]),
+  UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 10, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[110], 8, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[124]), false, UPB_SYNTAX_PROTO2, &reftables[24], &reftables[25]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 15, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[118], 7, 6), UPB_STRTABLE_INIT(6, 7, UPB_CTYPE_PTR, 3, &strentries[132]), false, UPB_SYNTAX_PROTO2, &reftables[26], &reftables[27]),
+  UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[10], &arrays[125], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[140]), false, UPB_SYNTAX_PROTO2, &reftables[28], &reftables[29]),
+  UPB_MSGDEF_INIT("google.protobuf.OneofDescriptorProto", 5, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[126], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[144]), false, UPB_SYNTAX_PROTO2, &reftables[30], &reftables[31]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[128], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[148]), false, UPB_SYNTAX_PROTO2, &reftables[32], &reftables[33]),
+  UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 7, 1, UPB_INTTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &intentries[14], &arrays[132], 1, 0), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[152]), false, UPB_SYNTAX_PROTO2, &reftables[34], &reftables[35]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[133], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[156]), false, UPB_SYNTAX_PROTO2, &reftables[36], &reftables[37]),
+  UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 19, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[135], 7, 5), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &strentries[160]), false, UPB_SYNTAX_PROTO2, &reftables[38], &reftables[39]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[142], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[168]), false, UPB_SYNTAX_PROTO2, &reftables[40], &reftables[41]),
+  UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[151], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[184]), false, UPB_SYNTAX_PROTO2, &reftables[42], &reftables[43]),
 };
 
-static const upb_fielddef fields[105] = {
+static const upb_fielddef fields[107] = {
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "aggregate_value", 8, &msgs[20], NULL, 15, 6, {0},&reftables[44], &reftables[45]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "allow_alias", 2, &msgs[4], NULL, 6, 1, {0},&reftables[46], &reftables[47]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "cc_enable_arenas", 31, &msgs[11], NULL, 23, 12, {0},&reftables[48], &reftables[49]),
@@ -6590,18 +6482,18 @@
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "ctype", 1, &msgs[8], (const upb_def*)(&enums[2]), 6, 1, {0},&reftables[56], &reftables[57]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "default_value", 7, &msgs[7], NULL, 16, 7, {0},&reftables[58], &reftables[59]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "dependency", 3, &msgs[9], NULL, 30, 8, {0},&reftables[60], &reftables[61]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[62], &reftables[63]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[64], &reftables[65]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[66], &reftables[67]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[8], NULL, 8, 3, {0},&reftables[62], &reftables[63]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[14], NULL, 6, 1, {0},&reftables[64], &reftables[65]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[12], NULL, 8, 3, {0},&reftables[66], &reftables[67]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 23, &msgs[11], NULL, 21, 10, {0},&reftables[68], &reftables[69]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[70], &reftables[71]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[72], &reftables[73]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[74], &reftables[75]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 1, &msgs[6], NULL, 6, 1, {0},&reftables[70], &reftables[71]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 3, &msgs[4], NULL, 7, 2, {0},&reftables[72], &reftables[73]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "deprecated", 33, &msgs[17], NULL, 6, 1, {0},&reftables[74], &reftables[75]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, false, "double_value", 6, &msgs[20], NULL, 11, 4, {0},&reftables[76], &reftables[77]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[2], NULL, 3, 1, {0},&reftables[78], &reftables[79]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[80], &reftables[81]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[82], &reftables[83]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[84], &reftables[85]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 5, &msgs[9], (const upb_def*)(&msgs[3]), 13, 1, {0},&reftables[82], &reftables[83]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "enum_type", 4, &msgs[0], (const upb_def*)(&msgs[3]), 18, 2, {0},&reftables[84], &reftables[85]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "extendee", 2, &msgs[7], NULL, 7, 2, {0},&reftables[86], &reftables[87]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 6, &msgs[0], (const upb_def*)(&msgs[7]), 24, 4, {0},&reftables[88], &reftables[89]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "extension", 7, &msgs[9], (const upb_def*)(&msgs[7]), 19, 3, {0},&reftables[90], &reftables[91]),
@@ -6630,77 +6522,79 @@
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "message_set_wire_format", 1, &msgs[12], NULL, 6, 1, {0},&reftables[136], &reftables[137]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "message_type", 4, &msgs[9], (const upb_def*)(&msgs[0]), 10, 0, {0},&reftables[138], &reftables[139]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "method", 2, &msgs[16], (const upb_def*)(&msgs[13]), 6, 0, {0},&reftables[140], &reftables[141]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[142], &reftables[143]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[144], &reftables[145]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[146], &reftables[147]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[148], &reftables[149]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[150], &reftables[151]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[152], &reftables[153]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[154], &reftables[155]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[156], &reftables[157]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[158], &reftables[159]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "name", 2, &msgs[20], (const upb_def*)(&msgs[21]), 5, 0, {0},&reftables[142], &reftables[143]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[5], NULL, 4, 1, {0},&reftables[144], &reftables[145]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[9], NULL, 22, 6, {0},&reftables[146], &reftables[147]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[3], NULL, 8, 2, {0},&reftables[148], &reftables[149]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[16], NULL, 8, 2, {0},&reftables[150], &reftables[151]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[15], NULL, 2, 0, {0},&reftables[152], &reftables[153]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[13], NULL, 4, 1, {0},&reftables[154], &reftables[155]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[7], NULL, 4, 1, {0},&reftables[156], &reftables[157]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "name", 1, &msgs[0], NULL, 32, 8, {0},&reftables[158], &reftables[159]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, false, "name_part", 1, &msgs[21], NULL, 2, 0, {0},&reftables[160], &reftables[161]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, false, "negative_int_value", 5, &msgs[20], NULL, 10, 3, {0},&reftables[162], &reftables[163]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "nested_type", 3, &msgs[0], (const upb_def*)(&msgs[0]), 15, 1, {0},&reftables[164], &reftables[165]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[12], NULL, 7, 2, {0},&reftables[166], &reftables[167]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[168], &reftables[169]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[170], &reftables[171]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 3, &msgs[7], NULL, 10, 3, {0},&reftables[168], &reftables[169]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "number", 2, &msgs[5], NULL, 7, 2, {0},&reftables[170], &reftables[171]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "objc_class_prefix", 36, &msgs[11], NULL, 24, 13, {0},&reftables[172], &reftables[173]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "oneof_decl", 8, &msgs[0], (const upb_def*)(&msgs[15]), 28, 6, {0},&reftables[174], &reftables[175]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "oneof_index", 9, &msgs[7], NULL, 19, 8, {0},&reftables[176], &reftables[177]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "optimize_for", 9, &msgs[11], (const upb_def*)(&enums[4]), 12, 3, {0},&reftables[178], &reftables[179]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 7, &msgs[0], (const upb_def*)(&msgs[12]), 25, 5, {0},&reftables[180], &reftables[181]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[9], (const upb_def*)(&msgs[11]), 20, 4, {0},&reftables[182], &reftables[183]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[184], &reftables[185]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[186], &reftables[187]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 8, &msgs[7], (const upb_def*)(&msgs[8]), 3, 0, {0},&reftables[184], &reftables[185]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 4, &msgs[13], (const upb_def*)(&msgs[14]), 3, 0, {0},&reftables[186], &reftables[187]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[16], (const upb_def*)(&msgs[17]), 7, 1, {0},&reftables[188], &reftables[189]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[190], &reftables[191]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[192], &reftables[193]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[3], (const upb_def*)(&msgs[4]), 7, 1, {0},&reftables[190], &reftables[191]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "options", 3, &msgs[5], (const upb_def*)(&msgs[6]), 3, 0, {0},&reftables[192], &reftables[193]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "output_type", 3, &msgs[13], NULL, 10, 3, {0},&reftables[194], &reftables[195]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "package", 2, &msgs[9], NULL, 25, 7, {0},&reftables[196], &reftables[197]),
   UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "packed", 2, &msgs[8], NULL, 7, 2, {0},&reftables[198], &reftables[199]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "path", 1, &msgs[19], NULL, 4, 0, {0},&reftables[200], &reftables[201]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[202], &reftables[203]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[204], &reftables[205]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[206], &reftables[207]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[208], &reftables[209]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[210], &reftables[211]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[212], &reftables[213]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[214], &reftables[215]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[216], &reftables[217]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[218], &reftables[219]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[220], &reftables[221]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[222], &reftables[223]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[224], &reftables[225]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[226], &reftables[227]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[228], &reftables[229]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[230], &reftables[231]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[232], &reftables[233]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[234], &reftables[235]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[236], &reftables[237]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_class_prefix", 40, &msgs[11], NULL, 31, 16, {0},&reftables[202], &reftables[203]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "php_namespace", 41, &msgs[11], NULL, 34, 17, {0},&reftables[204], &reftables[205]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, false, "positive_int_value", 4, &msgs[20], NULL, 9, 2, {0},&reftables[206], &reftables[207]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "public_dependency", 10, &msgs[9], NULL, 35, 9, {0},&reftables[208], &reftables[209]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "py_generic_services", 18, &msgs[11], NULL, 19, 8, {0},&reftables[210], &reftables[211]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, false, "reserved_name", 10, &msgs[0], NULL, 37, 9, {0},&reftables[212], &reftables[213]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "reserved_range", 9, &msgs[0], (const upb_def*)(&msgs[2]), 31, 7, {0},&reftables[214], &reftables[215]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "server_streaming", 6, &msgs[13], NULL, 14, 5, {0},&reftables[216], &reftables[217]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "service", 6, &msgs[9], (const upb_def*)(&msgs[16]), 16, 2, {0},&reftables[218], &reftables[219]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, false, "source_code_info", 9, &msgs[9], (const upb_def*)(&msgs[18]), 21, 5, {0},&reftables[220], &reftables[221]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, true, "span", 2, &msgs[19], NULL, 7, 1, {0},&reftables[222], &reftables[223]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[2], NULL, 2, 0, {0},&reftables[224], &reftables[225]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[226], &reftables[227]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, false, "string_value", 7, &msgs[20], NULL, 12, 5, {0},&reftables[228], &reftables[229]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "syntax", 12, &msgs[9], NULL, 39, 11, {0},&reftables[230], &reftables[231]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "trailing_comments", 4, &msgs[19], NULL, 11, 3, {0},&reftables[232], &reftables[233]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, false, "type", 5, &msgs[7], (const upb_def*)(&enums[1]), 12, 5, {0},&reftables[234], &reftables[235]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, false, "type_name", 6, &msgs[7], NULL, 13, 6, {0},&reftables[236], &reftables[237]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[12], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[238], &reftables[239]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[240], &reftables[241]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[11], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[242], &reftables[243]),
   UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[14], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[244], &reftables[245]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[17], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[248], &reftables[249]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[250], &reftables[251]),
-  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[252], &reftables[253]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[8], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[246], &reftables[247]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[6], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[248], &reftables[249]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "uninterpreted_option", 999, &msgs[4], (const upb_def*)(&msgs[20]), 5, 0, {0},&reftables[250], &reftables[251]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, false, "value", 2, &msgs[3], (const upb_def*)(&msgs[5]), 6, 0, {0},&reftables[252], &reftables[253]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, false, "weak", 10, &msgs[8], NULL, 11, 6, {0},&reftables[254], &reftables[255]),
+  UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, false, "weak_dependency", 11, &msgs[9], NULL, 38, 10, {0},&reftables[256], &reftables[257]),
 };
 
 static const upb_enumdef enums[5] = {
-  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[151], 4, 3), 0, &reftables[254], &reftables[255]),
-  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[155], 19, 18), 0, &reftables[256], &reftables[257]),
-  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[174], 3, 3), 0, &reftables[258], &reftables[259]),
-  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[260], &reftables[261]),
-  UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 4, 3), 0, &reftables[262], &reftables[263]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[154], 4, 3), 0, &reftables[258], &reftables[259]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[192]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[158], 19, 18), 0, &reftables[260], &reftables[261]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[224]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[177], 3, 3), 0, &reftables[262], &reftables[263]),
+  UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.JSType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[228]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[180], 3, 3), 0, &reftables[264], &reftables[265]),
+  UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[232]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[183], 4, 3), 0, &reftables[266], &reftables[267]),
 };
 
 static const upb_tabent strentries[236] = {
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[22]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[82]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "reserved_name"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6709,53 +6603,53 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "nested_type"), UPB_TABVALUE_PTR_INIT(&fields[60]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
+  {UPB_TABKEY_STR("\016", "\000", "\000", "\000", "reserved_range"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
   {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[68]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "oneof_decl"), UPB_TABVALUE_PTR_INIT(&fields[65]), NULL},
-  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), &strentries[13]},
-  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[89]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), &strentries[13]},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
   {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[18]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "start"), UPB_TABVALUE_PTR_INIT(&fields[90]), NULL},
   {UPB_TABKEY_STR("\003", "\000", "\000", "\000", "end"), UPB_TABVALUE_PTR_INIT(&fields[17]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), &strentries[26]},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
-  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
+  {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "value"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[52]), &strentries[26]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "allow_alias"), UPB_TABVALUE_PTR_INIT(&fields[1]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[73]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[34]},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
-  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[74]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), &strentries[34]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[13]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "oneof_index"), UPB_TABVALUE_PTR_INIT(&fields[66]), NULL},
   {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "label"), UPB_TABVALUE_PTR_INIT(&fields[40]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[63]), &strentries[53]},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "number"), UPB_TABVALUE_PTR_INIT(&fields[62]), &strentries[53]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\010", "\000", "\000", "\000", "extendee"), UPB_TABVALUE_PTR_INIT(&fields[21]), NULL},
-  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "type_name"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "json_name"), UPB_TABVALUE_PTR_INIT(&fields[38]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[93]), &strentries[50]},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "type"), UPB_TABVALUE_PTR_INIT(&fields[95]), &strentries[50]},
   {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "default_value"), UPB_TABVALUE_PTR_INIT(&fields[7]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "weak"), UPB_TABVALUE_PTR_INIT(&fields[105]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6766,25 +6660,25 @@
   {UPB_TABKEY_STR("\005", "\000", "\000", "\000", "ctype"), UPB_TABVALUE_PTR_INIT(&fields[6]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "jstype"), UPB_TABVALUE_PTR_INIT(&fields[39]), NULL},
-  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "extension"), UPB_TABVALUE_PTR_INIT(&fields[23]), NULL},
-  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[104]), NULL},
+  {UPB_TABKEY_STR("\017", "\000", "\000", "\000", "weak_dependency"), UPB_TABVALUE_PTR_INIT(&fields[106]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[85]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "service"), UPB_TABVALUE_PTR_INIT(&fields[87]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "source_code_info"), UPB_TABVALUE_PTR_INIT(&fields[88]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[91]), NULL},
+  {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "syntax"), UPB_TABVALUE_PTR_INIT(&fields[93]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "dependency"), UPB_TABVALUE_PTR_INIT(&fields[8]), NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "message_type"), UPB_TABVALUE_PTR_INIT(&fields[47]), NULL},
   {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "package"), UPB_TABVALUE_PTR_INIT(&fields[76]), NULL},
   {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[69]), &strentries[86]},
-  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[20]), NULL},
-  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[85]},
+  {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "enum_type"), UPB_TABVALUE_PTR_INIT(&fields[19]), NULL},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "public_dependency"), UPB_TABVALUE_PTR_INIT(&fields[82]), &strentries[85]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "file"), UPB_TABVALUE_PTR_INIT(&fields[26]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6792,7 +6686,7 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "cc_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[3]), NULL},
-  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "csharp_namespace"), UPB_TABVALUE_PTR_INIT(&fields[5]), &strentries[116]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6805,17 +6699,17 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "java_outer_classname"), UPB_TABVALUE_PTR_INIT(&fields[34]), NULL},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
+  {UPB_TABKEY_STR("\015", "\000", "\000", "\000", "php_namespace"), UPB_TABVALUE_PTR_INIT(&fields[80]), &strentries[113]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "java_multiple_files"), UPB_TABVALUE_PTR_INIT(&fields[33]), &strentries[117]},
-  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
   {UPB_TABKEY_STR("\025", "\000", "\000", "\000", "java_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[32]), &strentries[118]},
   {UPB_TABKEY_STR("\035", "\000", "\000", "\000", "java_generate_equals_and_hash"), UPB_TABVALUE_PTR_INIT(&fields[31]), NULL},
-  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "php_class_prefix"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
   {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "javanano_use_deprecated_package"), UPB_TABVALUE_PTR_INIT(&fields[37]), &strentries[123]},
-  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
+  {UPB_TABKEY_STR("\023", "\000", "\000", "\000", "py_generic_services"), UPB_TABVALUE_PTR_INIT(&fields[83]), NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "optimize_for"), UPB_TABVALUE_PTR_INIT(&fields[67]), NULL},
   {UPB_TABKEY_STR("\026", "\000", "\000", "\000", "java_string_check_utf8"), UPB_TABVALUE_PTR_INIT(&fields[36]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[12]), &strentries[119]},
@@ -6825,32 +6719,32 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
-  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[9]), NULL},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
   {UPB_TABKEY_STR("\011", "\000", "\000", "\000", "map_entry"), UPB_TABVALUE_PTR_INIT(&fields[45]), NULL},
   {UPB_TABKEY_STR("\037", "\000", "\000", "\000", "no_standard_descriptor_accessor"), UPB_TABVALUE_PTR_INIT(&fields[61]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "client_streaming"), UPB_TABVALUE_PTR_INIT(&fields[4]), NULL},
-  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[84]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[56]), NULL},
+  {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "server_streaming"), UPB_TABVALUE_PTR_INIT(&fields[86]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[55]), NULL},
   {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "input_type"), UPB_TABVALUE_PTR_INIT(&fields[29]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\013", "\000", "\000", "\000", "output_type"), UPB_TABVALUE_PTR_INIT(&fields[75]), NULL},
-  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[70]), NULL},
+  {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[71]), NULL},
   {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
-  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[50]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[54]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\007", "\000", "\000", "\000", "options"), UPB_TABVALUE_PTR_INIT(&fields[72]), &strentries[150]},
   {UPB_TABKEY_STR("\006", "\000", "\000", "\000", "method"), UPB_TABVALUE_PTR_INIT(&fields[48]), NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[57]), &strentries[149]},
-  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
-  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[53]), &strentries[149]},
+  {UPB_TABKEY_STR("\024", "\000", "\000", "\000", "uninterpreted_option"), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
+  {UPB_TABKEY_STR("\012", "\000", "\000", "\000", "deprecated"), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6860,15 +6754,15 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[87]), &strentries[167]},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "span"), UPB_TABVALUE_PTR_INIT(&fields[89]), &strentries[167]},
   {UPB_TABKEY_STR("\031", "\000", "\000", "\000", "leading_detached_comments"), UPB_TABVALUE_PTR_INIT(&fields[43]), &strentries[165]},
-  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[92]), NULL},
+  {UPB_TABKEY_STR("\021", "\000", "\000", "\000", "trailing_comments"), UPB_TABVALUE_PTR_INIT(&fields[94]), NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "leading_comments"), UPB_TABVALUE_PTR_INIT(&fields[42]), &strentries[164]},
   {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "path"), UPB_TABVALUE_PTR_INIT(&fields[78]), NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "double_value"), UPB_TABVALUE_PTR_INIT(&fields[16]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[51]), NULL},
+  {UPB_TABKEY_STR("\004", "\000", "\000", "\000", "name"), UPB_TABVALUE_PTR_INIT(&fields[49]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
@@ -6878,9 +6772,9 @@
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[79]), NULL},
+  {UPB_TABKEY_STR("\022", "\000", "\000", "\000", "positive_int_value"), UPB_TABVALUE_PTR_INIT(&fields[81]), NULL},
   {UPB_TABKEY_STR("\020", "\000", "\000", "\000", "identifier_value"), UPB_TABVALUE_PTR_INIT(&fields[28]), NULL},
-  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[90]), &strentries[182]},
+  {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "string_value"), UPB_TABVALUE_PTR_INIT(&fields[92]), &strentries[182]},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_STR("\014", "\000", "\000", "\000", "is_extension"), UPB_TABVALUE_PTR_INIT(&fields[30]), NULL},
@@ -6937,92 +6831,92 @@
 
 static const upb_tabent intentries[18] = {
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[103]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[102]), NULL},
+  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[99]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[95]), NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[97]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[96]), NULL},
-  {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[11]), NULL},
+  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[10]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
   {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[100]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[14]), NULL},
+  {UPB_TABKEY_NUM(33), UPB_TABVALUE_PTR_INIT(&fields[15]), NULL},
   {UPB_TABKEY_NONE, UPB_TABVALUE_EMPTY_INIT, NULL},
-  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[101]), NULL},
+  {UPB_TABKEY_NUM(999), UPB_TABVALUE_PTR_INIT(&fields[98]), NULL},
 };
 
-static const upb_tabval arrays[184] = {
+static const upb_tabval arrays[187] = {
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[52]),
+  UPB_TABVALUE_PTR_INIT(&fields[57]),
   UPB_TABVALUE_PTR_INIT(&fields[25]),
   UPB_TABVALUE_PTR_INIT(&fields[60]),
-  UPB_TABVALUE_PTR_INIT(&fields[19]),
+  UPB_TABVALUE_PTR_INIT(&fields[20]),
   UPB_TABVALUE_PTR_INIT(&fields[24]),
   UPB_TABVALUE_PTR_INIT(&fields[22]),
   UPB_TABVALUE_PTR_INIT(&fields[68]),
   UPB_TABVALUE_PTR_INIT(&fields[65]),
-  UPB_TABVALUE_PTR_INIT(&fields[83]),
-  UPB_TABVALUE_PTR_INIT(&fields[82]),
+  UPB_TABVALUE_PTR_INIT(&fields[85]),
+  UPB_TABVALUE_PTR_INIT(&fields[84]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[89]),
+  UPB_TABVALUE_PTR_INIT(&fields[91]),
   UPB_TABVALUE_PTR_INIT(&fields[18]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[88]),
+  UPB_TABVALUE_PTR_INIT(&fields[90]),
   UPB_TABVALUE_PTR_INIT(&fields[17]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[49]),
-  UPB_TABVALUE_PTR_INIT(&fields[102]),
-  UPB_TABVALUE_PTR_INIT(&fields[74]),
+  UPB_TABVALUE_PTR_INIT(&fields[52]),
+  UPB_TABVALUE_PTR_INIT(&fields[104]),
+  UPB_TABVALUE_PTR_INIT(&fields[73]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[1]),
+  UPB_TABVALUE_PTR_INIT(&fields[14]),
+  UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[50]),
+  UPB_TABVALUE_PTR_INIT(&fields[63]),
+  UPB_TABVALUE_PTR_INIT(&fields[74]),
+  UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[13]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[53]),
-  UPB_TABVALUE_PTR_INIT(&fields[62]),
-  UPB_TABVALUE_PTR_INIT(&fields[73]),
-  UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[15]),
-  UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[55]),
+  UPB_TABVALUE_PTR_INIT(&fields[56]),
   UPB_TABVALUE_PTR_INIT(&fields[21]),
-  UPB_TABVALUE_PTR_INIT(&fields[63]),
+  UPB_TABVALUE_PTR_INIT(&fields[62]),
   UPB_TABVALUE_PTR_INIT(&fields[40]),
-  UPB_TABVALUE_PTR_INIT(&fields[93]),
-  UPB_TABVALUE_PTR_INIT(&fields[94]),
+  UPB_TABVALUE_PTR_INIT(&fields[95]),
+  UPB_TABVALUE_PTR_INIT(&fields[96]),
   UPB_TABVALUE_PTR_INIT(&fields[7]),
-  UPB_TABVALUE_PTR_INIT(&fields[71]),
+  UPB_TABVALUE_PTR_INIT(&fields[70]),
   UPB_TABVALUE_PTR_INIT(&fields[66]),
   UPB_TABVALUE_PTR_INIT(&fields[38]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[6]),
   UPB_TABVALUE_PTR_INIT(&fields[77]),
-  UPB_TABVALUE_PTR_INIT(&fields[10]),
+  UPB_TABVALUE_PTR_INIT(&fields[9]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[41]),
   UPB_TABVALUE_PTR_INIT(&fields[39]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[103]),
+  UPB_TABVALUE_PTR_INIT(&fields[105]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[54]),
+  UPB_TABVALUE_PTR_INIT(&fields[51]),
   UPB_TABVALUE_PTR_INIT(&fields[76]),
   UPB_TABVALUE_PTR_INIT(&fields[8]),
   UPB_TABVALUE_PTR_INIT(&fields[47]),
-  UPB_TABVALUE_PTR_INIT(&fields[20]),
-  UPB_TABVALUE_PTR_INIT(&fields[85]),
+  UPB_TABVALUE_PTR_INIT(&fields[19]),
+  UPB_TABVALUE_PTR_INIT(&fields[87]),
   UPB_TABVALUE_PTR_INIT(&fields[23]),
   UPB_TABVALUE_PTR_INIT(&fields[69]),
-  UPB_TABVALUE_PTR_INIT(&fields[86]),
-  UPB_TABVALUE_PTR_INIT(&fields[80]),
-  UPB_TABVALUE_PTR_INIT(&fields[104]),
-  UPB_TABVALUE_PTR_INIT(&fields[91]),
+  UPB_TABVALUE_PTR_INIT(&fields[88]),
+  UPB_TABVALUE_PTR_INIT(&fields[82]),
+  UPB_TABVALUE_PTR_INIT(&fields[106]),
+  UPB_TABVALUE_PTR_INIT(&fields[93]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[26]),
   UPB_TABVALUE_EMPTY_INIT,
@@ -7043,7 +6937,7 @@
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[3]),
   UPB_TABVALUE_PTR_INIT(&fields[32]),
-  UPB_TABVALUE_PTR_INIT(&fields[81]),
+  UPB_TABVALUE_PTR_INIT(&fields[83]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[31]),
   UPB_TABVALUE_EMPTY_INIT,
@@ -7065,25 +6959,28 @@
   UPB_TABVALUE_PTR_INIT(&fields[5]),
   UPB_TABVALUE_PTR_INIT(&fields[37]),
   UPB_TABVALUE_EMPTY_INIT,
+  UPB_TABVALUE_PTR_INIT(&fields[79]),
+  UPB_TABVALUE_PTR_INIT(&fields[80]),
+  UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[46]),
   UPB_TABVALUE_PTR_INIT(&fields[61]),
-  UPB_TABVALUE_PTR_INIT(&fields[9]),
+  UPB_TABVALUE_PTR_INIT(&fields[11]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[45]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[56]),
+  UPB_TABVALUE_PTR_INIT(&fields[55]),
   UPB_TABVALUE_PTR_INIT(&fields[29]),
   UPB_TABVALUE_PTR_INIT(&fields[75]),
-  UPB_TABVALUE_PTR_INIT(&fields[70]),
+  UPB_TABVALUE_PTR_INIT(&fields[71]),
   UPB_TABVALUE_PTR_INIT(&fields[4]),
-  UPB_TABVALUE_PTR_INIT(&fields[84]),
+  UPB_TABVALUE_PTR_INIT(&fields[86]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[50]),
+  UPB_TABVALUE_PTR_INIT(&fields[54]),
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[57]),
+  UPB_TABVALUE_PTR_INIT(&fields[53]),
   UPB_TABVALUE_PTR_INIT(&fields[48]),
   UPB_TABVALUE_PTR_INIT(&fields[72]),
   UPB_TABVALUE_EMPTY_INIT,
@@ -7091,19 +6988,19 @@
   UPB_TABVALUE_PTR_INIT(&fields[44]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[78]),
-  UPB_TABVALUE_PTR_INIT(&fields[87]),
+  UPB_TABVALUE_PTR_INIT(&fields[89]),
   UPB_TABVALUE_PTR_INIT(&fields[42]),
-  UPB_TABVALUE_PTR_INIT(&fields[92]),
+  UPB_TABVALUE_PTR_INIT(&fields[94]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[43]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_EMPTY_INIT,
-  UPB_TABVALUE_PTR_INIT(&fields[51]),
+  UPB_TABVALUE_PTR_INIT(&fields[49]),
   UPB_TABVALUE_PTR_INIT(&fields[28]),
-  UPB_TABVALUE_PTR_INIT(&fields[79]),
+  UPB_TABVALUE_PTR_INIT(&fields[81]),
   UPB_TABVALUE_PTR_INIT(&fields[59]),
   UPB_TABVALUE_PTR_INIT(&fields[16]),
-  UPB_TABVALUE_PTR_INIT(&fields[90]),
+  UPB_TABVALUE_PTR_INIT(&fields[92]),
   UPB_TABVALUE_PTR_INIT(&fields[0]),
   UPB_TABVALUE_EMPTY_INIT,
   UPB_TABVALUE_PTR_INIT(&fields[58]),
@@ -7144,7 +7041,11 @@
 };
 
 #ifdef UPB_DEBUG_REFS
-static upb_inttable reftables[264] = {
+static upb_inttable reftables[268] = {
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
+  UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
   UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
   UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
   UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
@@ -7686,6 +7587,37 @@
   return n;
 }
 
+static size_t file_onphpnamespace(void *closure, const void *hd,
+                                  const char *buf, size_t n,
+                                  const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *php_namespace;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  php_namespace = upb_gstrndup(buf, n);
+  ok = upb_filedef_setphpnamespace(r->file, php_namespace, NULL);
+  upb_gfree(php_namespace);
+  UPB_ASSERT(ok);
+  return n;
+}
+
+static size_t file_onphpprefix(void *closure, const void *hd, const char *buf,
+                             size_t n, const upb_bufhandle *handle) {
+  upb_descreader *r = closure;
+  char *prefix;
+  bool ok;
+  UPB_UNUSED(hd);
+  UPB_UNUSED(handle);
+
+  prefix = upb_gstrndup(buf, n);
+  ok = upb_filedef_setphpprefix(r->file, prefix, NULL);
+  upb_gfree(prefix);
+  UPB_ASSERT(ok);
+  return n;
+}
+
 static size_t file_onsyntax(void *closure, const void *hd, const char *buf,
                             size_t n, const upb_bufhandle *handle) {
   upb_descreader *r = closure;
@@ -8212,6 +8144,11 @@
     upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
   } else if (upbdefs_google_protobuf_MessageOptions_is(m)) {
     upb_handlers_setbool(h, F(MessageOptions, map_entry), &msg_onmapentry, NULL);
+  } else if (upbdefs_google_protobuf_FileOptions_is(m)) {
+    upb_handlers_setstring(h, F(FileOptions, php_class_prefix),
+                           &file_onphpprefix, NULL);
+    upb_handlers_setstring(h, F(FileOptions, php_namespace),
+                           &file_onphpnamespace, NULL);
   }
 
   UPB_ASSERT(upb_ok(upb_handlers_status(h)));
@@ -10759,7 +10696,7 @@
 T(double,   double,   dbl2uint64,   encode_fixed64)
 T(float,    float,    flt2uint32,   encode_fixed32)
 T(int64,    int64_t,  uint64_t,     encode_varint)
-T(int32,    int32_t,  uint32_t,     encode_varint)
+T(int32,    int32_t,  int64_t,      encode_varint)
 T(fixed64,  uint64_t, uint64_t,     encode_fixed64)
 T(fixed32,  uint32_t, uint32_t,     encode_fixed32)
 T(bool,     bool,     bool,         encode_varint)
@@ -11374,57 +11311,6 @@
   return r;
 }
 
-/* Given an encoded varint v, returns an integer with a single bit set that
- * indicates the end of the varint.  Subtracting one from this value will
- * yield a mask that leaves only bits that are part of the varint.  Returns
- * 0 if the varint is unterminated. */
-static uint64_t upb_get_vstopbit(uint64_t v) {
-  uint64_t cbits = v | 0x7f7f7f7f7f7f7f7fULL;
-  return ~cbits & (cbits+1);
-}
-
-/* A branchless decoder.  Credit to Pascal Massimino for the bit-twiddling. */
-upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r) {
-  uint64_t b;
-  uint64_t stop_bit;
-  upb_decoderet my_r;
-  memcpy(&b, r.p, sizeof(b));
-  stop_bit = upb_get_vstopbit(b);
-  b =  (b & 0x7f7f7f7f7f7f7f7fULL) & (stop_bit - 1);
-  b +=       b & 0x007f007f007f007fULL;
-  b +=  3 * (b & 0x0000ffff0000ffffULL);
-  b += 15 * (b & 0x00000000ffffffffULL);
-  if (stop_bit == 0) {
-    /* Error: unterminated varint. */
-    upb_decoderet err_r = {(void*)0, 0};
-    return err_r;
-  }
-  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
-                            r.val | (b << 7));
-  return my_r;
-}
-
-/* A branchless decoder.  Credit to Daniel Wright for the bit-twiddling. */
-upb_decoderet upb_vdecode_max8_wright(upb_decoderet r) {
-  uint64_t b;
-  uint64_t stop_bit;
-  upb_decoderet my_r;
-  memcpy(&b, r.p, sizeof(b));
-  stop_bit = upb_get_vstopbit(b);
-  b &= (stop_bit - 1);
-  b = ((b & 0x7f007f007f007f00ULL) >> 1) | (b & 0x007f007f007f007fULL);
-  b = ((b & 0xffff0000ffff0000ULL) >> 2) | (b & 0x0000ffff0000ffffULL);
-  b = ((b & 0xffffffff00000000ULL) >> 4) | (b & 0x00000000ffffffffULL);
-  if (stop_bit == 0) {
-    /* Error: unterminated varint. */
-    upb_decoderet err_r = {(void*)0, 0};
-    return err_r;
-  }
-  my_r = upb_decoderet_make(r.p + ((__builtin_ctzll(stop_bit) + 1) / 8),
-                            r.val | (b << 14));
-  return my_r;
-}
-
 #line 1 "upb/json/parser.rl"
 /*
 ** upb::json::Parser (upb_json_parser)
@@ -11447,8 +11333,9 @@
 ** - handling of keys/escape-sequences/etc that span input buffers.
 */
 
-#include <assert.h>
 #include <errno.h>
+#include <float.h>
+#include <math.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -12033,21 +11920,136 @@
   capture_begin(p, ptr);
 }
 
-static bool parse_number(upb_json_parser *p);
+static bool parse_number(upb_json_parser *p, bool is_quoted);
 
 static bool end_number(upb_json_parser *p, const char *ptr) {
   if (!capture_end(p, ptr)) {
     return false;
   }
 
-  return parse_number(p);
+  return parse_number(p, false);
 }
 
-static bool parse_number(upb_json_parser *p) {
+static bool parse_number_from_buffer(upb_json_parser *p, const char *buf,
+                                     const char *bufend, bool is_quoted) {
+  size_t len = bufend - buf;
+  char *end;
+  upb_fieldtype_t type = upb_fielddef_type(p->top->f);
+  double val;
+  double dummy;
+
+  if (buf[0] == ' ') {
+    return false;
+  }
+
+  /* For integer types, first try parsing with integer-specific routines.
+   * If these succeed, they will be more accurate for int64/uint64 than
+   * strtod().
+   */
+  switch (type) {
+    case UPB_TYPE_ENUM:
+    case UPB_TYPE_INT32: {
+      long val = strtol(buf, &end, 0);
+      if (errno == ERANGE || end != bufend) {
+        break;
+      } else if (val > INT32_MAX || val < INT32_MIN) {
+        return false;
+      } else {
+        upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
+        return true;
+      }
+    }
+    case UPB_TYPE_UINT32: {
+      unsigned long val = strtoul(buf, &end, 0);
+      if (end != bufend) {
+        break;
+      } else if (val > UINT32_MAX || errno == ERANGE) {
+        return false;
+      } else {
+        upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
+        return true;
+      }
+    }
+    /* XXX: We can't handle [u]int64 properly on 32-bit machines because
+     * strto[u]ll isn't in C89. */
+    case UPB_TYPE_INT64: {
+      long val = strtol(buf, &end, 0);
+      if (errno == ERANGE || end != bufend) {
+        break;
+      } else {
+        upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
+        return true;
+      }
+    }
+    case UPB_TYPE_UINT64: {
+      unsigned long val = strtoul(p->accumulated, &end, 0);
+      if (end != bufend) {
+        break;
+      } else if (errno == ERANGE) {
+        return false;
+      } else {
+        upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
+        return true;
+      }
+    }
+    default:
+      break;
+  }
+
+  if (type != UPB_TYPE_DOUBLE && type != UPB_TYPE_FLOAT && is_quoted) {
+    /* Quoted numbers shouldn't support double forms for integer types. */
+    return false;
+  }
+
+  if (len == strlen("Infinity") && strcmp(buf, "Infinity") == 0) {
+    /* C89 does not have an INFINITY macro. */
+    val = 1.0 / 0.0;
+  } else if (len == strlen("-Infinity") && strcmp(buf, "-Infinity") == 0) {
+    val = -1.0 / 0.0;
+  } else {
+    val = strtod(buf, &end);
+    if (errno == ERANGE || end != bufend) {
+      return false;
+    }
+  }
+
+  switch (type) {
+#define CASE(capitaltype, smalltype, min, max)                            \
+    case UPB_TYPE_ ## capitaltype: {                                      \
+      if (modf(val, &dummy) != 0 || val > max || val < min) {             \
+        return false;                                                     \
+      } else {                                                            \
+        upb_sink_put ## smalltype(&p->top->sink, parser_getsel(p), val);  \
+        return true;                                                      \
+      }                                                                   \
+      break;                                                              \
+    }
+    case UPB_TYPE_ENUM:
+    CASE(INT32, int32, INT32_MIN, INT32_MAX);
+    CASE(INT64, int64, INT64_MIN, INT64_MAX);
+    CASE(UINT32, uint32, 0, UINT32_MAX);
+    CASE(UINT64, uint64, 0, UINT64_MAX);
+#undef CASE
+
+    case UPB_TYPE_DOUBLE:
+      upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
+      return true;
+    case UPB_TYPE_FLOAT:
+      if (false /*val > FLT_MAX || val < -FLT_MAX*/) {
+        return false;
+      } else {
+        upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
+        return true;
+      }
+    default:
+      return false;
+  }
+}
+
+static bool parse_number(upb_json_parser *p, bool is_quoted) {
   size_t len;
   const char *buf;
-  const char *myend;
-  char *end;
+  const char *bufend;
 
   /* strtol() and friends unfortunately do not support specifying the length of
    * the input string, so we need to force a copy into a NULL-terminated buffer. */
@@ -12056,80 +12058,18 @@
   }
 
   buf = accumulate_getptr(p, &len);
-  myend = buf + len - 1;  /* One for NULL. */
+  bufend = buf + len - 1;  /* One for NULL. */
+  errno = 0;
 
-  /* XXX: We are using strtol to parse integers, but this is wrong as even
-   * integers can be represented as 1e6 (for example), which strtol can't
-   * handle correctly.
-   *
-   * XXX: Also, we can't handle large integers properly because strto[u]ll
-   * isn't in C89.
-   *
-   * XXX: Also, we don't properly check floats for overflow, since strtof
-   * isn't in C89. */
-  switch (upb_fielddef_type(p->top->f)) {
-    case UPB_TYPE_ENUM:
-    case UPB_TYPE_INT32: {
-      long val = strtol(p->accumulated, &end, 0);
-      if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || end != myend)
-        goto err;
-      else
-        upb_sink_putint32(&p->top->sink, parser_getsel(p), val);
-      break;
-    }
-    case UPB_TYPE_INT64: {
-      long long val = strtol(p->accumulated, &end, 0);
-      if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || end != myend)
-        goto err;
-      else
-        upb_sink_putint64(&p->top->sink, parser_getsel(p), val);
-      break;
-    }
-    case UPB_TYPE_UINT32: {
-      unsigned long val = strtoul(p->accumulated, &end, 0);
-      if (val > UINT32_MAX || errno == ERANGE || end != myend)
-        goto err;
-      else
-        upb_sink_putuint32(&p->top->sink, parser_getsel(p), val);
-      break;
-    }
-    case UPB_TYPE_UINT64: {
-      unsigned long long val = strtoul(p->accumulated, &end, 0);
-      if (val > UINT64_MAX || errno == ERANGE || end != myend)
-        goto err;
-      else
-        upb_sink_putuint64(&p->top->sink, parser_getsel(p), val);
-      break;
-    }
-    case UPB_TYPE_DOUBLE: {
-      double val = strtod(p->accumulated, &end);
-      if (errno == ERANGE || end != myend)
-        goto err;
-      else
-        upb_sink_putdouble(&p->top->sink, parser_getsel(p), val);
-      break;
-    }
-    case UPB_TYPE_FLOAT: {
-      float val = strtod(p->accumulated, &end);
-      if (errno == ERANGE || end != myend)
-        goto err;
-      else
-        upb_sink_putfloat(&p->top->sink, parser_getsel(p), val);
-      break;
-    }
-    default:
-      UPB_ASSERT(false);
+  if (parse_number_from_buffer(p, buf, bufend, is_quoted)) {
+    multipart_end(p);
+    return true;
+  } else {
+    upb_status_seterrf(&p->status, "error parsing number: %s", buf);
+    upb_env_reporterror(p->env, &p->status);
+    multipart_end(p);
+    return false;
   }
-
-  multipart_end(p);
-
-  return true;
-
-err:
-  upb_status_seterrf(&p->status, "error parsing number: %s", buf);
-  upb_env_reporterror(p->env, &p->status);
-  multipart_end(p);
-  return false;
 }
 
 static bool parser_putbool(upb_json_parser *p, bool val) {
@@ -12182,17 +12122,16 @@
       multipart_startaccum(p);
       return true;
     }
-  } else if (upb_fielddef_type(p->top->f) == UPB_TYPE_ENUM) {
-    /* No need to push a frame -- symbolic enum names in quotes remain in the
-     * current parser frame.
-     *
-     * Enum string values must accumulate so we can look up the value in a table
-     * once it is complete. */
+  } else if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL &&
+             upb_fielddef_type(p->top->f) != UPB_TYPE_MESSAGE) {
+    /* No need to push a frame -- numeric values in quotes remain in the
+     * current parser frame.  These values must accmulate so we can convert
+     * them all at once at the end. */
     multipart_startaccum(p);
     return true;
   } else {
     upb_status_seterrf(&p->status,
-                       "String specified for non-string/non-enum field: %s",
+                       "String specified for bool or submessage field: %s",
                        upb_fielddef_name(p->top->f));
     upb_env_reporterror(p->env, &p->status);
     return false;
@@ -12239,6 +12178,15 @@
       break;
     }
 
+    case UPB_TYPE_INT32:
+    case UPB_TYPE_INT64:
+    case UPB_TYPE_UINT32:
+    case UPB_TYPE_UINT64:
+    case UPB_TYPE_DOUBLE:
+    case UPB_TYPE_FLOAT:
+      ok = parse_number(p, true);
+      break;
+
     default:
       UPB_ASSERT(false);
       upb_status_seterrmsg(&p->status, "Internal error in JSON decoder");
@@ -12282,7 +12230,7 @@
     case UPB_TYPE_UINT32:
     case UPB_TYPE_UINT64:
       /* Invoke end_number. The accum buffer has the number's text already. */
-      if (!parse_number(p)) {
+      if (!parse_number(p, true)) {
         return false;
       }
       break;
@@ -12573,11 +12521,11 @@
  * final state once, when the closing '"' is seen. */
 
 
-#line 1244 "upb/json/parser.rl"
+#line 1306 "upb/json/parser.rl"
 
 
 
-#line 1156 "upb/json/parser.c"
+#line 1218 "upb/json/parser.c"
 static const char _json_actions[] = {
 	0, 1, 0, 1, 2, 1, 3, 1, 
 	5, 1, 6, 1, 7, 1, 8, 1, 
@@ -12726,7 +12674,7 @@
 static const int json_en_main = 1;
 
 
-#line 1247 "upb/json/parser.rl"
+#line 1309 "upb/json/parser.rl"
 
 size_t parse(void *closure, const void *hd, const char *buf, size_t size,
              const upb_bufhandle *handle) {
@@ -12748,7 +12696,7 @@
   capture_resume(parser, buf);
 
   
-#line 1327 "upb/json/parser.c"
+#line 1389 "upb/json/parser.c"
 	{
 	int _klen;
 	unsigned int _trans;
@@ -12823,118 +12771,118 @@
 		switch ( *_acts++ )
 		{
 	case 0:
-#line 1159 "upb/json/parser.rl"
+#line 1221 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 1:
-#line 1160 "upb/json/parser.rl"
+#line 1222 "upb/json/parser.rl"
 	{ p--; {stack[top++] = cs; cs = 10; goto _again;} }
 	break;
 	case 2:
-#line 1164 "upb/json/parser.rl"
+#line 1226 "upb/json/parser.rl"
 	{ start_text(parser, p); }
 	break;
 	case 3:
-#line 1165 "upb/json/parser.rl"
+#line 1227 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_text(parser, p)); }
 	break;
 	case 4:
-#line 1171 "upb/json/parser.rl"
+#line 1233 "upb/json/parser.rl"
 	{ start_hex(parser); }
 	break;
 	case 5:
-#line 1172 "upb/json/parser.rl"
+#line 1234 "upb/json/parser.rl"
 	{ hexdigit(parser, p); }
 	break;
 	case 6:
-#line 1173 "upb/json/parser.rl"
+#line 1235 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_hex(parser)); }
 	break;
 	case 7:
-#line 1179 "upb/json/parser.rl"
+#line 1241 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(escape(parser, p)); }
 	break;
 	case 8:
-#line 1185 "upb/json/parser.rl"
+#line 1247 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
 	case 9:
-#line 1188 "upb/json/parser.rl"
+#line 1250 "upb/json/parser.rl"
 	{ {stack[top++] = cs; cs = 19; goto _again;} }
 	break;
 	case 10:
-#line 1190 "upb/json/parser.rl"
+#line 1252 "upb/json/parser.rl"
 	{ p--; {stack[top++] = cs; cs = 27; goto _again;} }
 	break;
 	case 11:
-#line 1195 "upb/json/parser.rl"
+#line 1257 "upb/json/parser.rl"
 	{ start_member(parser); }
 	break;
 	case 12:
-#line 1196 "upb/json/parser.rl"
+#line 1258 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_membername(parser)); }
 	break;
 	case 13:
-#line 1199 "upb/json/parser.rl"
+#line 1261 "upb/json/parser.rl"
 	{ end_member(parser); }
 	break;
 	case 14:
-#line 1205 "upb/json/parser.rl"
+#line 1267 "upb/json/parser.rl"
 	{ start_object(parser); }
 	break;
 	case 15:
-#line 1208 "upb/json/parser.rl"
+#line 1270 "upb/json/parser.rl"
 	{ end_object(parser); }
 	break;
 	case 16:
-#line 1214 "upb/json/parser.rl"
+#line 1276 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_array(parser)); }
 	break;
 	case 17:
-#line 1218 "upb/json/parser.rl"
+#line 1280 "upb/json/parser.rl"
 	{ end_array(parser); }
 	break;
 	case 18:
-#line 1223 "upb/json/parser.rl"
+#line 1285 "upb/json/parser.rl"
 	{ start_number(parser, p); }
 	break;
 	case 19:
-#line 1224 "upb/json/parser.rl"
+#line 1286 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_number(parser, p)); }
 	break;
 	case 20:
-#line 1226 "upb/json/parser.rl"
+#line 1288 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_stringval(parser)); }
 	break;
 	case 21:
-#line 1227 "upb/json/parser.rl"
+#line 1289 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(end_stringval(parser)); }
 	break;
 	case 22:
-#line 1229 "upb/json/parser.rl"
+#line 1291 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(parser_putbool(parser, true)); }
 	break;
 	case 23:
-#line 1231 "upb/json/parser.rl"
+#line 1293 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(parser_putbool(parser, false)); }
 	break;
 	case 24:
-#line 1233 "upb/json/parser.rl"
+#line 1295 "upb/json/parser.rl"
 	{ /* null value */ }
 	break;
 	case 25:
-#line 1235 "upb/json/parser.rl"
+#line 1297 "upb/json/parser.rl"
 	{ CHECK_RETURN_TOP(start_subobject(parser)); }
 	break;
 	case 26:
-#line 1236 "upb/json/parser.rl"
+#line 1298 "upb/json/parser.rl"
 	{ end_subobject(parser); }
 	break;
 	case 27:
-#line 1241 "upb/json/parser.rl"
+#line 1303 "upb/json/parser.rl"
 	{ p--; {cs = stack[--top]; goto _again;} }
 	break;
-#line 1513 "upb/json/parser.c"
+#line 1575 "upb/json/parser.c"
 		}
 	}
 
@@ -12947,7 +12895,7 @@
 	_out: {}
 	}
 
-#line 1268 "upb/json/parser.rl"
+#line 1330 "upb/json/parser.rl"
 
   if (p != pe) {
     upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p);
@@ -12988,13 +12936,13 @@
 
   /* Emit Ragel initialization of the parser. */
   
-#line 1567 "upb/json/parser.c"
+#line 1629 "upb/json/parser.c"
 	{
 	cs = json_start;
 	top = 0;
 	}
 
-#line 1308 "upb/json/parser.rl"
+#line 1370 "upb/json/parser.rl"
   p->current_state = cs;
   p->parser_top = top;
   accumulate_clear(p);
@@ -13291,10 +13239,23 @@
  * Right now we use %.8g and %.17g for float/double, respectively, to match
  * proto2::util::JsonFormat's defaults.  May want to change this later. */
 
+const char neginf[] = "\"-Infinity\"";
+const char inf[] = "\"Infinity\"";
+
 static size_t fmt_double(double val, char* buf, size_t length) {
-  size_t n = _upb_snprintf(buf, length, "%.17g", val);
-  CHKLENGTH(n > 0 && n < length);
-  return n;
+  if (val == (1.0 / 0.0)) {
+    CHKLENGTH(length >= strlen(inf));
+    strcpy(buf, inf);
+    return strlen(inf);
+  } else if (val == (-1.0 / 0.0)) {
+    CHKLENGTH(length >= strlen(neginf));
+    strcpy(buf, neginf);
+    return strlen(neginf);
+  } else {
+    size_t n = _upb_snprintf(buf, length, "%.17g", val);
+    CHKLENGTH(n > 0 && n < length);
+    return n;
+  }
 }
 
 static size_t fmt_float(float val, char* buf, size_t length) {
diff --git a/ruby/ext/google/protobuf_c/upb.h b/ruby/ext/google/protobuf_c/upb.h
index 6e1e6c6..3edee0d 100644
--- a/ruby/ext/google/protobuf_c/upb.h
+++ b/ruby/ext/google/protobuf_c/upb.h
@@ -2966,6 +2966,17 @@
   const char* package() const;
   bool set_package(const char* package, Status* s);
 
+  /* Sets the php class prefix which is prepended to all php generated classes
+   * from this .proto. Default is empty. */
+  const char* phpprefix() const;
+  bool set_phpprefix(const char* phpprefix, Status* s);
+
+  /* Use this option to change the namespace of php generated classes. Default
+   * is empty. When this option is empty, the package name will be used for
+   * determining the namespace. */
+  const char* phpnamespace() const;
+  bool set_phpnamespace(const char* phpnamespace, Status* s);
+
   /* Syntax for the file.  Defaults to proto2. */
   upb_syntax_t syntax() const;
   void set_syntax(upb_syntax_t syntax);
@@ -3019,6 +3030,8 @@
 
 const char *upb_filedef_name(const upb_filedef *f);
 const char *upb_filedef_package(const upb_filedef *f);
+const char *upb_filedef_phpprefix(const upb_filedef *f);
+const char *upb_filedef_phpnamespace(const upb_filedef *f);
 upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
 size_t upb_filedef_defcount(const upb_filedef *f);
 size_t upb_filedef_depcount(const upb_filedef *f);
@@ -3028,6 +3041,10 @@
 bool upb_filedef_freeze(upb_filedef *f, upb_status *s);
 bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s);
 bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s);
+bool upb_filedef_setphpprefix(upb_filedef *f, const char *phpprefix,
+                              upb_status *s);
+bool upb_filedef_setphpnamespace(upb_filedef *f, const char *phpnamespace,
+                                 upb_status *s);
 bool upb_filedef_setsyntax(upb_filedef *f, upb_syntax_t syntax, upb_status *s);
 
 bool upb_filedef_adddef(upb_filedef *f, upb_def *def, const void *ref_donor,
@@ -3786,6 +3803,18 @@
 inline bool FileDef::set_package(const char* package, Status* s) {
   return upb_filedef_setpackage(this, package, s);
 }
+inline const char* FileDef::phpprefix() const {
+  return upb_filedef_phpprefix(this);
+}
+inline bool FileDef::set_phpprefix(const char* phpprefix, Status* s) {
+  return upb_filedef_setphpprefix(this, phpprefix, s);
+}
+inline const char* FileDef::phpnamespace() const {
+  return upb_filedef_phpnamespace(this);
+}
+inline bool FileDef::set_phpnamespace(const char* phpnamespace, Status* s) {
+  return upb_filedef_setphpnamespace(this, phpnamespace, s);
+}
 inline int FileDef::def_count() const {
   return upb_filedef_defcount(this);
 }
@@ -4000,6 +4029,8 @@
 
   const char *name;
   const char *package;
+  const char *phpprefix;
+  const char *phpnamespace;
   upb_syntax_t syntax;
 
   upb_inttable defs;
@@ -7206,6 +7237,8 @@
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_javanano_use_deprecated_package(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 38); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_objc_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 36); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_optimize_for(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 9); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_class_prefix(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 40); }
+UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_php_namespace(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 41); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_py_generic_services(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 18); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_f_uninterpreted_option(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_FileOptions_is(m)); return upb_msgdef_itof(m, 999); }
 UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_f_deprecated(const upb_msgdef *m) { UPB_ASSERT(upbdefs_google_protobuf_MessageOptions_is(m)); return upb_msgdef_itof(m, 3); }
@@ -8304,16 +8337,8 @@
   return ret;
 }
 
-/* Four functions for decoding a varint of at most eight bytes.  They are all
- * functionally identical, but are implemented in different ways and likely have
- * different performance profiles.  We keep them around for performance testing.
- *
- * Note that these functions may not read byte-by-byte, so they must not be used
- * unless there are at least eight bytes left in the buffer! */
 upb_decoderet upb_vdecode_max8_branch32(upb_decoderet r);
 upb_decoderet upb_vdecode_max8_branch64(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_wright(upb_decoderet r);
-upb_decoderet upb_vdecode_max8_massimino(upb_decoderet r);
 
 /* Template for a function that checks the first two bytes with branching
  * and dispatches 2-10 bytes with a separate function.  Note that this may read
@@ -8338,8 +8363,6 @@
 
 UPB_VARINT_DECODER_CHECK2(branch32, upb_vdecode_max8_branch32)
 UPB_VARINT_DECODER_CHECK2(branch64, upb_vdecode_max8_branch64)
-UPB_VARINT_DECODER_CHECK2(wright, upb_vdecode_max8_wright)
-UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino)
 #undef UPB_VARINT_DECODER_CHECK2
 
 /* Our canonical functions for decoding varints, based on the currently
@@ -8351,10 +8374,6 @@
     return upb_vdecode_check2_branch32(p);
 }
 
-UPB_INLINE upb_decoderet upb_vdecode_max8_fast(upb_decoderet r) {
-  return upb_vdecode_max8_massimino(r);
-}
-
 
 /* Encoding *******************************************************************/
 
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index 836b1dd..bd1e39f 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -1,6 +1,6 @@
 Gem::Specification.new do |s|
   s.name        = "google-protobuf"
-  s.version     = "3.3.0"
+  s.version     = "3.4.0.2"
   s.licenses    = ["BSD-3-Clause"]
   s.summary     = "Protocol Buffers"
   s.description = "Protocol Buffers are Google's data interchange format."
diff --git a/ruby/lib/google/protobuf/well_known_types.rb b/ruby/lib/google/protobuf/well_known_types.rb
index 547de87..921ddbc 100644
--- a/ruby/lib/google/protobuf/well_known_types.rb
+++ b/ruby/lib/google/protobuf/well_known_types.rb
@@ -80,7 +80,7 @@
       end
 
       def to_f
-        self.seconds + (self.nanos.to_f / 1_000_000_000)
+        self.seconds + (self.nanos.quo(1_000_000_000))
       end
     end
 
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 02cc7a0..94071ca 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -96,8 +96,18 @@
         optional :d, :enum, 4, "TestEnum"
       end
     end
+
+    add_message "repro.Outer" do
+      map :items, :int32, :message, 1, "repro.Inner"
+    end
+
+    add_message "repro.Inner" do
+    end
   end
 
+
+  Outer = pool.lookup("repro.Outer").msgclass
+  Inner = pool.lookup("repro.Inner").msgclass
   Foo = pool.lookup("Foo").msgclass
   Bar = pool.lookup("Bar").msgclass
   Baz = pool.lookup("Baz").msgclass
@@ -675,6 +685,21 @@
       m.map_string_int32['aaa'] = 3
     end
 
+    def test_concurrent_decoding
+      o = Outer.new
+      o.items[0] = Inner.new
+      raw = Outer.encode(o)
+
+      thds = 2.times.map do
+        Thread.new do
+          100000.times do
+            assert_equal o, Outer.decode(raw)
+          end
+        end
+      end
+      thds.map(&:join)
+    end
+
     def test_map_encode_decode
       m = MapMessage.new(
         :map_string_int32 => {"a" => 1, "b" => 2},
@@ -1174,6 +1199,8 @@
 
       json_text = TestMessage.encode_json(m)
       m2 = TestMessage.decode_json(json_text)
+      puts m.inspect
+      puts m2.inspect
       assert m == m2
 
       # Crash case from GitHub issue 283.
diff --git a/ruby/tests/well_known_types_test.rb b/ruby/tests/well_known_types_test.rb
index 9b46632..bd24c32 100644
--- a/ruby/tests/well_known_types_test.rb
+++ b/ruby/tests/well_known_types_test.rb
@@ -13,10 +13,18 @@
     assert_equal Time.at(12345), ts.to_time
     assert_equal 12345, ts.to_i
 
-    ts.from_time(Time.at(123456, 654321))
+    # millisecond accuracy
+    time = Time.at(123456, 654321)
+    ts.from_time(time)
     assert_equal 123456, ts.seconds
     assert_equal 654321000, ts.nanos
-    assert_equal Time.at(123456.654321), ts.to_time
+    assert_equal time, ts.to_time
+
+    # nanosecond accuracy
+    time = Time.at(123456, Rational(654321321, 1000))
+    ts.from_time(time)
+    assert_equal 654321321, ts.nanos
+    assert_equal time, ts.to_time
   end
 
   def test_duration
diff --git a/src/Makefile.am b/src/Makefile.am
index bfb875a..1999213 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -48,8 +48,7 @@
                          google/protobuf/timestamp.proto       \
                          google/protobuf/type.proto            \
                          google/protobuf/wrappers.proto        \
-                         google/protobuf/compiler/plugin.proto \
-                         google/protobuf/compiler/profile.proto
+                         google/protobuf/compiler/plugin.proto
 
 # Not sure why these don't get cleaned automatically.
 clean-local:
@@ -104,6 +103,7 @@
   google/protobuf/api.pb.h                                       \
   google/protobuf/any.h                                          \
   google/protobuf/arena.h                                        \
+  google/protobuf/arena_impl.h                                   \
   google/protobuf/arenastring.h                                  \
   google/protobuf/descriptor_database.h                          \
   google/protobuf/descriptor.h                                   \
@@ -158,7 +158,6 @@
   google/protobuf/compiler/parser.h                              \
   google/protobuf/compiler/plugin.h                              \
   google/protobuf/compiler/plugin.pb.h                           \
-  google/protobuf/compiler/profile.pb.h                          \
   google/protobuf/compiler/cpp/cpp_generator.h                   \
   google/protobuf/compiler/csharp/csharp_generator.h             \
   google/protobuf/compiler/csharp/csharp_names.h                 \
@@ -184,7 +183,7 @@
 lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
 
 libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
-libprotobuf_lite_la_LDFLAGS = -version-info 13:0:0 -export-dynamic -no-undefined
+libprotobuf_lite_la_LDFLAGS = -version-info 14:0:0 -export-dynamic -no-undefined
 if HAVE_LD_VERSION_SCRIPT
 libprotobuf_lite_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf-lite.map
 EXTRA_libprotobuf_lite_la_DEPENDENCIES = libprotobuf-lite.map
@@ -198,6 +197,8 @@
   google/protobuf/stubs/hash.h                                 \
   google/protobuf/stubs/int128.cc                              \
   google/protobuf/stubs/int128.h                               \
+  google/protobuf/stubs/io_win32.cc                            \
+  google/protobuf/stubs/io_win32.h                             \
   google/protobuf/stubs/map_util.h                             \
   google/protobuf/stubs/mathutil.h                             \
   google/protobuf/stubs/once.cc                                \
@@ -220,6 +221,8 @@
   google/protobuf/arenastring.cc                               \
   google/protobuf/extension_set.cc                             \
   google/protobuf/generated_message_util.cc                    \
+  google/protobuf/generated_message_table_driven_lite.h        \
+  google/protobuf/generated_message_table_driven_lite.cc       \
   google/protobuf/message_lite.cc                              \
   google/protobuf/repeated_field.cc                            \
   google/protobuf/wire_format_lite.cc                          \
@@ -229,7 +232,7 @@
   google/protobuf/io/zero_copy_stream_impl_lite.cc
 
 libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
-libprotobuf_la_LDFLAGS = -version-info 13:0:0 -export-dynamic -no-undefined
+libprotobuf_la_LDFLAGS = -version-info 14:0:0 -export-dynamic -no-undefined
 if HAVE_LD_VERSION_SCRIPT
 libprotobuf_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf.map
 EXTRA_libprotobuf_la_DEPENDENCIES = libprotobuf.map
@@ -250,6 +253,8 @@
   google/protobuf/extension_set_heavy.cc                       \
   google/protobuf/field_mask.pb.cc                             \
   google/protobuf/generated_message_reflection.cc              \
+  google/protobuf/generated_message_table_driven_lite.h        \
+  google/protobuf/generated_message_table_driven.cc            \
   google/protobuf/map_field.cc                                 \
   google/protobuf/message.cc                                   \
   google/protobuf/reflection_internal.h                        \
@@ -318,7 +323,7 @@
 nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
 
 libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
-libprotoc_la_LDFLAGS = -version-info 13:0:0 -export-dynamic -no-undefined
+libprotoc_la_LDFLAGS = -version-info 14:0:0 -export-dynamic -no-undefined
 if HAVE_LD_VERSION_SCRIPT
 libprotoc_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotoc.map
 EXTRA_libprotoc_la_DEPENDENCIES = libprotoc.map
@@ -328,7 +333,6 @@
   google/protobuf/compiler/command_line_interface.cc           \
   google/protobuf/compiler/plugin.cc                           \
   google/protobuf/compiler/plugin.pb.cc                        \
-  google/protobuf/compiler/profile.pb.cc                       \
   google/protobuf/compiler/subprocess.cc                       \
   google/protobuf/compiler/subprocess.h                        \
   google/protobuf/compiler/zip_writer.cc                       \
@@ -677,10 +681,10 @@
   google/protobuf/unittest_preserve_unknown_enum.pb.h             \
   google/protobuf/unittest_proto3_arena.pb.cc                     \
   google/protobuf/unittest_proto3_arena.pb.h                      \
-  google/protobuf/unittest_proto3_arena_lite.pb.cc                     \
-  google/protobuf/unittest_proto3_arena_lite.pb.h                      \
-  google/protobuf/unittest_proto3_lite.pb.cc                     \
-  google/protobuf/unittest_proto3_lite.pb.h                      \
+  google/protobuf/unittest_proto3_arena_lite.pb.cc                \
+  google/protobuf/unittest_proto3_arena_lite.pb.h                 \
+  google/protobuf/unittest_proto3_lite.pb.cc                      \
+  google/protobuf/unittest_proto3_lite.pb.h                       \
   google/protobuf/unittest_well_known_types.pb.cc                 \
   google/protobuf/unittest_well_known_types.pb.h                  \
   google/protobuf/util/internal/testdata/anys.pb.cc               \
@@ -761,6 +765,7 @@
   google/protobuf/stubs/bytestream_unittest.cc                 \
   google/protobuf/stubs/common_unittest.cc                     \
   google/protobuf/stubs/int128_unittest.cc                     \
+  google/protobuf/stubs/io_win32_unittest.cc                   \
   google/protobuf/stubs/once_unittest.cc                       \
   google/protobuf/stubs/statusor_test.cc                       \
   google/protobuf/stubs/status_test.cc                         \
@@ -786,8 +791,8 @@
   google/protobuf/no_field_presence_test.cc                    \
   google/protobuf/preserve_unknown_enum_test.cc                \
   google/protobuf/proto3_arena_unittest.cc                     \
-  google/protobuf/proto3_arena_lite_unittest.cc                     \
-  google/protobuf/proto3_lite_unittest.cc                     \
+  google/protobuf/proto3_arena_lite_unittest.cc                \
+  google/protobuf/proto3_lite_unittest.cc                      \
   google/protobuf/reflection_ops_unittest.cc                   \
   google/protobuf/repeated_field_reflection_unittest.cc        \
   google/protobuf/repeated_field_unittest.cc                   \
@@ -805,6 +810,7 @@
   google/protobuf/compiler/mock_code_generator.h               \
   google/protobuf/compiler/parser_unittest.cc                  \
   google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc       \
+  google/protobuf/compiler/cpp/cpp_move_unittest.cc            \
   google/protobuf/compiler/cpp/cpp_unittest.h                  \
   google/protobuf/compiler/cpp/cpp_unittest.cc                 \
   google/protobuf/compiler/cpp/cpp_plugin_unittest.cc          \
@@ -916,15 +922,11 @@
 	    echo "#include <$${FILE}>" >> no_warning_test.cc; \
 	  fi \
 	done
-	echo "#include <gtest/gtest.h>" >> no_warning_test.cc
-	echo "TEST(NoWarningTest, Empty) {}" >> no_warning_test.cc
+	echo "int main(int, char**) { return 0; }" >> no_warning_test.cc
 
-no_warning_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la      \
-                        ../gmock/gtest/lib/libgtest.la      \
-                        ../gmock/gtest/lib/libgtest_main.la
-no_warning_test_CPPFLAGS = -I$(srcdir)/../gmock/gtest/include
+no_warning_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
 no_warning_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) \
-                           -Wall -Werror
+                           -Wall -Wextra -Werror -Wno-unused-parameter
 nodist_no_warning_test_SOURCES = no_warning_test.cc $(protoc_outputs)
 
 TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index 6c80aaa..7d53821 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -19,7 +19,10 @@
 
 namespace google {
 namespace protobuf {
-class AnyDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Any> {
+class AnyDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Any>
+     _instance;
 } _Any_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fany_2eproto {
@@ -32,20 +35,20 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -54,8 +57,7 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, type_url_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Any, value_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Any)},
 };
 
@@ -85,26 +87,22 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Any_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _Any_default_instance_.DefaultConstruct();
-}
+  _Any_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Any_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\031google/protobuf/any.proto\022\017google.prot"
       "obuf\"&\n\003Any\022\020\n\010type_url\030\001 \001(\t\022\r\n\005value\030\002"
       " \001(\014Bo\n\023com.google.protobufB\010AnyProtoP\001Z"
@@ -116,14 +114,14 @@
       descriptor, 205);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/any.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -219,8 +217,13 @@
 
 void Any::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
 }
 
 bool Any::MergePartialFromCodedStream(
@@ -236,11 +239,11 @@
       // string type_url = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_type_url()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->type_url().data(), this->type_url().length(),
+            this->type_url().data(), static_cast<int>(this->type_url().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Any.type_url"));
         } else {
@@ -252,7 +255,7 @@
       // bytes value = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
                 input, this->mutable_value()));
         } else {
@@ -263,12 +266,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -291,7 +293,7 @@
   // string type_url = 1;
   if (this->type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->type_url().data(), this->type_url().length(),
+      this->type_url().data(), static_cast<int>(this->type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Any.type_url");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -304,11 +306,16 @@
       2, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Any)
 }
 
 ::google::protobuf::uint8* Any::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -316,7 +323,7 @@
   // string type_url = 1;
   if (this->type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->type_url().data(), this->type_url().length(),
+      this->type_url().data(), static_cast<int>(this->type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Any.type_url");
     target =
@@ -331,6 +338,10 @@
         2, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Any)
   return target;
 }
@@ -339,6 +350,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // string type_url = 1;
   if (this->type_url().size() > 0) {
     total_size += 1 +
@@ -415,9 +431,11 @@
   InternalSwap(other);
 }
 void Any::InternalSwap(Any* other) {
+  using std::swap;
   type_url_.Swap(&other->type_url_);
   value_.Swap(&other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Any::GetMetadata() const {
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index bc05fb3..5ffda74 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -49,8 +49,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -69,7 +70,6 @@
     CopyFrom(from);
     return *this;
   }
-
   static const ::google::protobuf::Descriptor* descriptor();
   static const Any& default_instance();
 
@@ -91,6 +91,9 @@
   }
 
   void Swap(Any* other);
+  friend void swap(Any& a, Any& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -176,6 +179,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Any
 
 // string type_url = 1;
@@ -284,6 +291,9 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Any.value)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index 9bd3f50..c748667 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -74,6 +74,16 @@
 //       any.Unpack(foo)
 //       ...
 //
+//  Example 4: Pack and unpack a message in Go
+//
+//      foo := &pb.Foo{...}
+//      any, err := ptypes.MarshalAny(foo)
+//      ...
+//      foo := &pb.Foo{}
+//      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+//        ...
+//      }
+//
 // The pack methods provided by protobuf library will by default use
 // 'type.googleapis.com/full.type.name' as the type URL and the unpack
 // methods only use the fully qualified type name after the last '/'
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 94c6685..96a5074 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -19,11 +19,20 @@
 
 namespace google {
 namespace protobuf {
-class ApiDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Api> {
+class ApiDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Api>
+     _instance;
 } _Api_default_instance_;
-class MethodDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Method> {
+class MethodDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Method>
+     _instance;
 } _Method_default_instance_;
-class MixinDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Mixin> {
+class MixinDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Mixin>
+     _instance;
 } _Mixin_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fapi_2eproto {
@@ -36,22 +45,22 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Api, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -84,8 +93,7 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, name_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Mixin, root_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Api)},
   { 12, -1, sizeof(Method)},
   { 24, -1, sizeof(Mixin)},
@@ -119,26 +127,19 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Api_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-  _Method_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _Mixin_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
   ::google::protobuf::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::InitDefaults();
   ::google::protobuf::protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults();
-  _Api_default_instance_.DefaultConstruct();
-  _Method_default_instance_.DefaultConstruct();
-  _Mixin_default_instance_.DefaultConstruct();
-  _Api_default_instance_.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>(
+  _Api_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Api_default_instance_);_Method_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Method_default_instance_);_Mixin_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Mixin_default_instance_);_Api_default_instance_._instance.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>(
       ::google::protobuf::SourceContext::internal_default_instance());
 }
 
@@ -146,9 +147,10 @@
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\031google/protobuf/api.proto\022\017google.prot"
       "obuf\032$google/protobuf/source_context.pro"
       "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014"
@@ -175,14 +177,14 @@
     "google/protobuf/api.proto", &protobuf_RegisterTypes);
   ::google::protobuf::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::AddDescriptors();
   ::google::protobuf::protobuf_google_2fprotobuf_2ftype_2eproto::AddDescriptors();
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -240,8 +242,9 @@
 void Api::SharedCtor() {
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   version_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&source_context_, 0, reinterpret_cast<char*>(&syntax_) -
-    reinterpret_cast<char*>(&source_context_) + sizeof(syntax_));
+  ::memset(&source_context_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&syntax_) -
+      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
   _cached_size_ = 0;
 }
 
@@ -253,9 +256,7 @@
 void Api::SharedDtor() {
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   version_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete source_context_;
-  }
+  if (this != internal_default_instance()) delete source_context_;
 }
 
 void Api::SetCachedSize(int size) const {
@@ -283,6 +284,10 @@
 
 void Api::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   methods_.Clear();
   options_.Clear();
   mixins_.Clear();
@@ -293,6 +298,7 @@
   }
   source_context_ = NULL;
   syntax_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool Api::MergePartialFromCodedStream(
@@ -308,11 +314,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Api.name"));
         } else {
@@ -324,7 +330,7 @@
       // repeated .google.protobuf.Method methods = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_methods()));
         } else {
@@ -336,7 +342,7 @@
       // repeated .google.protobuf.Option options = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_options()));
         } else {
@@ -348,11 +354,11 @@
       // string version = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_version()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->version().data(), this->version().length(),
+            this->version().data(), static_cast<int>(this->version().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Api.version"));
         } else {
@@ -364,7 +370,7 @@
       // .google.protobuf.SourceContext source_context = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(42u)) {
+            static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_source_context()));
         } else {
@@ -376,7 +382,7 @@
       // repeated .google.protobuf.Mixin mixins = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_mixins()));
         } else {
@@ -388,7 +394,7 @@
       // .google.protobuf.Syntax syntax = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(56u)) {
+            static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -402,12 +408,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -430,7 +435,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Api.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -438,21 +443,23 @@
   }
 
   // repeated .google.protobuf.Method methods = 2;
-  for (unsigned int i = 0, n = this->methods_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->methods_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->methods(i), output);
+      2, this->methods(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      3, this->options(i), output);
+      3, this->options(static_cast<int>(i)), output);
   }
 
   // string version = 4;
   if (this->version().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->version().data(), this->version().length(),
+      this->version().data(), static_cast<int>(this->version().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Api.version");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -466,9 +473,10 @@
   }
 
   // repeated .google.protobuf.Mixin mixins = 6;
-  for (unsigned int i = 0, n = this->mixins_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->mixins_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      6, this->mixins(i), output);
+      6, this->mixins(static_cast<int>(i)), output);
   }
 
   // .google.protobuf.Syntax syntax = 7;
@@ -477,11 +485,16 @@
       7, this->syntax(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Api)
 }
 
 ::google::protobuf::uint8* Api::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -489,7 +502,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Api.name");
     target =
@@ -498,23 +511,25 @@
   }
 
   // repeated .google.protobuf.Method methods = 2;
-  for (unsigned int i = 0, n = this->methods_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->methods_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->methods(i), deterministic, target);
+        2, this->methods(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        3, this->options(i), deterministic, target);
+        3, this->options(static_cast<int>(i)), deterministic, target);
   }
 
   // string version = 4;
   if (this->version().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->version().data(), this->version().length(),
+      this->version().data(), static_cast<int>(this->version().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Api.version");
     target =
@@ -530,10 +545,11 @@
   }
 
   // repeated .google.protobuf.Mixin mixins = 6;
-  for (unsigned int i = 0, n = this->mixins_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->mixins_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        6, this->mixins(i), deterministic, target);
+        6, this->mixins(static_cast<int>(i)), deterministic, target);
   }
 
   // .google.protobuf.Syntax syntax = 7;
@@ -542,6 +558,10 @@
       7, this->syntax(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Api)
   return target;
 }
@@ -550,36 +570,41 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.Method methods = 2;
   {
-    unsigned int count = this->methods_size();
+    unsigned int count = static_cast<unsigned int>(this->methods_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->methods(i));
+          this->methods(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.Option options = 3;
   {
-    unsigned int count = this->options_size();
+    unsigned int count = static_cast<unsigned int>(this->options_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->options(i));
+          this->options(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.Mixin mixins = 6;
   {
-    unsigned int count = this->mixins_size();
+    unsigned int count = static_cast<unsigned int>(this->mixins_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->mixins(i));
+          this->mixins(static_cast<int>(i)));
     }
   }
 
@@ -681,14 +706,16 @@
   InternalSwap(other);
 }
 void Api::InternalSwap(Api* other) {
+  using std::swap;
   methods_.InternalSwap(&other->methods_);
   options_.InternalSwap(&other->options_);
   mixins_.InternalSwap(&other->mixins_);
   name_.Swap(&other->name_);
   version_.Swap(&other->version_);
-  std::swap(source_context_, other->source_context_);
-  std::swap(syntax_, other->syntax_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(source_context_, other->source_context_);
+  swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Api::GetMetadata() const {
@@ -874,9 +901,10 @@
   source_context_ = NULL;
 }
 const ::google::protobuf::SourceContext& Api::source_context() const {
+  const ::google::protobuf::SourceContext* p = source_context_;
   // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
-  return source_context_ != NULL ? *source_context_
-                         : *::google::protobuf::SourceContext::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceContext*>(
+      &::google::protobuf::_SourceContext_default_instance_);
 }
 ::google::protobuf::SourceContext* Api::mutable_source_context() {
   
@@ -989,8 +1017,8 @@
     response_type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.response_type_url_);
   }
   ::memcpy(&request_streaming_, &from.request_streaming_,
-    reinterpret_cast<char*>(&syntax_) -
-    reinterpret_cast<char*>(&request_streaming_) + sizeof(syntax_));
+    static_cast<size_t>(reinterpret_cast<char*>(&syntax_) -
+    reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Method)
 }
 
@@ -998,8 +1026,9 @@
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   request_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   response_type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&request_streaming_, 0, reinterpret_cast<char*>(&syntax_) -
-    reinterpret_cast<char*>(&request_streaming_) + sizeof(syntax_));
+  ::memset(&request_streaming_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&syntax_) -
+      reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
   _cached_size_ = 0;
 }
 
@@ -1039,12 +1068,18 @@
 
 void Method::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   options_.Clear();
   name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&request_streaming_, 0, reinterpret_cast<char*>(&syntax_) -
-    reinterpret_cast<char*>(&request_streaming_) + sizeof(syntax_));
+  ::memset(&request_streaming_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&syntax_) -
+      reinterpret_cast<char*>(&request_streaming_)) + sizeof(syntax_));
+  _internal_metadata_.Clear();
 }
 
 bool Method::MergePartialFromCodedStream(
@@ -1060,11 +1095,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Method.name"));
         } else {
@@ -1076,11 +1111,11 @@
       // string request_type_url = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_request_type_url()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->request_type_url().data(), this->request_type_url().length(),
+            this->request_type_url().data(), static_cast<int>(this->request_type_url().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Method.request_type_url"));
         } else {
@@ -1092,7 +1127,7 @@
       // bool request_streaming = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -1106,11 +1141,11 @@
       // string response_type_url = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_response_type_url()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->response_type_url().data(), this->response_type_url().length(),
+            this->response_type_url().data(), static_cast<int>(this->response_type_url().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Method.response_type_url"));
         } else {
@@ -1122,7 +1157,7 @@
       // bool response_streaming = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(40u)) {
+            static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -1136,7 +1171,7 @@
       // repeated .google.protobuf.Option options = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_options()));
         } else {
@@ -1148,7 +1183,7 @@
       // .google.protobuf.Syntax syntax = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(56u)) {
+            static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -1162,12 +1197,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1190,7 +1224,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Method.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1200,7 +1234,7 @@
   // string request_type_url = 2;
   if (this->request_type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->request_type_url().data(), this->request_type_url().length(),
+      this->request_type_url().data(), static_cast<int>(this->request_type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Method.request_type_url");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1215,7 +1249,7 @@
   // string response_type_url = 4;
   if (this->response_type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->response_type_url().data(), this->response_type_url().length(),
+      this->response_type_url().data(), static_cast<int>(this->response_type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Method.response_type_url");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1228,9 +1262,10 @@
   }
 
   // repeated .google.protobuf.Option options = 6;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      6, this->options(i), output);
+      6, this->options(static_cast<int>(i)), output);
   }
 
   // .google.protobuf.Syntax syntax = 7;
@@ -1239,11 +1274,16 @@
       7, this->syntax(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Method)
 }
 
 ::google::protobuf::uint8* Method::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1251,7 +1291,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Method.name");
     target =
@@ -1262,7 +1302,7 @@
   // string request_type_url = 2;
   if (this->request_type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->request_type_url().data(), this->request_type_url().length(),
+      this->request_type_url().data(), static_cast<int>(this->request_type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Method.request_type_url");
     target =
@@ -1278,7 +1318,7 @@
   // string response_type_url = 4;
   if (this->response_type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->response_type_url().data(), this->response_type_url().length(),
+      this->response_type_url().data(), static_cast<int>(this->response_type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Method.response_type_url");
     target =
@@ -1292,10 +1332,11 @@
   }
 
   // repeated .google.protobuf.Option options = 6;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        6, this->options(i), deterministic, target);
+        6, this->options(static_cast<int>(i)), deterministic, target);
   }
 
   // .google.protobuf.Syntax syntax = 7;
@@ -1304,6 +1345,10 @@
       7, this->syntax(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Method)
   return target;
 }
@@ -1312,14 +1357,19 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.Option options = 6;
   {
-    unsigned int count = this->options_size();
+    unsigned int count = static_cast<unsigned int>(this->options_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->options(i));
+          this->options(static_cast<int>(i)));
     }
   }
 
@@ -1436,14 +1486,16 @@
   InternalSwap(other);
 }
 void Method::InternalSwap(Method* other) {
+  using std::swap;
   options_.InternalSwap(&other->options_);
   name_.Swap(&other->name_);
   request_type_url_.Swap(&other->request_type_url_);
   response_type_url_.Swap(&other->response_type_url_);
-  std::swap(request_streaming_, other->request_streaming_);
-  std::swap(response_streaming_, other->response_streaming_);
-  std::swap(syntax_, other->syntax_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(request_streaming_, other->request_streaming_);
+  swap(response_streaming_, other->response_streaming_);
+  swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Method::GetMetadata() const {
@@ -1759,8 +1811,13 @@
 
 void Mixin::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
 }
 
 bool Mixin::MergePartialFromCodedStream(
@@ -1776,11 +1833,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Mixin.name"));
         } else {
@@ -1792,11 +1849,11 @@
       // string root = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_root()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->root().data(), this->root().length(),
+            this->root().data(), static_cast<int>(this->root().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Mixin.root"));
         } else {
@@ -1807,12 +1864,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1835,7 +1891,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Mixin.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1845,18 +1901,23 @@
   // string root = 2;
   if (this->root().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->root().data(), this->root().length(),
+      this->root().data(), static_cast<int>(this->root().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Mixin.root");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
       2, this->root(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Mixin)
 }
 
 ::google::protobuf::uint8* Mixin::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1864,7 +1925,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Mixin.name");
     target =
@@ -1875,7 +1936,7 @@
   // string root = 2;
   if (this->root().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->root().data(), this->root().length(),
+      this->root().data(), static_cast<int>(this->root().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Mixin.root");
     target =
@@ -1883,6 +1944,10 @@
         2, this->root(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Mixin)
   return target;
 }
@@ -1891,6 +1956,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // string name = 1;
   if (this->name().size() > 0) {
     total_size += 1 +
@@ -1967,9 +2037,11 @@
   InternalSwap(other);
 }
 void Mixin::InternalSwap(Mixin* other) {
+  using std::swap;
   name_.Swap(&other->name_);
   root_.Swap(&other->root_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Mixin::GetMetadata() const {
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index 108c63a..bed136d 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -37,30 +37,12 @@
 class Api;
 class ApiDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern ApiDefaultTypeInternal _Api_default_instance_;
-class Enum;
-class EnumDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern EnumDefaultTypeInternal _Enum_default_instance_;
-class EnumValue;
-class EnumValueDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern EnumValueDefaultTypeInternal _EnumValue_default_instance_;
-class Field;
-class FieldDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern FieldDefaultTypeInternal _Field_default_instance_;
 class Method;
 class MethodDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern MethodDefaultTypeInternal _Method_default_instance_;
 class Mixin;
 class MixinDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
-class Option;
-class OptionDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern OptionDefaultTypeInternal _Option_default_instance_;
-class SourceContext;
-class SourceContextDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
-class Type;
-class TypeDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern TypeDefaultTypeInternal _Type_default_instance_;
 }  // namespace protobuf
 }  // namespace google
 
@@ -74,8 +56,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -94,7 +77,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Api(Api&& from) noexcept
+    : Api() {
+    *this = ::std::move(from);
+  }
 
+  inline Api& operator=(Api&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   static const ::google::protobuf::Descriptor* descriptor();
   static const Api& default_instance();
 
@@ -106,6 +103,9 @@
     0;
 
   void Swap(Api* other);
+  friend void swap(Api& a, Api& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -253,7 +253,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Method(Method&& from) noexcept
+    : Method() {
+    *this = ::std::move(from);
+  }
 
+  inline Method& operator=(Method&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   static const ::google::protobuf::Descriptor* descriptor();
   static const Method& default_instance();
 
@@ -265,6 +279,9 @@
     1;
 
   void Swap(Method* other);
+  friend void swap(Method& a, Method& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -405,7 +422,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Mixin(Mixin&& from) noexcept
+    : Mixin() {
+    *this = ::std::move(from);
+  }
 
+  inline Mixin& operator=(Mixin&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   static const ::google::protobuf::Descriptor* descriptor();
   static const Mixin& default_instance();
 
@@ -417,6 +448,9 @@
     2;
 
   void Swap(Mixin* other);
+  friend void swap(Mixin& a, Mixin& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -501,6 +535,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Api
 
 // string name = 1;
@@ -678,9 +716,10 @@
   source_context_ = NULL;
 }
 inline const ::google::protobuf::SourceContext& Api::source_context() const {
+  const ::google::protobuf::SourceContext* p = source_context_;
   // @@protoc_insertion_point(field_get:google.protobuf.Api.source_context)
-  return source_context_ != NULL ? *source_context_
-                         : *::google::protobuf::SourceContext::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceContext*>(
+      &::google::protobuf::_SourceContext_default_instance_);
 }
 inline ::google::protobuf::SourceContext* Api::mutable_source_context() {
   
@@ -1097,6 +1136,9 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Mixin.root)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 // -------------------------------------------------------------------
 
diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto
index 7c30e8b..f37ee2f 100644
--- a/src/google/protobuf/api.proto
+++ b/src/google/protobuf/api.proto
@@ -42,26 +42,33 @@
 option objc_class_prefix = "GPB";
 option go_package = "google.golang.org/genproto/protobuf/api;api";
 
-// Api is a light-weight descriptor for a protocol buffer service.
+// Api is a light-weight descriptor for an API Interface.
+//
+// Interfaces are also described as "protocol buffer services" in some contexts,
+// such as by the "service" keyword in a .proto file, but they are different
+// from API Services, which represent a concrete implementation of an interface
+// as opposed to simply a description of methods and bindings. They are also
+// sometimes simply referred to as "APIs" in other contexts, such as the name of
+// this message itself. See https://cloud.google.com/apis/design/glossary for
+// detailed terminology.
 message Api {
 
-  // The fully qualified name of this api, including package name
-  // followed by the api's simple name.
+  // The fully qualified name of this interface, including package name
+  // followed by the interface's simple name.
   string name = 1;
 
-  // The methods of this api, in unspecified order.
+  // The methods of this interface, in unspecified order.
   repeated Method methods = 2;
 
-  // Any metadata attached to the API.
+  // Any metadata attached to the interface.
   repeated Option options = 3;
 
-  // A version string for this api. If specified, must have the form
-  // `major-version.minor-version`, as in `1.10`. If the minor version
-  // is omitted, it defaults to zero. If the entire version field is
-  // empty, the major version is derived from the package name, as
-  // outlined below. If the field is not empty, the version in the
-  // package name will be verified to be consistent with what is
-  // provided here.
+  // A version string for this interface. If specified, must have the form
+  // `major-version.minor-version`, as in `1.10`. If the minor version is
+  // omitted, it defaults to zero. If the entire version field is empty, the
+  // major version is derived from the package name, as outlined below. If the
+  // field is not empty, the version in the package name will be verified to be
+  // consistent with what is provided here.
   //
   // The versioning schema uses [semantic
   // versioning](http://semver.org) where the major version number
@@ -71,10 +78,10 @@
   // chosen based on the product plan.
   //
   // The major version is also reflected in the package name of the
-  // API, which must end in `v<major-version>`, as in
+  // interface, which must end in `v<major-version>`, as in
   // `google.feature.v1`. For major versions 0 and 1, the suffix can
   // be omitted. Zero major versions must only be used for
-  // experimental, none-GA apis.
+  // experimental, non-GA interfaces.
   //
   //
   string version = 4;
@@ -83,14 +90,14 @@
   // message.
   SourceContext source_context = 5;
 
-  // Included APIs. See [Mixin][].
+  // Included interfaces. See [Mixin][].
   repeated Mixin mixins = 6;
 
   // The source syntax of the service.
   Syntax syntax = 7;
 }
 
-// Method represents a method of an api.
+// Method represents a method of an API interface.
 message Method {
 
   // The simple name of this method.
@@ -115,9 +122,9 @@
   Syntax syntax = 7;
 }
 
-// Declares an API to be included in this API. The including API must
-// redeclare all the methods from the included API, but documentation
-// and options are inherited as follows:
+// Declares an API Interface to be included in this interface. The including
+// interface must redeclare all the methods from the included interface, but
+// documentation and options are inherited as follows:
 //
 // - If after comment and whitespace stripping, the documentation
 //   string of the redeclared method is empty, it will be inherited
@@ -129,7 +136,8 @@
 //
 // - If an http annotation is inherited, the path pattern will be
 //   modified as follows. Any version prefix will be replaced by the
-//   version of the including API plus the [root][] path if specified.
+//   version of the including interface plus the [root][] path if
+//   specified.
 //
 // Example of a simple mixin:
 //
@@ -193,7 +201,7 @@
 //       ...
 //     }
 message Mixin {
-  // The fully qualified name of the API which is included.
+  // The fully qualified name of the interface which is included.
   string name = 1;
 
   // If non-empty specifies a path under which inherited HTTP paths
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 16cf895..fe38f5d 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -39,32 +39,35 @@
 #endif  // ADDRESS_SANITIZER
 
 namespace google {
+static const size_t kMinCleanupListElements = 8;
+static const size_t kMaxCleanupListElements = 64;  // 1kB on 64-bit.
+
 namespace protobuf {
+namespace internal {
 
 
-google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
+google::protobuf::internal::SequenceNumber ArenaImpl::lifecycle_id_generator_;
 #if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-Arena::ThreadCache& Arena::thread_cache() {
+ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
   static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
       new internal::ThreadLocalStorage<ThreadCache>();
   return *thread_cache_->Get();
 }
 #elif defined(PROTOBUF_USE_DLLS)
-Arena::ThreadCache& Arena::thread_cache() {
+ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
   static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
   return thread_cache_;
 }
 #else
-GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
+GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};
 #endif
 
-void Arena::Init() {
+void ArenaImpl::Init() {
   lifecycle_id_ = lifecycle_id_generator_.GetNext();
   blocks_ = 0;
   hint_ = 0;
   space_allocated_ = 0;
   owns_first_block_ = true;
-  cleanup_list_ = 0;
 
   if (options_.initial_block != NULL && options_.initial_block_size > 0) {
     GOOGLE_CHECK_GE(options_.initial_block_size, sizeof(Block))
@@ -75,134 +78,154 @@
     first_block->size = options_.initial_block_size;
     first_block->pos = kHeaderSize;
     first_block->next = NULL;
+    first_block->cleanup = NULL;
     // Thread which calls Init() owns the first block. This allows the
     // single-threaded case to allocate on the first block without taking any
     // locks.
     first_block->owner = &thread_cache();
-    SetThreadCacheBlock(first_block);
     AddBlockInternal(first_block);
+    CacheBlock(first_block);
     owns_first_block_ = false;
   }
-
-  // Call the initialization hook
-  if (options_.on_arena_init != NULL) {
-    hooks_cookie_ = options_.on_arena_init(this);
-  } else {
-    hooks_cookie_ = NULL;
-  }
 }
 
-Arena::~Arena() {
-  uint64 space_allocated = ResetInternal();
+ArenaImpl::~ArenaImpl() { ResetInternal(); }
 
-  // Call the destruction hook
-  if (options_.on_arena_destruction != NULL) {
-    options_.on_arena_destruction(this, hooks_cookie_, space_allocated);
-  }
-}
-
-uint64 Arena::Reset() {
+uint64 ArenaImpl::Reset() {
   // Invalidate any ThreadCaches pointing to any blocks we just destroyed.
   lifecycle_id_ = lifecycle_id_generator_.GetNext();
   return ResetInternal();
 }
 
-uint64 Arena::ResetInternal() {
-  CleanupList();
-  uint64 space_allocated = FreeBlocks();
-
-  // Call the reset hook
-  if (options_.on_arena_reset != NULL) {
-    options_.on_arena_reset(this, hooks_cookie_, space_allocated);
-  }
+uint64 ArenaImpl::ResetInternal() {
+  Block* head =
+      reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
+  CleanupList(head);
+  uint64 space_allocated = FreeBlocks(head);
 
   return space_allocated;
 }
 
-Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n,
-                              size_t start_block_size, size_t max_block_size) {
+ArenaImpl::Block* ArenaImpl::NewBlock(void* me, Block* my_last_block,
+                                      size_t min_bytes, size_t start_block_size,
+                                      size_t max_block_size) {
   size_t size;
   if (my_last_block != NULL) {
     // Double the current block size, up to a limit.
-    size = 2 * (my_last_block->size);
-    if (size > max_block_size) size = max_block_size;
+    size = std::min(2 * my_last_block->size, max_block_size);
   } else {
     size = start_block_size;
   }
-  // Verify that n + kHeaderSize won't overflow.
-  GOOGLE_CHECK_LE(n, std::numeric_limits<size_t>::max() - kHeaderSize);
-  size = std::max(size, kHeaderSize + n);
+  // Verify that min_bytes + kHeaderSize won't overflow.
+  GOOGLE_CHECK_LE(min_bytes, std::numeric_limits<size_t>::max() - kHeaderSize);
+  size = std::max(size, kHeaderSize + min_bytes);
 
   Block* b = reinterpret_cast<Block*>(options_.block_alloc(size));
-  b->pos = kHeaderSize + n;
+  b->pos = kHeaderSize;
   b->size = size;
   b->owner = me;
+  b->cleanup = NULL;
 #ifdef ADDRESS_SANITIZER
   // Poison the rest of the block for ASAN. It was unpoisoned by the underlying
   // malloc but it's not yet usable until we return it as part of an allocation.
   ASAN_POISON_MEMORY_REGION(
       reinterpret_cast<char*>(b) + b->pos, b->size - b->pos);
 #endif  // ADDRESS_SANITIZER
+  AddBlock(b);
   return b;
 }
 
-void Arena::AddBlock(Block* b) {
+void ArenaImpl::AddBlock(Block* b) {
   MutexLock l(&blocks_lock_);
   AddBlockInternal(b);
 }
 
-void Arena::AddBlockInternal(Block* b) {
+void ArenaImpl::AddBlockInternal(Block* b) {
   b->next = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
   google::protobuf::internal::Release_Store(&blocks_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
-  if (b->avail() != 0) {
-    // Direct future allocations to this block.
-    google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
-  }
   space_allocated_ += b->size;
 }
 
-void Arena::AddListNode(void* elem, void (*cleanup)(void*)) {
-  Node* node = reinterpret_cast<Node*>(AllocateAligned(sizeof(Node)));
-  node->elem = elem;
-  node->cleanup = cleanup;
-  node->next = reinterpret_cast<Node*>(
-      google::protobuf::internal::NoBarrier_AtomicExchange(&cleanup_list_,
-            reinterpret_cast<google::protobuf::internal::AtomicWord>(node)));
+ArenaImpl::Block* ArenaImpl::ExpandCleanupList(Block* b) {
+  size_t size = b->cleanup ? b->cleanup->size * 2 : kMinCleanupListElements;
+  size = std::min(size, kMaxCleanupListElements);
+  size_t bytes = internal::AlignUpTo8(CleanupChunk::SizeOf(size));
+  if (b->avail() < bytes) {
+    b = GetBlock(bytes);
+  }
+  CleanupChunk* list =
+      reinterpret_cast<CleanupChunk*>(AllocFromBlock(b, bytes));
+  list->next = b->cleanup;
+  list->size = size;
+  list->len = 0;
+  b->cleanup = list;
+  return b;
 }
 
-void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) {
-  // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
-  n = (n + 7) & -8;
-
-  // Monitor allocation if needed.
-  if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL) &&
-      options_.on_arena_allocation != NULL) {
-    options_.on_arena_allocation(allocated, n, hooks_cookie_);
+inline GOOGLE_ATTRIBUTE_ALWAYS_INLINE void ArenaImpl::AddCleanupInBlock(
+    Block* b, void* elem, void (*cleanup)(void*)) {
+  if (b->cleanup == NULL || b->cleanup->len == b->cleanup->size) {
+    b = ExpandCleanupList(b);
   }
 
+  CleanupNode* node = &b->cleanup->nodes[b->cleanup->len++];
+
+  node->elem = elem;
+  node->cleanup = cleanup;
+}
+
+void ArenaImpl::AddCleanup(void* elem, void (*cleanup)(void*)) {
+  return AddCleanupInBlock(GetBlock(0), elem, cleanup);
+}
+
+void* ArenaImpl::AllocateAligned(size_t n) {
+  GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
+
+  return AllocFromBlock(GetBlock(n), n);
+}
+
+void* ArenaImpl::AllocateAlignedAndAddCleanup(size_t n,
+                                              void (*cleanup)(void*)) {
+  GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
+
+  Block* b = GetBlock(n);
+  void* mem = AllocFromBlock(b, n);
+  AddCleanupInBlock(b, mem, cleanup);
+  return mem;
+}
+
+inline GOOGLE_ATTRIBUTE_ALWAYS_INLINE ArenaImpl::Block* ArenaImpl::GetBlock(size_t n) {
+  Block* my_block = NULL;
+
   // If this thread already owns a block in this arena then try to use that.
   // This fast path optimizes the case where multiple threads allocate from the
   // same arena.
-  if (thread_cache().last_lifecycle_id_seen == lifecycle_id_ &&
-      thread_cache().last_block_used_ != NULL) {
-    if (thread_cache().last_block_used_->avail() < n) {
-      return SlowAlloc(n);
+  ThreadCache* tc = &thread_cache();
+  if (tc->last_lifecycle_id_seen == lifecycle_id_) {
+    my_block = tc->last_block_used_;
+    if (my_block->avail() >= n) {
+      return my_block;
     }
-    return AllocFromBlock(thread_cache().last_block_used_, n);
   }
 
   // Check whether we own the last accessed block on this arena.
   // This fast path optimizes the case where a single thread uses multiple
   // arenas.
-  void* me = &thread_cache();
   Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
-  if (!b || b->owner != me || b->avail() < n) {
-    return SlowAlloc(n);
+  if (b != NULL && b->owner == tc) {
+    my_block = b;
+    if (my_block->avail() >= n) {
+      return my_block;
+    }
   }
-  return AllocFromBlock(b, n);
+  return GetBlockSlow(tc, my_block, n);
 }
 
-void* Arena::AllocFromBlock(Block* b, size_t n) {
+inline GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* ArenaImpl::AllocFromBlock(Block* b,
+                                                               size_t n) {
+  GOOGLE_DCHECK_EQ(internal::AlignUpTo8(b->pos), b->pos);  // Must be already aligned.
+  GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
+  GOOGLE_DCHECK_GE(b->avail(), n);
   size_t p = b->pos;
   b->pos = p + n;
 #ifdef ADDRESS_SANITIZER
@@ -211,27 +234,32 @@
   return reinterpret_cast<char*>(b) + p;
 }
 
-void* Arena::SlowAlloc(size_t n) {
-  void* me = &thread_cache();
+ArenaImpl::Block* ArenaImpl::GetBlockSlow(void* me, Block* my_full_block,
+                                          size_t n) {
   Block* b = FindBlock(me);  // Find block owned by me.
-  // See if allocation fits in my latest block.
-  if (b != NULL && b->avail() >= n) {
-    SetThreadCacheBlock(b);
-    google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(b));
-    return AllocFromBlock(b, n);
+  if (b == NULL || b->avail() < n) {
+    b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
+
+    // Try to steal the cleanup list from my_full_block.  It's too full for this
+    // allocation, but it might have space left in its cleanup list and there's
+    // no reason to waste that memory.
+    if (my_full_block) {
+      GOOGLE_DCHECK_EQ(my_full_block->owner, me);
+      GOOGLE_DCHECK(b->cleanup == NULL);
+      b->cleanup = my_full_block->cleanup;
+      my_full_block->cleanup = NULL;
+    }
   }
-  b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size);
-  AddBlock(b);
-  SetThreadCacheBlock(b);
-  return reinterpret_cast<char*>(b) + kHeaderSize;
+  CacheBlock(b);
+  return b;
 }
 
-uint64 Arena::SpaceAllocated() const {
+uint64 ArenaImpl::SpaceAllocated() const {
   MutexLock l(&blocks_lock_);
   return space_allocated_;
 }
 
-uint64 Arena::SpaceUsed() const {
+uint64 ArenaImpl::SpaceUsed() const {
   uint64 space_used = 0;
   Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
   while (b != NULL) {
@@ -241,14 +269,11 @@
   return space_used;
 }
 
-std::pair<uint64, uint64> Arena::SpaceAllocatedAndUsed() const {
-  return std::make_pair(SpaceAllocated(), SpaceUsed());
-}
-
-uint64 Arena::FreeBlocks() {
+uint64 ArenaImpl::FreeBlocks(Block* head) {
   uint64 space_allocated = 0;
-  Block* b = reinterpret_cast<Block*>(google::protobuf::internal::NoBarrier_Load(&blocks_));
   Block* first_block = NULL;
+  Block* b = head;
+
   while (b != NULL) {
     space_allocated += (b->size);
     Block* next = b->next;
@@ -281,27 +306,35 @@
     // Make the first block that was passed in through ArenaOptions
     // available for reuse.
     first_block->pos = kHeaderSize;
+    first_block->cleanup = NULL;
     // Thread which calls Reset() owns the first block. This allows the
     // single-threaded case to allocate on the first block without taking any
     // locks.
     first_block->owner = &thread_cache();
-    SetThreadCacheBlock(first_block);
     AddBlockInternal(first_block);
+    CacheBlock(first_block);
   }
   return space_allocated;
 }
 
-void Arena::CleanupList() {
-  Node* head =
-      reinterpret_cast<Node*>(google::protobuf::internal::NoBarrier_Load(&cleanup_list_));
-  while (head != NULL) {
-    head->cleanup(head->elem);
-    head = head->next;
+void ArenaImpl::CleanupList(Block* head) {
+  // Have to do this in a first pass, because some of the destructors might
+  // refer to memory in other blocks.
+  for (Block* b = head; b; b = b->next) {
+    CleanupChunk* list = b->cleanup;
+    while (list) {
+      size_t n = list->len;
+      CleanupNode* node = &list->nodes[list->len - 1];
+      for (size_t i = 0; i < n; i++, node--) {
+        node->cleanup(node->elem);
+      }
+      list = list->next;
+    }
+    b->cleanup = NULL;
   }
-  cleanup_list_ = 0;
 }
 
-Arena::Block* Arena::FindBlock(void* me) {
+ArenaImpl::Block* ArenaImpl::FindBlock(void* me) {
   // TODO(sanjay): We might want to keep a separate list with one
   // entry per thread.
   Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&blocks_));
@@ -311,5 +344,14 @@
   return b;
 }
 
+}  // namespace internal
+
+void Arena::OnArenaAllocation(const std::type_info* allocated_type,
+                              size_t n) const {
+  if (on_arena_allocation_ != NULL) {
+    on_arena_allocation_(allocated_type, n, hooks_cookie_);
+  }
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 0ffc600..f8a9470 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -37,7 +37,7 @@
 #ifdef max
 #undef max  // Visual Studio defines this macro
 #endif
-#if __cplusplus >= 201103L
+#if LANG_CXX11
 #include <google/protobuf/stubs/type_traits.h>
 #endif
 #if defined(_MSC_VER) && !_HAS_EXCEPTIONS
@@ -51,13 +51,7 @@
 #include <typeinfo>
 #endif
 
-#include <google/protobuf/stubs/atomic_sequence_num.h>
-#include <google/protobuf/stubs/atomicops.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/stubs/type_traits.h>
-
+#include <google/protobuf/arena_impl.h>
 
 namespace google {
 namespace protobuf {
@@ -122,7 +116,6 @@
   // from the arena. By default, it contains a ptr to a wrapper function that
   // calls free.
   void (*block_dealloc)(void*, size_t);
-
   // Hooks for adding external functionality such as user-specific metrics
   // collection, specific debugging abilities, etc.
   // Init hook may return a pointer to a cookie to be stored in the arena.
@@ -225,21 +218,38 @@
  public:
   // Arena constructor taking custom options. See ArenaOptions below for
   // descriptions of the options available.
-  explicit Arena(const ArenaOptions& options) : options_(options) {
-    Init();
+  explicit Arena(const ArenaOptions& options) : impl_(options) {
+    Init(options);
   }
 
   // Default constructor with sensible default options, tuned for average
   // use-cases.
-  Arena() {
-    Init();
+  Arena() : impl_(ArenaOptions()) { Init(ArenaOptions()); }
+
+  ~Arena() {
+    uint64 space_allocated = SpaceAllocated();
+    // Call the reset hook
+    if (on_arena_reset_ != NULL) {
+      on_arena_reset_(this, hooks_cookie_, space_allocated);
+    }
+
+    // Call the destruction hook
+    if (on_arena_destruction_ != NULL) {
+      on_arena_destruction_(this, hooks_cookie_, space_allocated);
+    }
   }
 
-  // Destructor deletes all owned heap allocated objects, and destructs objects
-  // that have non-trivial destructors, except for proto2 message objects whose
-  // destructors can be skipped. Also, frees all blocks except the initial block
-  // if it was passed in.
-  ~Arena();
+  void Init(const ArenaOptions& options) {
+    on_arena_allocation_ = options.on_arena_allocation;
+    on_arena_reset_ = options.on_arena_reset;
+    on_arena_destruction_ = options.on_arena_destruction;
+    // Call the initialization hook
+    if (options.on_arena_init != NULL) {
+      hooks_cookie_ = options.on_arena_init(this);
+    } else {
+      hooks_cookie_ = NULL;
+    }
+  }
 
   // API to create proto2 message objects on the arena. If the arena passed in
   // is NULL, then a heap allocated object is returned. Type T must be a message
@@ -253,10 +263,15 @@
   // allocation protocol, documented above.
   template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   static T* CreateMessage(::google::protobuf::Arena* arena) {
+#if LANG_CXX11
+    static_assert(
+        InternalHelper<T>::is_arena_constructable::value,
+        "CreateMessage can only construct types that are ArenaConstructable");
+#endif
     if (arena == NULL) {
       return new T;
     } else {
-      return arena->CreateMessageInternal<T>(static_cast<T*>(0));
+      return arena->CreateMessageInternal<T>();
     }
   }
 
@@ -265,11 +280,15 @@
   // take additional constructor arguments.
   template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) {
+#if LANG_CXX11
+    static_assert(
+        InternalHelper<T>::is_arena_constructable::value,
+        "CreateMessage can only construct types that are ArenaConstructable");
+#endif
     if (arena == NULL) {
       return new T(NULL, arg);
     } else {
-      return arena->CreateMessageInternal<T>(static_cast<T*>(0),
-                                             arg);
+      return arena->CreateMessageInternal<T>(arg);
     }
   }
 
@@ -280,11 +299,15 @@
   static T* CreateMessage(::google::protobuf::Arena* arena,
                           const Arg1& arg1,
                           const Arg2& arg2) {
+#if LANG_CXX11
+    static_assert(
+        InternalHelper<T>::is_arena_constructable::value,
+        "CreateMessage can only construct types that are ArenaConstructable");
+#endif
     if (arena == NULL) {
       return new T(NULL, arg1, arg2);
     } else {
-      return arena->CreateMessageInternal<T>(static_cast<T*>(0),
-                                             arg1, arg2);
+      return arena->CreateMessageInternal<T>(arg1, arg2);
     }
   }
 
@@ -463,24 +486,33 @@
   // Returns the total space allocated by the arena, which is the sum of the
   // sizes of the underlying blocks. This method is relatively fast; a counter
   // is kept as blocks are allocated.
-  uint64 SpaceAllocated() const;
+  uint64 SpaceAllocated() const { return impl_.SpaceAllocated(); }
   // Returns the total space used by the arena. Similar to SpaceAllocated but
   // does not include free space and block overhead. The total space returned
   // may not include space used by other threads executing concurrently with
   // the call to this method.
-  GOOGLE_ATTRIBUTE_NOINLINE uint64 SpaceUsed() const;
+  uint64 SpaceUsed() const { return impl_.SpaceUsed(); }
   // DEPRECATED. Please use SpaceAllocated() and SpaceUsed().
   //
   // Combines SpaceAllocated and SpaceUsed. Returns a pair of
   // <space_allocated, space_used>.
-  GOOGLE_ATTRIBUTE_NOINLINE std::pair<uint64, uint64> SpaceAllocatedAndUsed() const;
+  std::pair<uint64, uint64> SpaceAllocatedAndUsed() const {
+    return std::make_pair(SpaceAllocated(), SpaceUsed());
+  }
 
   // Frees all storage allocated by this arena after calling destructors
   // registered with OwnDestructor() and freeing objects registered with Own().
   // Any objects allocated on this arena are unusable after this call. It also
   // returns the total space used by the arena which is the sums of the sizes
   // of the allocated blocks. This method is not thread-safe.
-  GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset();
+  GOOGLE_ATTRIBUTE_NOINLINE uint64 Reset() {
+    uint64 space_allocated = SpaceAllocated();
+    // Call the reset hook
+    if (on_arena_reset_ != NULL) {
+      on_arena_reset_(this, hooks_cookie_, space_allocated);
+    }
+    return impl_.Reset();
+  }
 
   // Adds |object| to a list of heap-allocated objects to be freed with |delete|
   // when the arena is destroyed or reset.
@@ -497,7 +529,7 @@
   template <typename T> GOOGLE_ATTRIBUTE_NOINLINE
   void OwnDestructor(T* object) {
     if (object != NULL) {
-      AddListNode(object, &internal::arena_destruct_object<T>);
+      impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
     }
   }
 
@@ -507,7 +539,7 @@
   // the class destructor.
   GOOGLE_ATTRIBUTE_NOINLINE void OwnCustomDestructor(void* object,
                                               void (*destruct)(void*)) {
-    AddListNode(object, destruct);
+    impl_.AddCleanup(object, destruct);
   }
 
   // Retrieves the arena associated with |value| if |value| is an arena-capable
@@ -516,19 +548,59 @@
   // resolves at compile-time.
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   static ::google::protobuf::Arena* GetArena(const T* value) {
-    return GetArenaInternal(value, static_cast<T*>(0));
+    return GetArenaInternal(value, is_arena_constructable<T>());
   }
 
- private:
-  struct InternalIsArenaConstructableHelper {
+  template <typename T>
+  class InternalHelper {
+    template <typename U>
+    static char DestructorSkippable(const typename U::DestructorSkippable_*);
+    template <typename U>
+    static double DestructorSkippable(...);
+
+    typedef google::protobuf::internal::integral_constant<
+        bool, sizeof(DestructorSkippable<T>(static_cast<const T*>(0))) ==
+                      sizeof(char) ||
+                  google::protobuf::internal::has_trivial_destructor<T>::value>
+        is_destructor_skippable;
+
     template<typename U>
     static char ArenaConstructable(
         const typename U::InternalArenaConstructable_*);
     template<typename U>
     static double ArenaConstructable(...);
+
+    typedef google::protobuf::internal::integral_constant<bool, sizeof(ArenaConstructable<T>(
+                                              static_cast<const T*>(0))) ==
+                                              sizeof(char)>
+        is_arena_constructable;
+
+#if LANG_CXX11
+    template <typename... Args>
+    static T* Construct(void* ptr, Args&&... args) {
+      return new (ptr) T(std::forward<Args>(args)...);
+    }
+#else
+    template <typename Arg1>
+    static T* Construct(void* ptr, const Arg1& arg1) {
+      return new (ptr) T(arg1);
+    }
+    template <typename Arg1, typename Arg2>
+    static T* Construct(void* ptr, const Arg1& arg1, const Arg2& arg2) {
+      return new (ptr) T(arg1, arg2);
+    }
+    template <typename Arg1, typename Arg2, typename Arg3>
+    static T* Construct(void* ptr, const Arg1& arg1,
+                        const Arg2& arg2, const Arg3& arg3) {
+      return new (ptr) T(arg1, arg2, arg3);
+    }
+#endif  // LANG_CXX11
+
+    static Arena* GetArena(const T* p) { return p->GetArenaNoVirtual(); }
+
+    friend class Arena;
   };
 
- public:
   // Helper typetrait that indicates support for arenas in a type T at compile
   // time. This is public only to allow construction of higher-level templated
   // utilities. is_arena_constructable<T>::value is true if the message type T
@@ -537,113 +609,54 @@
   // This is inside Arena because only Arena has the friend relationships
   // necessary to see the underlying generated code traits.
   template <typename T>
-  struct is_arena_constructable
-      : public google::protobuf::internal::integral_constant<
-            bool, sizeof(InternalIsArenaConstructableHelper::ArenaConstructable<
-                         const T>(static_cast<const T*>(0))) == sizeof(char)> {
-  };
+  struct is_arena_constructable : InternalHelper<T>::is_arena_constructable {};
 
  private:
-  // Blocks are variable length malloc-ed objects.  The following structure
-  // describes the common header for all blocks.
-  struct Block {
-    void* owner;   // &ThreadCache of thread that owns this block, or
-                   // &this->owner if not yet owned by a thread.
-    Block* next;   // Next block in arena (may have different owner)
-    // ((char*) &block) + pos is next available byte. It is always
-    // aligned at a multiple of 8 bytes.
-    size_t pos;
-    size_t size;  // total size of the block.
-    GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
-    // data follows
-  };
-
-  template<typename Type> friend class ::google::protobuf::internal::GenericTypeHandler;
-  friend class MockArena;              // For unit-testing.
-  friend class internal::ArenaString;  // For AllocateAligned.
-  friend class internal::LazyField;    // For CreateMaybeMessage.
-
-  struct ThreadCache {
-    // The ThreadCache is considered valid as long as this matches the
-    // lifecycle_id of the arena being used.
-    int64 last_lifecycle_id_seen;
-    Block* last_block_used_;
-  };
-
-  static const size_t kHeaderSize = sizeof(Block);
-  static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
-#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-  // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
-  // local storage class we implemented.
-  // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
-  static ThreadCache& thread_cache();
-#elif defined(PROTOBUF_USE_DLLS)
-  // Thread local variables cannot be exposed through DLL interface but we can
-  // wrap them in static functions.
-  static ThreadCache& thread_cache();
-#else
-  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
-  static ThreadCache& thread_cache() { return thread_cache_; }
-#endif
-
-  // SFINAE for skipping addition to delete list for a message type when created
-  // with CreateMessage. This is mainly to skip proto2/proto1 message objects
-  // with cc_enable_arenas=true from being part of the delete list. Also, note,
-  // compiler will optimize out the branch in CreateInternal<T>.
-  template<typename T>
-  static inline bool SkipDeleteList(typename T::DestructorSkippable_*) {
-    return true;
+  void OnArenaAllocation(const std::type_info* allocated_type, size_t n) const;
+  inline void AllocHook(const std::type_info* allocated_type, size_t n) const {
+    if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL)) {
+      OnArenaAllocation(allocated_type, n);
+    }
   }
 
-  // For message objects that don't have the DestructorSkippable_ trait, we
-  // always add to the delete list.
-  template<typename T>
-  static inline bool SkipDeleteList(...) {
-    return google::protobuf::internal::has_trivial_destructor<T>::value;
+  // Allocate and also optionally call on_arena_allocation callback with the
+  // allocated type info when the hooks are in place in ArenaOptions and
+  // the cookie is not null.
+  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
+  void* AllocateInternal(bool skip_explicit_ownership) {
+    const size_t n = internal::AlignUpTo8(sizeof(T));
+    AllocHook(RTTI_TYPE_ID(T), n);
+    // Monitor allocation if needed.
+    if (skip_explicit_ownership) {
+      return impl_.AllocateAligned(n);
+    } else {
+      return impl_.AllocateAlignedAndAddCleanup(
+          n, &internal::arena_destruct_object<T>);
+    }
   }
 
- private:
-  struct InternalIsDestructorSkippableHelper {
-    template<typename U>
-    static char DestructorSkippable(
-        const typename U::DestructorSkippable_*);
-    template<typename U>
-    static double DestructorSkippable(...);
-  };
-
- public:
-  // Helper typetrait that indicates whether the desctructor of type T should be
-  // called when arena is destroyed at compile time. This is only to allow
-  // construction of higher-level templated utilities.
-  // is_destructor_skippable<T>::value is true if the destructor of the message
-  // type T should not be called when arena is destroyed or false otherwise.
-  // This is inside Arena because only Arena has the friend relationships
-  // necessary to see the underlying generated code traits.
-  template<typename T>
-  struct is_destructor_skippable
-      : public google::protobuf::internal::integral_constant<
-            bool,
-            sizeof(InternalIsDestructorSkippableHelper::DestructorSkippable<
-                   const T>(static_cast<const T*>(0))) == sizeof(char) ||
-                google::protobuf::internal::has_trivial_destructor<T>::value> {};
-
- private:
   // CreateMessage<T> requires that T supports arenas, but this private method
   // works whether or not T supports arenas. These are not exposed to user code
   // as it can cause confusing API usages, and end up having double free in
   // user code. These are used only internally from LazyField and Repeated
   // fields, since they are designed to work in all mode combinations.
-  template<typename Msg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static Msg* CreateMaybeMessage(
-      Arena* arena, typename Msg::InternalArenaConstructable_*) {
+  template <typename Msg>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static Msg* CreateMaybeMessage(Arena* arena,
+                                                         google::protobuf::internal::true_type) {
     return CreateMessage<Msg>(arena);
   }
 
-  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static T* CreateMaybeMessage(Arena* arena, ...) {
+  template <typename T>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena,
+                                                       google::protobuf::internal::false_type) {
     return Create<T>(arena);
   }
 
+  template <typename T>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateMaybeMessage(Arena* arena) {
+    return CreateMaybeMessage<T>(arena, is_arena_constructable<T>());
+  }
+
   // Just allocate the required size for the given type assuming the
   // type has a trivial constructor.
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
@@ -651,47 +664,34 @@
     GOOGLE_CHECK_LE(num_elements,
              std::numeric_limits<size_t>::max() / sizeof(T))
         << "Requested size is too large to fit into size_t.";
-    return static_cast<T*>(
-        AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements));
+    const size_t n = internal::AlignUpTo8(sizeof(T) * num_elements);
+    // Monitor allocation if needed.
+    AllocHook(RTTI_TYPE_ID(T), n);
+    return static_cast<T*>(impl_.AllocateAligned(n));
   }
 
 #if LANG_CXX11
   template <typename T, typename... Args> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   T* CreateInternal(bool skip_explicit_ownership, Args&&... args) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(std::forward<Args>(args)...);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
   }
-#endif
+#else
   template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   T* CreateInternal(bool skip_explicit_ownership) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T();
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
+    return new (AllocateInternal<T>(skip_explicit_ownership)) T();
   }
 
   template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   T* CreateInternal(bool skip_explicit_ownership, const Arg& arg) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
+    return new (AllocateInternal<T>(skip_explicit_ownership)) T(arg);
   }
 
-  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  T* CreateInternal(
-      bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
+  template <typename T, typename Arg1, typename Arg2>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateInternal(bool skip_explicit_ownership,
+                                            const Arg1& arg1,
+                                            const Arg2& arg2) {
+    return new (AllocateInternal<T>(skip_explicit_ownership)) T(arg1, arg2);
   }
 
   template <typename T, typename Arg1, typename Arg2, typename Arg3>
@@ -699,12 +699,8 @@
                                             const Arg1& arg1,
                                             const Arg2& arg2,
                                             const Arg3& arg3) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(arg1, arg2, arg3);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
   }
 
   template <typename T, typename Arg1, typename Arg2, typename Arg3,
@@ -714,12 +710,8 @@
                                             const Arg2& arg2,
                                             const Arg3& arg3,
                                             const Arg4& arg4) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(arg1, arg2, arg3, arg4);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
   }
 
   template <typename T, typename Arg1, typename Arg2, typename Arg3,
@@ -730,12 +722,8 @@
                                             const Arg3& arg3,
                                             const Arg4& arg4,
                                             const Arg5& arg5) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(arg1, arg2, arg3, arg4, arg5);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
   }
 
   template <typename T, typename Arg1, typename Arg2, typename Arg3,
@@ -747,12 +735,8 @@
                                             const Arg4& arg4,
                                             const Arg5& arg5,
                                             const Arg6& arg6) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(arg1, arg2, arg3, arg4, arg5, arg6);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
   }
 
   template <typename T, typename Arg1, typename Arg2, typename Arg3,
@@ -765,12 +749,8 @@
                                             const Arg5& arg5,
                                             const Arg6& arg6,
                                             const Arg7& arg7) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
   }
 
   template <typename T, typename Arg1, typename Arg2, typename Arg3,
@@ -785,30 +765,30 @@
                                             const Arg6& arg6,
                                             const Arg7& arg7,
                                             const Arg8& arg8) {
-    T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T)))
+    return new (AllocateInternal<T>(skip_explicit_ownership))
         T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
-    if (!skip_explicit_ownership) {
-      AddListNode(t, &internal::arena_destruct_object<T>);
-    }
-    return t;
+  }
+#endif
+  template <typename T>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal() {
+    return InternalHelper<T>::Construct(
+        AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
+        this);
   }
 
-  template <typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  T* CreateMessageInternal(typename T::InternalArenaConstructable_*) {
-    return CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)), this);
+  template <typename T, typename Arg>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal(const Arg& arg) {
+    return InternalHelper<T>::Construct(
+        AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
+        this, arg);
   }
 
-  template <typename T, typename Arg> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
-                           const Arg& arg) {
-    return CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)), this, arg);
-  }
-
-  template <typename T, typename Arg1, typename Arg2> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  T* CreateMessageInternal(typename T::InternalArenaConstructable_*,
-                           const Arg1& arg1, const Arg2& arg2) {
-    return CreateInternal<T>(SkipDeleteList<T>(static_cast<T*>(0)), this, arg1,
-                             arg2);
+  template <typename T, typename Arg1, typename Arg2>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE T* CreateMessageInternal(const Arg1& arg1,
+                                                   const Arg2& arg2) {
+    return InternalHelper<T>::Construct(
+        AllocateInternal<T>(InternalHelper<T>::is_destructor_skippable::value),
+        this, arg1, arg2);
   }
 
   // CreateInArenaStorage is used to implement map field. Without it,
@@ -818,14 +798,15 @@
   static void CreateInArenaStorage(T* ptr, Arena* arena) {
     CreateInArenaStorageInternal(ptr, arena,
                                  typename is_arena_constructable<T>::type());
-    RegisterDestructorInternal(ptr, arena,
-                               typename is_destructor_skippable<T>::type());
+    RegisterDestructorInternal(
+        ptr, arena,
+        typename InternalHelper<T>::is_destructor_skippable::type());
   }
 
   template <typename T>
   static void CreateInArenaStorageInternal(
       T* ptr, Arena* arena, google::protobuf::internal::true_type) {
-    new (ptr) T(arena);
+    InternalHelper<T>::Construct(ptr, arena);
   }
   template <typename T>
   static void CreateInArenaStorageInternal(
@@ -850,100 +831,56 @@
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   void OwnInternal(T* object, google::protobuf::internal::true_type) {
     if (object != NULL) {
-      AddListNode(object, &internal::arena_delete_object< ::google::protobuf::Message >);
+      impl_.AddCleanup(object,
+                       &internal::arena_delete_object< ::google::protobuf::Message>);
     }
   }
   template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
   void OwnInternal(T* object, google::protobuf::internal::false_type) {
     if (object != NULL) {
-      AddListNode(object, &internal::arena_delete_object<T>);
+      impl_.AddCleanup(object, &internal::arena_delete_object<T>);
     }
   }
 
   // Implementation for GetArena(). Only message objects with
   // InternalArenaConstructable_ tags can be associated with an arena, and such
   // objects must implement a GetArenaNoVirtual() method.
-  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static ::google::protobuf::Arena* GetArenaInternal(
-      const T* value, typename T::InternalArenaConstructable_*) {
-    return value->GetArenaNoVirtual();
+  template <typename T>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static ::google::protobuf::Arena* GetArenaInternal(
+      const T* value, google::protobuf::internal::true_type) {
+    return InternalHelper<T>::GetArena(value);
   }
 
-  template<typename T> GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  static ::google::protobuf::Arena* GetArenaInternal(const T* /* value */, ...) {
+  template <typename T>
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE static ::google::protobuf::Arena* GetArenaInternal(
+      const T* value, google::protobuf::internal::false_type) {
     return NULL;
   }
 
-  // Allocate and also optionally call on_arena_allocation callback with the
-  // allocated type info when the hooks are in place in ArenaOptions and
-  // the cookie is not null.
-  void* AllocateAligned(const std::type_info* allocated, size_t n);
-
-  // Allocate an internal allocation, avoiding optional typed monitoring.
-  GOOGLE_ATTRIBUTE_ALWAYS_INLINE void* AllocateAligned(size_t n) {
-    return AllocateAligned(NULL, n);
+  // For friends of arena.
+  void* AllocateAligned(size_t n) {
+    AllocHook(NULL, n);
+    return impl_.AllocateAligned(internal::AlignUpTo8(n));
   }
 
-  void Init();
+  internal::ArenaImpl impl_;
 
-  // Free all blocks and return the total space used which is the sums of sizes
-  // of the all the allocated blocks.
-  uint64 FreeBlocks();
-
-  // Add object pointer and cleanup function pointer to the list.
-  // TODO(rohananil, cfallin): We could pass in a sub-arena into this method
-  // to avoid polluting blocks of this arena with list nodes. This would help in
-  // mixed mode (where many protobufs have cc_enable_arenas=false), and is an
-  // alternative to a chunked linked-list, but with extra overhead of *next.
-  void AddListNode(void* elem, void (*cleanup)(void*));
-  // Delete or Destruct all objects owned by the arena.
-  void CleanupList();
-  uint64 ResetInternal();
-
-  inline void SetThreadCacheBlock(Block* block) {
-    thread_cache().last_block_used_ = block;
-    thread_cache().last_lifecycle_id_seen = lifecycle_id_;
-  }
-
-  int64 lifecycle_id_;  // Unique for each arena. Changes on Reset().
-
-  google::protobuf::internal::AtomicWord blocks_;       // Head of linked list of all allocated blocks
-  google::protobuf::internal::AtomicWord hint_;         // Fast thread-local block access
-  uint64 space_allocated_;  // Sum of sizes of all allocated blocks.
-
-  // Node contains the ptr of the object to be cleaned up and the associated
-  // cleanup function ptr.
-  struct Node {
-    void* elem;              // Pointer to the object to be cleaned up.
-    void (*cleanup)(void*);  // Function pointer to the destructor or deleter.
-    Node* next;              // Next node in the list.
-  };
-
-  google::protobuf::internal::AtomicWord cleanup_list_;  // Head of a linked list of nodes containing object
-                             // ptrs and cleanup methods.
-
-  bool owns_first_block_;    // Indicates that arena owns the first block
-  mutable Mutex blocks_lock_;
-
-  void AddBlock(Block* b);
-  // Access must be synchronized, either by blocks_lock_ or by being called from
-  // Init()/Reset().
-  void AddBlockInternal(Block* b);
-  void* SlowAlloc(size_t n);
-  Block* FindBlock(void* me);
-  Block* NewBlock(void* me, Block* my_last_block, size_t n,
-                  size_t start_block_size, size_t max_block_size);
-  static void* AllocFromBlock(Block* b, size_t n);
-  template <typename Key, typename T>
-  friend class Map;
+  void* (*on_arena_init_)(Arena* arena);
+  void (*on_arena_allocation_)(const std::type_info* allocated_type,
+                               uint64 alloc_size, void* cookie);
+  void (*on_arena_reset_)(Arena* arena, void* cookie, uint64 space_used);
+  void (*on_arena_destruction_)(Arena* arena, void* cookie, uint64 space_used);
 
   // The arena may save a cookie it receives from the external on_init hook
   // and then use it when calling the on_reset and on_destruction hooks.
   void* hooks_cookie_;
 
-  ArenaOptions options_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena);
+  template <typename Type>
+  friend class ::google::protobuf::internal::GenericTypeHandler;
+  friend class internal::ArenaString;  // For AllocateAligned.
+  friend class internal::LazyField;    // For CreateMaybeMessage.
+  template <typename Key, typename T>
+  friend class Map;
 };
 
 // Defined above for supporting environments without RTTI.
diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h
new file mode 100644
index 0000000..b7f0c7b
--- /dev/null
+++ b/src/google/protobuf/arena_impl.h
@@ -0,0 +1,214 @@
+// 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.
+
+// This file defines an Arena allocator for better allocation performance.
+
+#ifndef GOOGLE_PROTOBUF_ARENA_IMPL_H__
+#define GOOGLE_PROTOBUF_ARENA_IMPL_H__
+
+#include <limits>
+
+#include <google/protobuf/stubs/atomic_sequence_num.h>
+#include <google/protobuf/stubs/atomicops.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/mutex.h>
+#include <google/protobuf/stubs/type_traits.h>
+
+namespace google {
+
+namespace protobuf {
+namespace internal {
+
+inline size_t AlignUpTo8(size_t n) {
+  // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.)
+  return (n + 7) & -8;
+}
+
+// This class provides the core Arena memory allocation library. Different
+// implementations only need to implement the public interface below.
+// Arena is not a template type as that would only be useful if all protos
+// in turn would be templates, which will/cannot happen. However separating
+// the memory allocation part from the cruft of the API users expect we can
+// use #ifdef the select the best implementation based on hardware / OS.
+class LIBPROTOBUF_EXPORT ArenaImpl {
+ public:
+  struct Options {
+    size_t start_block_size;
+    size_t max_block_size;
+    char* initial_block;
+    size_t initial_block_size;
+    void* (*block_alloc)(size_t);
+    void (*block_dealloc)(void*, size_t);
+
+    template <typename O>
+    explicit Options(const O& options)
+      : start_block_size(options.start_block_size),
+        max_block_size(options.max_block_size),
+        initial_block(options.initial_block),
+        initial_block_size(options.initial_block_size),
+        block_alloc(options.block_alloc),
+        block_dealloc(options.block_dealloc) {}
+  };
+
+  template <typename O>
+  explicit ArenaImpl(const O& options) : options_(options) {
+    Init();
+  }
+
+  // Destructor deletes all owned heap allocated objects, and destructs objects
+  // that have non-trivial destructors, except for proto2 message objects whose
+  // destructors can be skipped. Also, frees all blocks except the initial block
+  // if it was passed in.
+  ~ArenaImpl();
+
+  uint64 Reset();
+
+  uint64 SpaceAllocated() const;
+  uint64 SpaceUsed() const;
+
+  void* AllocateAligned(size_t n);
+
+  void* AllocateAlignedAndAddCleanup(size_t n, void (*cleanup)(void*));
+
+  // Add object pointer and cleanup function pointer to the list.
+  void AddCleanup(void* elem, void (*cleanup)(void*));
+
+ private:
+  // Node contains the ptr of the object to be cleaned up and the associated
+  // cleanup function ptr.
+  struct CleanupNode {
+    void* elem;              // Pointer to the object to be cleaned up.
+    void (*cleanup)(void*);  // Function pointer to the destructor or deleter.
+  };
+
+  // Cleanup uses a chunked linked list, to reduce pointer chasing.
+  struct CleanupChunk {
+    static size_t SizeOf(size_t i) {
+      return sizeof(CleanupChunk) + (sizeof(CleanupNode) * (i - 1));
+    }
+    size_t len;            // Number of elements currently present.
+    size_t size;           // Total elements in the list.
+    CleanupChunk* next;    // Next node in the list.
+    CleanupNode nodes[1];  // True length is |size|.
+  };
+
+  // Blocks are variable length malloc-ed objects.  The following structure
+  // describes the common header for all blocks.
+  struct Block {
+    void* owner;            // &ThreadCache of thread that owns this block.
+    Block* next;            // Next block in arena (may have different owner)
+    CleanupChunk* cleanup;  // Head of cleanup list (may point to another block,
+                            // but it must have the same owner).
+    // ((char*) &block) + pos is next available byte. It is always
+    // aligned at a multiple of 8 bytes.
+    size_t pos;
+    size_t size;  // total size of the block.
+    GOOGLE_ATTRIBUTE_ALWAYS_INLINE size_t avail() const { return size - pos; }
+    // data follows
+  };
+
+  struct ThreadCache {
+    // The ThreadCache is considered valid as long as this matches the
+    // lifecycle_id of the arena being used.
+    int64 last_lifecycle_id_seen;
+    Block* last_block_used_;
+  };
+
+  // kHeaderSize is sizeof(Block), aligned up to the nearest multiple of 8 to
+  // protect the invariant that pos is always at a multiple of 8.
+  static const size_t kHeaderSize = (sizeof(Block) + 7) & -8;
+#if LANG_CXX11
+  static_assert(kHeaderSize % 8 == 0, "kHeaderSize must be a multiple of 8.");
+#endif
+  static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
+#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
+  // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
+  // local storage class we implemented.
+  // iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
+  static ThreadCache& thread_cache();
+#elif defined(PROTOBUF_USE_DLLS)
+  // Thread local variables cannot be exposed through DLL interface but we can
+  // wrap them in static functions.
+  static ThreadCache& thread_cache();
+#else
+  static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
+  static ThreadCache& thread_cache() { return thread_cache_; }
+#endif
+
+  void Init();
+
+  // Free all blocks and return the total space used which is the sums of sizes
+  // of the all the allocated blocks.
+  uint64 FreeBlocks(Block* head);
+
+  void AddCleanupInBlock(Block* b, void* elem, void (*cleanup)(void*));
+  Block* ExpandCleanupList(Block* b);
+  // Delete or Destruct all objects owned by the arena.
+  void CleanupList(Block* head);
+  uint64 ResetInternal();
+
+  inline void CacheBlock(Block* block) {
+    thread_cache().last_block_used_ = block;
+    thread_cache().last_lifecycle_id_seen = lifecycle_id_;
+    google::protobuf::internal::Release_Store(&hint_, reinterpret_cast<google::protobuf::internal::AtomicWord>(block));
+  }
+
+  google::protobuf::internal::AtomicWord blocks_;       // Head of linked list of all allocated blocks
+  google::protobuf::internal::AtomicWord hint_;         // Fast thread-local block access
+  uint64 space_allocated_;  // Sum of sizes of all allocated blocks.
+
+  bool owns_first_block_;  // Indicates that arena owns the first block
+  mutable Mutex blocks_lock_;
+
+  void AddBlock(Block* b);
+  // Access must be synchronized, either by blocks_lock_ or by being called from
+  // Init()/Reset().
+  void AddBlockInternal(Block* b);
+  // Returns a block owned by this thread.
+  Block* GetBlock(size_t n);
+  Block* GetBlockSlow(void* me, Block* my_full_block, size_t n);
+  Block* FindBlock(void* me);
+  Block* NewBlock(void* me, Block* my_last_block, size_t min_bytes,
+                  size_t start_block_size, size_t max_block_size);
+  static void* AllocFromBlock(Block* b, size_t n);
+
+  int64 lifecycle_id_;  // Unique for each arena. Changes on Reset().
+
+  Options options_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArenaImpl);
+};
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_ARENA_IMPL_H__
diff --git a/src/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
index e5afe42..c330b90 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -32,16 +32,21 @@
 
 #include <google/protobuf/arenastring.h>
 
-#include <string>
+#include <algorithm>
+#include <cstdlib>
 #include <memory>
 #ifndef _SHARED_PTR_H
 #include <google/protobuf/stubs/shared_ptr.h>
 #endif
-#include <cstdlib>
+#include <string>
+#include <vector>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <gtest/gtest.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
 
 namespace google {
 using google::protobuf::internal::ArenaString;
@@ -87,7 +92,8 @@
   EXPECT_EQ(string("default"), field.Get());
   field.Set(&default_value, WrapString("Test short"), &arena);
   EXPECT_EQ(string("Test short"), field.Get());
-  field.Set(&default_value, WrapString("Test long long long long value"), &arena);
+  field.Set(&default_value, WrapString("Test long long long long value"),
+            &arena);
   EXPECT_EQ(string("Test long long long long value"), field.Get());
   field.Set(&default_value, string(""), &arena);
   field.Destroy(&default_value, &arena);
@@ -104,5 +110,6 @@
   field2.Destroy(&default_value, &arena);
 }
 
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index b917d37..dd6a59d 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -50,6 +50,7 @@
 class FileDescriptor;
 
 namespace compiler {
+class AccessInfoMap;
 class Version;
 
 // Defined in this file.
@@ -112,7 +113,8 @@
 // runs.
 class LIBPROTOC_EXPORT GeneratorContext {
  public:
-  inline GeneratorContext() {}
+  inline GeneratorContext() {
+  }
   virtual ~GeneratorContext();
 
   // Opens the given file, truncating it if it exists, and returns a
@@ -148,6 +150,7 @@
   // this GeneratorContext.
   virtual void GetCompilerVersion(Version* version) const;
 
+
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
 };
@@ -162,8 +165,8 @@
 //   "foo=bar,baz,qux=corge"
 // parses to the pairs:
 //   ("foo", "bar"), ("baz", ""), ("qux", "corge")
-extern void ParseGeneratorParameter(const string&,
-            std::vector<std::pair<string, string> >*);
+LIBPROTOC_EXPORT void ParseGeneratorParameter(
+    const string&, std::vector<std::pair<string, string> >*);
 
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index df03907..5f86404 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -33,6 +33,8 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/command_line_interface.h>
+
+
 #include <google/protobuf/stubs/platform_macros.h>
 
 #include <stdio.h>
@@ -45,10 +47,7 @@
 #endif
 #include <sys/stat.h>
 #include <fcntl.h>
-#ifdef _MSC_VER
-#include <io.h>
-#include <direct.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <errno.h>
@@ -68,18 +67,27 @@
 #endif
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/compiler/importer.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/compiler/plugin.pb.h>
 #include <google/protobuf/compiler/subprocess.h>
 #include <google/protobuf/compiler/zip_writer.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
@@ -91,22 +99,6 @@
 namespace protobuf {
 namespace compiler {
 
-#if defined(_WIN32)
-#define mkdir(name, mode) mkdir(name)
-#ifndef W_OK
-#define W_OK 02  // not defined by MSVC for whatever reason
-#endif
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
-#endif
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#endif
-
 #ifndef O_BINARY
 #ifdef _O_BINARY
 #define O_BINARY _O_BINARY
@@ -116,10 +108,15 @@
 #endif
 
 namespace {
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static const char* kPathSeparator = ";";
-#else
-static const char* kPathSeparator = ":";
+#if defined(_MSC_VER)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::mkdir;
+using google::protobuf::internal::win32::open;
+using google::protobuf::internal::win32::setmode;
+using google::protobuf::internal::win32::write;
 #endif
 
 static const char* kDefaultDirectDependenciesViolationMsg =
@@ -141,9 +138,9 @@
 
 void SetFdToTextMode(int fd) {
 #ifdef _WIN32
-  if (_setmode(fd, _O_TEXT) == -1) {
+  if (setmode(fd, _O_TEXT) == -1) {
     // This should never happen, I think.
-    GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno);
+    GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_TEXT): " << strerror(errno);
   }
 #endif
   // (Text and binary are the same on non-Windows platforms.)
@@ -151,9 +148,9 @@
 
 void SetFdToBinaryMode(int fd) {
 #ifdef _WIN32
-  if (_setmode(fd, _O_BINARY) == -1) {
+  if (setmode(fd, _O_BINARY) == -1) {
     // This should never happen, I think.
-    GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno);
+    GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_BINARY): " << strerror(errno);
   }
 #endif
   // (Text and binary are the same on non-Windows platforms.)
@@ -278,11 +275,14 @@
   // strip the "--" and "_out/_opt" and add the plugin prefix.
   return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6);
 }
+
 }  // namespace
 
 // A MultiFileErrorCollector that prints errors to stderr.
-class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector,
-                                           public io::ErrorCollector {
+class CommandLineInterface::ErrorPrinter
+    : public MultiFileErrorCollector,
+      public io::ErrorCollector,
+      public DescriptorPool::ErrorCollector {
  public:
   ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL)
     : format_(format), tree_(tree), found_errors_(false) {}
@@ -309,6 +309,25 @@
     AddErrorOrWarning("input", line, column, message, "warning", std::clog);
   }
 
+  // implements DescriptorPool::ErrorCollector-------------------------
+  void AddError(
+      const string& filename,
+      const string& element_name,
+      const Message* descriptor,
+      ErrorLocation location,
+      const string& message) {
+    AddErrorOrWarning(filename, -1, -1, message, "error", std::cerr);
+  }
+
+  void AddWarning(
+      const string& filename,
+      const string& element_name,
+      const Message* descriptor,
+      ErrorLocation location,
+      const string& message) {
+    AddErrorOrWarning(filename, -1, -1, message, "warning", std::clog);
+  }
+
   bool FoundErrors() const { return found_errors_; }
 
  private:
@@ -410,6 +429,13 @@
   virtual int64 ByteCount() const           { return inner_->ByteCount();      }
 
  private:
+  // Checks to see if "filename_.meta" exists in directory_; if so, fixes the
+  // offsets in that GeneratedCodeInfo record to reflect bytes inserted in
+  // filename_ at original offset insertion_offset with length insertion_length.
+  // We assume that insertions will not occur within any given annotated span
+  // of text.
+  void UpdateMetadata(size_t insertion_offset, size_t insertion_length);
+
   // Where to insert the string when it's done.
   GeneratorContextImpl* directory_;
   string filename_;
@@ -430,8 +456,7 @@
 CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl(
     const std::vector<const FileDescriptor*>& parsed_files)
     : parsed_files_(parsed_files),
-      had_error_(false) {
-}
+      had_error_(false) {}
 
 CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() {
   STLDeleteValues(&files_);
@@ -607,6 +632,44 @@
       inner_(new io::StringOutputStream(&data_)) {
 }
 
+void CommandLineInterface::MemoryOutputStream::UpdateMetadata(
+    size_t insertion_offset, size_t insertion_length) {
+  std::map<string, string*>::iterator meta_file =
+      directory_->files_.find(filename_ + ".meta");
+  if (meta_file == directory_->files_.end() || !meta_file->second) {
+    // No metadata was recorded for this file.
+    return;
+  }
+  string* encoded_data = meta_file->second;
+  GeneratedCodeInfo metadata;
+  bool is_text_format = false;
+  if (!metadata.ParseFromString(*encoded_data)) {
+    if (!TextFormat::ParseFromString(*encoded_data, &metadata)) {
+      // The metadata is invalid.
+      std::cerr << filename_
+                << ".meta: Could not parse metadata as wire or text format."
+                << std::endl;
+      return;
+    }
+    // Generators that use the public plugin interface emit text-format
+    // metadata (because in the public plugin protocol, file content must be
+    // UTF8-encoded strings).
+    is_text_format = true;
+  }
+  for (int i = 0; i < metadata.annotation_size(); ++i) {
+    GeneratedCodeInfo::Annotation* annotation = metadata.mutable_annotation(i);
+    if (annotation->begin() >= insertion_offset) {
+      annotation->set_begin(annotation->begin() + insertion_length);
+      annotation->set_end(annotation->end() + insertion_length);
+    }
+  }
+  if (is_text_format) {
+    TextFormat::PrintToString(metadata, encoded_data);
+  } else {
+    metadata.SerializeToString(encoded_data);
+  }
+}
+
 CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() {
   // Make sure all data has been written.
   inner_.reset();
@@ -684,6 +747,7 @@
     if (indent_.empty()) {
       // No indent.  This makes things easier.
       target->insert(pos, data_);
+      UpdateMetadata(pos, data_.size());
     } else {
       // Calculate how much space we need.
       int indent_size = 0;
@@ -693,6 +757,7 @@
 
       // Make a hole for it.
       target->insert(pos, data_.size() + indent_size, '\0');
+      UpdateMetadata(pos, data_.size() + indent_size);
 
       // Now copy in the data.
       string::size_type data_pos = 0;
@@ -720,6 +785,12 @@
 
 // ===================================================================
 
+#if defined(_WIN32) && !defined(__CYGWIN__)
+const char* const CommandLineInterface::kPathSeparator = ";";
+#else
+const char* const CommandLineInterface::kPathSeparator = ":";
+#endif
+
 CommandLineInterface::CommandLineInterface()
     : mode_(MODE_COMPILE),
       print_mode_(PRINT_NONE),
@@ -729,9 +800,7 @@
           kDefaultDirectDependenciesViolationMsg),
       imports_in_descriptor_set_(false),
       source_info_in_descriptor_set_(false),
-      disallow_services_(false),
-      inputs_are_proto_path_relative_(false) {
-}
+      disallow_services_(false) {}
 CommandLineInterface::~CommandLineInterface() {}
 
 void CommandLineInterface::RegisterGenerator(const string& flag_name,
@@ -772,61 +841,39 @@
       break;
   }
 
-  AddDefaultProtoPaths(&proto_path_);
-
-  // Set up the source tree.
-  DiskSourceTree source_tree;
-  for (int i = 0; i < proto_path_.size(); i++) {
-    source_tree.MapPath(proto_path_[i].first, proto_path_[i].second);
-  }
-
-  // Map input files to virtual paths if necessary.
-  if (!inputs_are_proto_path_relative_) {
-    if (!MakeInputsBeProtoPathRelative(&source_tree)) {
-      return 1;
-    }
-  }
-
-  // Allocate the Importer.
-  ErrorPrinter error_collector(error_format_, &source_tree);
-  Importer importer(&source_tree, &error_collector);
-
   std::vector<const FileDescriptor*> parsed_files;
-
-  // Parse each file.
-  for (int i = 0; i < input_files_.size(); i++) {
-    // Import the file.
-    importer.AddUnusedImportTrackFile(input_files_[i]);
-    const FileDescriptor* parsed_file = importer.Import(input_files_[i]);
-    importer.ClearUnusedImportTrackFiles();
-    if (parsed_file == NULL) return 1;
-    parsed_files.push_back(parsed_file);
-
-    // Enforce --disallow_services.
-    if (disallow_services_ && parsed_file->service_count() > 0) {
-      std::cerr << parsed_file->name() << ": This file contains services, but "
-              "--disallow_services was used." << std::endl;
+  // null unless descriptor_set_in_names_.empty()
+  google::protobuf::scoped_ptr<DiskSourceTree> disk_source_tree;
+  google::protobuf::scoped_ptr<ErrorPrinter> error_collector;
+  google::protobuf::scoped_ptr<DescriptorPool> descriptor_pool;
+  google::protobuf::scoped_ptr<DescriptorDatabase> descriptor_database;
+  if (descriptor_set_in_names_.empty()) {
+    disk_source_tree.reset(new DiskSourceTree());
+    if (!InitializeDiskSourceTree(disk_source_tree.get())) {
       return 1;
     }
+    error_collector.reset(
+        new ErrorPrinter(error_format_, disk_source_tree.get()));
 
-    // Enforce --direct_dependencies
-    if (direct_dependencies_explicitly_set_) {
-      bool indirect_imports = false;
-      for (int i = 0; i < parsed_file->dependency_count(); i++) {
-        if (direct_dependencies_.find(parsed_file->dependency(i)->name()) ==
-            direct_dependencies_.end()) {
-          indirect_imports = true;
-          std::cerr << parsed_file->name() << ": "
-                    << StringReplace(direct_dependencies_violation_msg_, "%s",
-                                     parsed_file->dependency(i)->name(),
-                                     true /* replace_all */)
-                    << std::endl;
-        }
-      }
-      if (indirect_imports) {
-        return 1;
-      }
+    SourceTreeDescriptorDatabase* database =
+        new SourceTreeDescriptorDatabase(disk_source_tree.get());
+    database->RecordErrorsTo(error_collector.get());
+    descriptor_database.reset(database);
+    descriptor_pool.reset(new DescriptorPool(
+        descriptor_database.get(), database->GetValidationErrorCollector()));
+  } else {
+    error_collector.reset(new ErrorPrinter(error_format_));
+
+    SimpleDescriptorDatabase* database = new SimpleDescriptorDatabase();
+    descriptor_database.reset(database);
+    if (!PopulateSimpleDescriptorDatabase(database)) {
+      return 1;
     }
+    descriptor_pool.reset(new DescriptorPool(database, error_collector.get()));
+  }
+  descriptor_pool->EnforceWeakDependencies(true);
+  if (!ParseInputFiles(descriptor_pool.get(), &parsed_files)) {
+    return 1;
   }
 
   // We construct a separate GeneratorContext for each output location.  Note
@@ -879,15 +926,16 @@
   }
 
   if (!dependency_out_name_.empty()) {
+    GOOGLE_DCHECK(disk_source_tree.get());
     if (!GenerateDependencyManifestFile(parsed_files, output_directories,
-                                        &source_tree)) {
+                                        disk_source_tree.get())) {
       return 1;
     }
   }
 
   STLDeleteValues(&output_directories);
 
-  if (!descriptor_set_name_.empty()) {
+  if (!descriptor_set_out_name_.empty()) {
     if (!WriteDescriptorSet(parsed_files)) {
       return 1;
     }
@@ -906,13 +954,13 @@
         return 1;
       }
     } else {
-      if (!EncodeOrDecode(importer.pool())) {
+      if (!EncodeOrDecode(descriptor_pool.get())) {
         return 1;
       }
     }
   }
 
-  if (error_collector.FoundErrors()) {
+  if (error_collector->FoundErrors()) {
     return 1;
   }
 
@@ -928,7 +976,7 @@
         break;
       case PRINT_NONE:
         GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of "
-                     "flag parsing in the CommonadLineInterface.";
+                     "flag parsing in the CommandLineInterface.";
         return 1;
 
       // Do not add a default case.
@@ -938,6 +986,112 @@
   return 0;
 }
 
+bool CommandLineInterface::InitializeDiskSourceTree(
+    DiskSourceTree* source_tree) {
+  AddDefaultProtoPaths(&proto_path_);
+
+  // Set up the source tree.
+  for (int i = 0; i < proto_path_.size(); i++) {
+    source_tree->MapPath(proto_path_[i].first, proto_path_[i].second);
+  }
+
+  // Map input files to virtual paths if possible.
+  if (!MakeInputsBeProtoPathRelative(source_tree)) {
+    return false;
+  }
+  return true;
+}
+
+bool CommandLineInterface::PopulateSimpleDescriptorDatabase(
+    SimpleDescriptorDatabase* database) {
+  for (int i = 0; i < descriptor_set_in_names_.size(); i++) {
+    int fd;
+    do {
+      fd = open(descriptor_set_in_names_[i].c_str(), O_RDONLY | O_BINARY);
+    } while (fd < 0 && errno == EINTR);
+    if (fd < 0) {
+      std::cerr << descriptor_set_in_names_[i] << ": "
+                << strerror(ENOENT) << std::endl;
+      return false;
+    }
+
+    FileDescriptorSet file_descriptor_set;
+    bool parsed = file_descriptor_set.ParseFromFileDescriptor(fd);
+    if (close(fd) != 0) {
+      std::cerr << descriptor_set_in_names_[i] << ": close: "
+                << strerror(errno);
+      return false;
+    }
+
+    if (!parsed) {
+      std::cerr << descriptor_set_in_names_[i] << ": Unable to parse."
+                << std::endl;
+      return false;
+    }
+
+    for (int j = 0; j < file_descriptor_set.file_size(); j++) {
+      FileDescriptorProto previously_added_file_descriptor_proto;
+      if (database->FindFileByName(file_descriptor_set.file(j).name(),
+                                   &previously_added_file_descriptor_proto)) {
+        // already present - skip
+        continue;
+      }
+      if (!database->Add(file_descriptor_set.file(j))) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool CommandLineInterface::ParseInputFiles(
+    DescriptorPool* descriptor_pool,
+    std::vector<const FileDescriptor*>* parsed_files) {
+
+  // Parse each file.
+  for (int i = 0; i < input_files_.size(); i++) {
+    // Import the file.
+    descriptor_pool->AddUnusedImportTrackFile(input_files_[i]);
+    const FileDescriptor* parsed_file =
+        descriptor_pool->FindFileByName(input_files_[i]);
+    descriptor_pool->ClearUnusedImportTrackFiles();
+    if (parsed_file == NULL) {
+      if (!descriptor_set_in_names_.empty()) {
+        std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+      }
+      return false;
+    }
+    parsed_files->push_back(parsed_file);
+
+    // Enforce --disallow_services.
+    if (disallow_services_ && parsed_file->service_count() > 0) {
+      std::cerr << parsed_file->name() << ": This file contains services, but "
+              "--disallow_services was used." << std::endl;
+      return false;
+    }
+
+    // Enforce --direct_dependencies
+    if (direct_dependencies_explicitly_set_) {
+      bool indirect_imports = false;
+      for (int i = 0; i < parsed_file->dependency_count(); i++) {
+        if (direct_dependencies_.find(parsed_file->dependency(i)->name()) ==
+            direct_dependencies_.end()) {
+          indirect_imports = true;
+          std::cerr << parsed_file->name() << ": "
+                    << StringReplace(direct_dependencies_violation_msg_, "%s",
+                                     parsed_file->dependency(i)->name(),
+                                     true /* replace_all */)
+                    << std::endl;
+        }
+      }
+      if (indirect_imports) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
 void CommandLineInterface::Clear() {
   // Clear all members that are set by Run().  Note that we must not clear
   // members which are set by other methods before Run() is called.
@@ -948,7 +1102,8 @@
   direct_dependencies_violation_msg_ = kDefaultDirectDependenciesViolationMsg;
   output_directives_.clear();
   codec_type_.clear();
-  descriptor_set_name_.clear();
+  descriptor_set_in_names_.clear();
+  descriptor_set_out_name_.clear();
   dependency_out_name_.clear();
 
   mode_ = MODE_COMPILE;
@@ -962,6 +1117,17 @@
 bool CommandLineInterface::MakeInputsBeProtoPathRelative(
     DiskSourceTree* source_tree) {
   for (int i = 0; i < input_files_.size(); i++) {
+    // If the input file path is not a physical file path, it must be a virtual
+    // path.
+    if (access(input_files_[i].c_str(), F_OK) < 0) {
+      string disk_file;
+      if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) {
+        return true;
+      } else {
+        std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+        return false;
+      }
+    }
     string virtual_file, shadowing_disk_file;
     switch (source_tree->DiskFileToVirtualFile(
         input_files_[i], &virtual_file, &shadowing_disk_file)) {
@@ -979,12 +1145,14 @@
       case DiskSourceTree::CANNOT_OPEN:
         std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl;
         return false;
-      case DiskSourceTree::NO_MAPPING:
-        // First check if the file exists at all.
-        if (access(input_files_[i].c_str(), F_OK) < 0) {
-          // File does not even exist.
-          std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl;
+      case DiskSourceTree::NO_MAPPING: {
+        // Try to interpret the path as a virtual path.
+        string disk_file;
+        if (source_tree->VirtualFileToDiskFile(input_files_[i], &disk_file)) {
+          return true;
         } else {
+          // The input file path can't be mapped to any --proto_path and it also
+          // can't be interpreted as a virtual path.
           std::cerr
               << input_files_[i]
               << ": File does not reside within any path "
@@ -993,9 +1161,11 @@
                  "proto_path must be an exact prefix of the .proto file "
                  "names -- protoc is too dumb to figure out when two paths "
                  "(e.g. absolute and relative) are equivalent (it's harder "
-                 "than you think)." << std::endl;
+                 "than you think)."
+              << std::endl;
+          return false;
         }
-        return false;
+      }
     }
   }
 
@@ -1091,7 +1261,7 @@
     return PARSE_ARGUMENT_FAIL;
   }
   if (mode_ == MODE_COMPILE && output_directives_.empty() &&
-      descriptor_set_name_.empty()) {
+      descriptor_set_out_name_.empty()) {
     std::cerr << "Missing output directives." << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
@@ -1106,11 +1276,11 @@
         << std::endl;
     return PARSE_ARGUMENT_FAIL;
   }
-  if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) {
+  if (imports_in_descriptor_set_ && descriptor_set_out_name_.empty()) {
     std::cerr << "--include_imports only makes sense when combined with "
                  "--descriptor_set_out." << std::endl;
   }
-  if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) {
+  if (source_info_in_descriptor_set_ && descriptor_set_out_name_.empty()) {
     std::cerr << "--include_source_info only makes sense when combined with "
                  "--descriptor_set_out." << std::endl;
   }
@@ -1197,11 +1367,20 @@
     input_files_.push_back(value);
 
   } else if (name == "-I" || name == "--proto_path") {
+    if (!descriptor_set_in_names_.empty()) {
+      std::cerr << "Only one of " << name
+                << " and --descriptor_set_in can be specified."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
     // Java's -classpath (and some other languages) delimits path components
     // with colons.  Let's accept that syntax too just to make things more
     // intuitive.
     std::vector<string> parts = Split(
-        value, kPathSeparator, true);
+        value,
+        CommandLineInterface::kPathSeparator,
+        true);
 
     for (int i = 0; i < parts.size(); i++) {
       string virtual_path;
@@ -1259,8 +1438,38 @@
   } else if (name == "--direct_dependencies_violation_msg") {
     direct_dependencies_violation_msg_ = value;
 
+  } else if (name == "--descriptor_set_in") {
+    if (!descriptor_set_in_names_.empty()) {
+      std::cerr << name << " may only be passed once. To specify multiple "
+                           "descriptor sets, pass them all as a single "
+                           "parameter separated by '"
+                << CommandLineInterface::kPathSeparator << "'."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (value.empty()) {
+      std::cerr << name << " requires a non-empty value." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (!proto_path_.empty()) {
+      std::cerr << "Only one of " << name
+                << " and --proto_path can be specified."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    if (!dependency_out_name_.empty()) {
+      std::cerr << name << " cannot be used with --dependency_out."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+
+    descriptor_set_in_names_ = Split(
+      value,
+      CommandLineInterface::kPathSeparator,
+      true);
+
   } else if (name == "-o" || name == "--descriptor_set_out") {
-    if (!descriptor_set_name_.empty()) {
+    if (!descriptor_set_out_name_.empty()) {
       std::cerr << name << " may only be passed once." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
@@ -1274,7 +1483,7 @@
              "same time." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    descriptor_set_name_ = value;
+    descriptor_set_out_name_ = value;
 
   } else if (name == "--dependency_out") {
     if (!dependency_out_name_.empty()) {
@@ -1285,6 +1494,11 @@
       std::cerr << name << " requires a non-empty value." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
+    if (!descriptor_set_in_names_.empty()) {
+      std::cerr << name << " cannot be used with --descriptor_set_in."
+                << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
     dependency_out_name_ = value;
 
   } else if (name == "--include_imports") {
@@ -1324,7 +1538,7 @@
                 << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
+    if (!output_directives_.empty() || !descriptor_set_out_name_.empty()) {
       std::cerr << "Cannot use " << name
                 << " and generate code or descriptors at the same time."
                 << std::endl;
@@ -1390,7 +1604,7 @@
                 << "other info at the same time." << std::endl;
       return PARSE_ARGUMENT_FAIL;
     }
-    if (!output_directives_.empty() || !descriptor_set_name_.empty()) {
+    if (!output_directives_.empty() || !descriptor_set_out_name_.empty()) {
       std::cerr << "Cannot use " << name
                 << " and generate code or descriptors at the same time."
                 << std::endl;
@@ -1482,6 +1696,14 @@
 "                              pairs in text format to standard output.  No\n"
 "                              PROTO_FILES should be given when using this\n"
 "                              flag.\n"
+"  --descriptor_set_in=FILES   Specifies a delimited list of FILES\n"
+"                              each containing a FileDescriptorSet (a\n"
+"                              protocol buffer defined in descriptor.proto).\n"
+"                              The FileDescriptor for each of the PROTO_FILES\n"
+"                              provided will be loaded from these\n"
+"                              FileDescriptorSets. If a FileDescriptor\n"
+"                              appears multiple times, the first occurrence\n"
+"                              will be used.\n"
 "  -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,\n"
 "    --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n"
 "                              the input files to FILE.\n"
@@ -1661,6 +1883,7 @@
     request.set_parameter(parameter);
   }
 
+
   std::set<const FileDescriptor*> already_seen;
   for (int i = 0; i < parsed_files.size(); i++) {
     request.add_file_to_generate(parsed_files[i]->name());
@@ -1829,24 +2052,24 @@
 
   int fd;
   do {
-    fd = open(descriptor_set_name_.c_str(),
+    fd = open(descriptor_set_out_name_.c_str(),
               O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666);
   } while (fd < 0 && errno == EINTR);
 
   if (fd < 0) {
-    perror(descriptor_set_name_.c_str());
+    perror(descriptor_set_out_name_.c_str());
     return false;
   }
 
   io::FileOutputStream out(fd);
   if (!file_set.SerializeToZeroCopyStream(&out)) {
-    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+    std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
               << std::endl;
     out.Close();
     return false;
   }
   if (!out.Close()) {
-    std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno())
+    std::cerr << descriptor_set_out_name_ << ": " << strerror(out.GetErrno())
               << std::endl;
     return false;
   }
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 997c174..e659657 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -52,17 +52,16 @@
 class Descriptor;            // descriptor.h
 class DescriptorPool;        // descriptor.h
 class FileDescriptor;        // descriptor.h
+class FileDescriptorSet;     // descriptor.h
 class FileDescriptorProto;   // descriptor.pb.h
 template<typename T> class RepeatedPtrField;  // repeated_field.h
+class SimpleDescriptorDatabase;               // descriptor_database.h
 
-}  // namespace protobuf
-
-namespace protobuf {
 namespace compiler {
 
-class CodeGenerator;        // code_generator.h
-class GeneratorContext;      // code_generator.h
-class DiskSourceTree;       // importer.h
+class CodeGenerator;     // code_generator.h
+class GeneratorContext;  // code_generator.h
+class DiskSourceTree;    // importer.h
 
 // This class implements the command-line interface to the protocol compiler.
 // It is designed to make it very easy to create a custom protocol compiler
@@ -91,9 +90,21 @@
 // The compiler is invoked with syntax like:
 //   protoc --cpp_out=outdir --foo_out=outdir --proto_path=src src/foo.proto
 //
+// The .proto file to compile can be specified on the command line using either
+// its physical file path, or a virtual path relative to a diretory specified
+// in --proto_path. For example, for src/foo.proto, the following two protoc
+// invocations work the same way:
+//   1. protoc --proto_path=src src/foo.proto (physical file path)
+//   2. protoc --proto_path=src foo.proto (virtual path relative to src)
+//
+// If a file path can be interpreted both as a physical file path and as a
+// relative virtual path, the physical file path takes precendence.
+//
 // For a full description of the command-line syntax, invoke it with --help.
 class LIBPROTOC_EXPORT CommandLineInterface {
  public:
+  static const char* const kPathSeparator;
+
   CommandLineInterface();
   ~CommandLineInterface();
 
@@ -175,17 +186,11 @@
   // it calls strerror().  I'm not sure why you'd want to do this anyway.
   int Run(int argc, const char* const argv[]);
 
-  // Call SetInputsAreCwdRelative(true) if the input files given on the command
-  // line should be interpreted relative to the proto import path specified
-  // using --proto_path or -I flags.  Otherwise, input file names will be
-  // interpreted relative to the current working directory (or as absolute
-  // paths if they start with '/'), though they must still reside inside
-  // a directory given by --proto_path or the compiler will fail.  The latter
-  // mode is generally more intuitive and easier to use, especially e.g. when
-  // defining implicit rules in Makefiles.
-  void SetInputsAreProtoPathRelative(bool enable) {
-    inputs_are_proto_path_relative_ = enable;
-  }
+  // DEPRECATED. Calling this method has no effect. Protocol compiler now
+  // always try to find the .proto file relative to the current directory
+  // first and if the file is not found, it will then treat the input path
+  // as a virutal path.
+  void SetInputsAreProtoPathRelative(bool /* enable */) {}
 
   // Provides some text which will be printed when the --version flag is
   // used.  The version of libprotoc will also be printed on the next line
@@ -243,6 +248,16 @@
   // Print the --help text to stderr.
   void PrintHelpText();
 
+  // Loads proto_path_ into the provided source_tree.
+  bool InitializeDiskSourceTree(DiskSourceTree* source_tree);
+
+  // Loads descriptor_set_in into the provided database
+  bool PopulateSimpleDescriptorDatabase(SimpleDescriptorDatabase* database);
+
+  // Parses input_files_ into parsed_files
+  bool ParseInputFiles(DescriptorPool* descriptor_pool,
+                       std::vector<const FileDescriptor*>* parsed_files);
+
   // Generate the given output file from the given input.
   struct OutputDirective;  // see below
   bool GenerateOutput(const std::vector<const FileDescriptor*>& parsed_files,
@@ -383,9 +398,13 @@
   // decoding.  (Empty string indicates --decode_raw.)
   string codec_type_;
 
+  // If --descriptor_set_in was given, these are filenames containing
+  // parsed FileDescriptorSets to be used for loading protos.  Otherwise, empty.
+  std::vector<string> descriptor_set_in_names_;
+
   // If --descriptor_set_out was given, this is the filename to which the
   // FileDescriptorSet should be written.  Otherwise, empty.
-  string descriptor_set_name_;
+  string descriptor_set_out_name_;
 
   // If --dependency_out was given, this is the path to the file where the
   // dependency file will be written. Otherwise, empty.
@@ -408,9 +427,6 @@
   // Was the --disallow_services flag used?
   bool disallow_services_;
 
-  // See SetInputsAreProtoPathRelative().
-  bool inputs_are_proto_path_relative_;
-
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
 };
 
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 366e623..73d3e4c 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -35,9 +35,7 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <memory>
@@ -65,27 +63,27 @@
 #include <gtest/gtest.h>
 
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/io_win32.h>
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 
+#if defined(_MSC_VER)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::dup;
+using google::protobuf::internal::win32::dup2;
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::open;
+using google::protobuf::internal::win32::write;
+#endif
+
 // Disable the whole test when we use tcmalloc for "draconian" heap checks, in
 // which case tcmalloc will print warnings that fail the plugin tests.
 #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
 
-#if defined(_WIN32)
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
-#endif
-#endif
-
 namespace {
 
 bool FileExists(const string& path) {
@@ -129,10 +127,6 @@
   // google3.
 #endif  // !PROTOBUF_OPENSOURCE
 
-  void SetInputsAreProtoPathRelative(bool enable) {
-    cli_.SetInputsAreProtoPathRelative(enable);
-  }
-
   // -----------------------------------------------------------------
   // Methods to check the test results (called after Run()).
 
@@ -192,12 +186,17 @@
                                      const string& insertions,
                                      const string& proto_name,
                                      const string& message_name);
+  void CheckGeneratedAnnotations(const string& name, const string& file);
 
   void ExpectNullCodeGeneratorCalled(const string& parameter);
 
+
   void ReadDescriptorSet(const string& filename,
                          FileDescriptorSet* descriptor_set);
 
+  void WriteDescriptorSet(const string& filename,
+                          const FileDescriptorSet* descriptor_set);
+
   void ExpectFileContent(const string& filename,
                          const string& content);
 
@@ -251,11 +250,6 @@
 // ===================================================================
 
 void CommandLineInterfaceTest::SetUp() {
-  // Most of these tests were written before this option was added, so we
-  // run with the option on (which used to be the only way) except in certain
-  // tests where we turn it off.
-  cli_.SetInputsAreProtoPathRelative(true);
-
   temp_directory_ = TestTempDir() + "/proto2_cli_test_temp";
 
   // If the temp directory already exists, it must be left over from a
@@ -281,6 +275,7 @@
   mock_generators_to_delete_.push_back(generator);
   cli_.RegisterGenerator("--null_out", generator, "Null output.");
 
+
   disallow_plugins_ = false;
 }
 
@@ -471,12 +466,18 @@
       proto_name, temp_directory_);
 }
 
+void CommandLineInterfaceTest::CheckGeneratedAnnotations(const string& name,
+                                                         const string& file) {
+  MockCodeGenerator::CheckGeneratedAnnotations(name, file, temp_directory_);
+}
+
 void CommandLineInterfaceTest::ExpectNullCodeGeneratorCalled(
     const string& parameter) {
   EXPECT_TRUE(null_generator_->called_);
   EXPECT_EQ(parameter, null_generator_->parameter_);
 }
 
+
 void CommandLineInterfaceTest::ReadDescriptorSet(
     const string& filename, FileDescriptorSet* descriptor_set) {
   string path = temp_directory_ + "/" + filename;
@@ -488,6 +489,13 @@
   }
 }
 
+void CommandLineInterfaceTest::WriteDescriptorSet(
+    const string& filename, const FileDescriptorSet* descriptor_set) {
+  string binary_proto;
+  GOOGLE_CHECK(descriptor_set->SerializeToString(&binary_proto));
+  CreateTempFile(filename, binary_proto);
+}
+
 void CommandLineInterfaceTest::ExpectCapturedStdout(
     const string& expected_text) {
   EXPECT_EQ(expected_text, captured_stdout_);
@@ -496,7 +504,8 @@
 void CommandLineInterfaceTest::ExpectCapturedStdoutSubstringWithZeroReturnCode(
     const string& expected_substring) {
   EXPECT_EQ(0, return_code_);
-  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, captured_stdout_);
+  EXPECT_PRED_FORMAT2(
+      testing::IsSubstring, expected_substring, captured_stdout_);
 }
 
 void CommandLineInterfaceTest::ExpectFileContent(
@@ -525,6 +534,22 @@
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, BasicOutput_DescriptorSetIn) {
+  // Test that the common case works.
+  FileDescriptorSet file_descriptor_set;
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, BasicPlugin) {
   // Test that basic plugins work.
 
@@ -539,6 +564,23 @@
   ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, BasicPlugin_DescriptorSetIn) {
+  // Test that basic plugins work.
+
+  FileDescriptorSet file_descriptor_set;
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin) {
   // Invoke a generator and a plugin at the same time.
 
@@ -554,6 +596,24 @@
   ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, GeneratorAndPlugin_DescriptorSetIn) {
+  // Invoke a generator and a plugin at the same time.
+
+  FileDescriptorSet file_descriptor_set;
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "foo.proto", "Foo");
+  ExpectGenerated("test_plugin", "", "foo.proto", "Foo");
+}
+
 TEST_F(CommandLineInterfaceTest, MultipleInputs) {
   // Test parsing multiple input files.
 
@@ -578,6 +638,34 @@
                                     "bar.proto", "Bar");
 }
 
+TEST_F(CommandLineInterfaceTest, MultipleInputs_DescriptorSetIn) {
+  // Test parsing multiple input files.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_message_type()->set_name("Bar");
+
+  WriteDescriptorSet("foo.bin", &file_descriptor_set);
+
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto bar.proto");
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+}
+
 TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport) {
   // Test parsing multiple input files with an import of a separate file.
 
@@ -608,6 +696,165 @@
                                     "bar.proto", "Bar");
 }
 
+TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) {
+  // Test parsing multiple input files with an import of a separate file.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  DescriptorProto* message = file_descriptor_proto->add_message_type();
+  message->set_name("Bar");
+  FieldDescriptorProto* field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+
+  WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+  file_descriptor_set.clear_file();
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("baz.proto");
+  file_descriptor_proto->add_message_type()->set_name("Baz");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bat.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  message = file_descriptor_proto->add_message_type();
+  message->set_name("Bat");
+  field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+
+  WriteDescriptorSet("baz_and_bat.bin", &file_descriptor_set);
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+      "--descriptor_set_in=$0 foo.proto bar.proto",
+      string("$tmpdir/foo_and_bar.bin") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/baz_and_bat.bin"));
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_generator", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "foo.proto", "Foo");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
+                                    "bar.proto", "Bar");
+
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+      "--descriptor_set_in=$0 baz.proto bat.proto",
+      string("$tmpdir/foo_and_bar.bin") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/baz_and_bat.bin"));
+
+  ExpectNoErrors();
+  ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto",
+                                    "baz.proto", "Baz");
+  ExpectGeneratedWithMultipleInputs("test_generator", "baz.proto,bat.proto",
+                                    "bat.proto", "Bat");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "baz.proto,bat.proto",
+                                    "baz.proto", "Baz");
+  ExpectGeneratedWithMultipleInputs("test_plugin", "baz.proto,bat.proto",
+                                    "bat.proto", "Bat");
+}
+
+TEST_F(CommandLineInterfaceTest,
+       MultipleInputsWithImport_DescriptorSetIn_DuplicateFileDescriptor) {
+  // Test parsing multiple input files with an import of a separate file.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto foo_file_descriptor_proto;
+  foo_file_descriptor_proto.set_name("foo.proto");
+  foo_file_descriptor_proto.add_message_type()->set_name("Foo");
+
+  file_descriptor_set.add_file()->CopyFrom(foo_file_descriptor_proto);
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  file_descriptor_proto->add_dependency("foo.proto");
+  DescriptorProto* message = file_descriptor_proto->add_message_type();
+  message->set_name("Bar");
+  FieldDescriptorProto* field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+  field = message->add_field();
+  field->set_type_name("Foo");
+  field->set_name("f");
+  field->set_number(2);
+  WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+  file_descriptor_set.clear_file();
+  file_descriptor_set.add_file()->CopyFrom(foo_file_descriptor_proto);
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("baz.proto");
+  file_descriptor_proto->add_dependency("foo.proto");
+  message = file_descriptor_proto->add_message_type();
+  message->set_name("Baz");
+  field = message->add_field();
+  field->set_type_name("Foo");
+  field->set_name("f");
+  field->set_number(1);
+  WriteDescriptorSet("foo_and_baz.bin", &file_descriptor_set);
+
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
+      "--descriptor_set_in=$0 bar.proto",
+      string("$tmpdir/foo_and_bar.bin") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/foo_and_baz.bin"));
+
+  ExpectNoErrors();
+  ExpectGenerated("test_generator", "", "bar.proto", "Bar");
+  ExpectGenerated("test_plugin", "", "bar.proto", "Bar");
+}
+
+TEST_F(CommandLineInterfaceTest,
+       MultipleInputsWithImport_DescriptorSetIn_MissingImport) {
+  // Test parsing multiple input files with an import of a separate file.
+  FileDescriptorSet file_descriptor_set;
+
+  FileDescriptorProto* file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("foo.proto");
+  file_descriptor_proto->add_message_type()->set_name("Foo");
+
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("bar.proto");
+  file_descriptor_proto->add_dependency("baz.proto");
+  DescriptorProto* message = file_descriptor_proto->add_message_type();
+  message->set_name("Bar");
+  FieldDescriptorProto* field = message->add_field();
+  field->set_type_name("Baz");
+  field->set_name("a");
+  field->set_number(1);
+
+  WriteDescriptorSet("foo_and_bar.bin", &file_descriptor_set);
+
+  file_descriptor_set.clear_file();
+  file_descriptor_proto = file_descriptor_set.add_file();
+  file_descriptor_proto->set_name("baz.proto");
+  file_descriptor_proto->add_message_type()->set_name("Baz");
+
+  WriteDescriptorSet("baz.bin", &file_descriptor_set);
+  Run("protocol_compiler --test_out=$tmpdir --plug_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo_and_bar.bin "
+      "foo.proto bar.proto");
+  ExpectErrorSubstring(
+      "bar.proto: Import \"baz.proto\" was not found or had errors.");
+  ExpectErrorSubstring("bar.proto: \"Baz\" is not defined.");
+}
+
 TEST_F(CommandLineInterfaceTest, CreateDirectory) {
   // Test that when we output to a sub-directory, it is created.
 
@@ -754,6 +1001,25 @@
       "foo.proto", "Foo");
 }
 
+TEST_F(CommandLineInterfaceTest, InsertWithAnnotationFixup) {
+  // Check that annotation spans are updated after insertions.
+
+  CreateTempFile("foo.proto",
+                 "syntax = \"proto2\";\n"
+                 "message MockCodeGenerator_Annotate {}\n");
+
+  Run("protocol_compiler "
+      "--test_out=TestParameter:$tmpdir "
+      "--plug_out=TestPluginParameter:$tmpdir "
+      "--test_out=insert=test_generator,test_plugin:$tmpdir "
+      "--plug_out=insert=test_generator,test_plugin:$tmpdir "
+      "--proto_path=$tmpdir foo.proto");
+
+  ExpectNoErrors();
+  CheckGeneratedAnnotations("test_generator", "foo.proto");
+  CheckGeneratedAnnotations("test_plugin", "foo.proto");
+}
+
 #if defined(_WIN32)
 
 TEST_F(CommandLineInterfaceTest, WindowsOutputPath) {
@@ -839,17 +1105,11 @@
     "}\n");
   CreateTempFile("b/foo.proto", "this should not be parsed\n");
 
-#undef PATH_SEPARATOR
-#if defined(_WIN32)
-#define PATH_SEPARATOR ";"
-#else
-#define PATH_SEPARATOR ":"
-#endif
-
-  Run("protocol_compiler --test_out=$tmpdir "
-      "--proto_path=$tmpdir/a" PATH_SEPARATOR "$tmpdir/b foo.proto");
-
-#undef PATH_SEPARATOR
+  Run(strings::Substitute(
+      "protocol_compiler --test_out=$$tmpdir --proto_path=$0 foo.proto",
+      string("$tmpdir/a") +
+      CommandLineInterface::kPathSeparator +
+      "$tmpdir/b"));
 
   ExpectNoErrors();
   ExpectGenerated("test_generator", "", "foo.proto", "Foo");
@@ -1059,8 +1319,6 @@
 TEST_F(CommandLineInterfaceTest, CwdRelativeInputs) {
   // Test that we can accept working-directory-relative input files.
 
-  SetInputsAreProtoPathRelative(false);
-
   CreateTempFile("foo.proto",
     "syntax = \"proto2\";\n"
     "message Foo {}\n");
@@ -1318,6 +1576,17 @@
     "foo.proto:2:1: Expected top-level statement (e.g. \"message\").\n");
 }
 
+TEST_F(CommandLineInterfaceTest, ParseErrors_DescriptorSetIn) {
+  // Test that parse errors are reported.
+  CreateTempFile("foo.bin", "not a FileDescriptorSet");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
+  ExpectErrorText(
+    "$tmpdir/foo.bin: Unable to parse.\n");
+}
+
 TEST_F(CommandLineInterfaceTest, ParseErrorsMultipleFiles) {
   // Test that parse errors are reported from multiple files.
 
@@ -1364,16 +1633,23 @@
   Run("protocol_compiler --test_out=$tmpdir "
       "--proto_path=$tmpdir foo.proto");
 
+  ExpectErrorText("foo.proto: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, InputNotFoundError_DescriptorSetIn) {
+  // Test what happens if the input file is not found.
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+
   ExpectErrorText(
-    "foo.proto: File not found.\n");
+    "$tmpdir/foo.bin: No such file or directory\n");
 }
 
 TEST_F(CommandLineInterfaceTest, CwdRelativeInputNotFoundError) {
   // Test what happens when a working-directory-relative input file is not
   // found.
 
-  SetInputsAreProtoPathRelative(false);
-
   Run("protocol_compiler --test_out=$tmpdir "
       "--proto_path=$tmpdir $tmpdir/foo.proto");
 
@@ -1385,8 +1661,6 @@
   // Test what happens when a working-directory-relative input file is not
   // mapped to a virtual path.
 
-  SetInputsAreProtoPathRelative(false);
-
   CreateTempFile("foo.proto",
     "syntax = \"proto2\";\n"
     "message Foo {}\n");
@@ -1411,8 +1685,6 @@
   // Check what happens if the input file is not found *and* is not mapped
   // in the proto_path.
 
-  SetInputsAreProtoPathRelative(false);
-
   // Create a directory called "bar" so that we can point --proto_path at it.
   CreateTempFile("bar/dummy", "");
 
@@ -1427,8 +1699,6 @@
   // Test what happens when a working-directory-relative input file is shadowed
   // by another file in the virtual path.
 
-  SetInputsAreProtoPathRelative(false);
-
   CreateTempFile("foo/foo.proto",
     "syntax = \"proto2\";\n"
     "message Foo {}\n");
@@ -1454,8 +1724,34 @@
       "--proto_path=$tmpdir/foo foo.proto");
 
   ExpectErrorText(
-    "$tmpdir/foo: warning: directory does not exist.\n"
-    "foo.proto: File not found.\n");
+      "$tmpdir/foo: warning: directory does not exist.\n"
+      "foo.proto: No such file or directory\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDescriptorSetIn) {
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--proto_path=$tmpdir --descriptor_set_in=$tmpdir/foo.bin foo.proto");
+  ExpectErrorText(
+      "Only one of --descriptor_set_in and --proto_path can be specified.\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin --proto_path=$tmpdir foo.proto");
+  ExpectErrorText(
+      "Only one of --proto_path and --descriptor_set_in can be specified.\n");
+}
+
+TEST_F(CommandLineInterfaceTest, ProtoPathAndDependencyOut) {
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--dependency_out=$tmpdir/manifest "
+      "--descriptor_set_in=$tmpdir/foo.bin foo.proto");
+  ExpectErrorText(
+      "--descriptor_set_in cannot be used with --dependency_out.\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+      "--descriptor_set_in=$tmpdir/foo.bin "
+      "--dependency_out=$tmpdir/manifest foo.proto");
+  ExpectErrorText(
+      "--dependency_out cannot be used with --descriptor_set_in.\n");
 }
 
 TEST_F(CommandLineInterfaceTest, MissingInputError) {
@@ -1905,9 +2201,16 @@
 // test as a shell script, but we'd like to be able to run the test on
 // platforms that don't have a Bourne-compatible shell available (especially
 // Windows/MSVC).
-class EncodeDecodeTest : public testing::Test {
+
+enum EncodeDecodeTestMode {
+  PROTO_PATH,
+  DESCRIPTOR_SET_IN
+};
+
+class EncodeDecodeTest : public testing::TestWithParam<EncodeDecodeTestMode> {
  protected:
   virtual void SetUp() {
+    WriteUnittestProtoDescriptorSet();
     duped_stdin_ = dup(STDIN_FILENO);
   }
 
@@ -1950,7 +2253,18 @@
     std::vector<string> args;
     args.push_back("protoc");
     SplitStringUsing(command, " ", &args);
-    args.push_back("--proto_path=" + TestSourceDir());
+    switch (GetParam()) {
+      case PROTO_PATH:
+        args.push_back("--proto_path=" + TestSourceDir());
+        break;
+      case DESCRIPTOR_SET_IN:
+        args.push_back(StrCat(
+            "--descriptor_set_in=",
+            unittest_proto_descriptor_set_filename_));
+        break;
+      default:
+        ADD_FAILURE() << "unexpected EncodeDecodeTestMode: " << GetParam();
+    }
 
     google::protobuf::scoped_array<const char * > argv(new const char* [args.size()]);
     for (int i = 0; i < args.size(); i++) {
@@ -1958,7 +2272,6 @@
     }
 
     CommandLineInterface cli;
-    cli.SetInputsAreProtoPathRelative(true);
 
     CaptureTestStdout();
     CaptureTestStderr();
@@ -1996,12 +2309,37 @@
   }
 
  private:
+  void WriteUnittestProtoDescriptorSet() {
+    unittest_proto_descriptor_set_filename_ =
+        TestTempDir() + "/unittest_proto_descriptor_set.bin";
+    FileDescriptorSet file_descriptor_set;
+    protobuf_unittest::TestAllTypes test_all_types;
+    test_all_types.descriptor()->file()->CopyTo(file_descriptor_set.add_file());
+
+    protobuf_unittest_import::ImportMessage import_message;
+    import_message.descriptor()->file()->CopyTo(file_descriptor_set.add_file());
+
+
+    protobuf_unittest_import::PublicImportMessage public_import_message;
+    public_import_message.descriptor()->file()->CopyTo(
+        file_descriptor_set.add_file());
+    GOOGLE_DCHECK(file_descriptor_set.IsInitialized());
+
+    string binary_proto;
+    GOOGLE_CHECK(file_descriptor_set.SerializeToString(&binary_proto));
+    GOOGLE_CHECK_OK(File::SetContents(
+        unittest_proto_descriptor_set_filename_,
+        binary_proto,
+        true));
+  }
+
   int duped_stdin_;
   string captured_stdout_;
   string captured_stderr_;
+  string unittest_proto_descriptor_set_filename_;
 };
 
-TEST_F(EncodeDecodeTest, Encode) {
+TEST_P(EncodeDecodeTest, Encode) {
   RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/"
     "testdata/text_format_unittest_data_oneof_implemented.txt");
   EXPECT_TRUE(Run("google/protobuf/unittest.proto "
@@ -2011,7 +2349,7 @@
   ExpectStderrMatchesText("");
 }
 
-TEST_F(EncodeDecodeTest, Decode) {
+TEST_P(EncodeDecodeTest, Decode) {
   RedirectStdinFromFile(TestSourceDir() +
     "/google/protobuf/testdata/golden_message_oneof_implemented");
   EXPECT_TRUE(Run("google/protobuf/unittest.proto "
@@ -2022,7 +2360,7 @@
   ExpectStderrMatchesText("");
 }
 
-TEST_F(EncodeDecodeTest, Partial) {
+TEST_P(EncodeDecodeTest, Partial) {
   RedirectStdinFromText("");
   EXPECT_TRUE(Run("google/protobuf/unittest.proto "
                   "--encode=protobuf_unittest.TestRequired"));
@@ -2031,7 +2369,7 @@
     "warning:  Input message is missing required fields:  a, b, c\n");
 }
 
-TEST_F(EncodeDecodeTest, DecodeRaw) {
+TEST_P(EncodeDecodeTest, DecodeRaw) {
   protobuf_unittest::TestAllTypes message;
   message.set_optional_int32(123);
   message.set_optional_string("foo");
@@ -2045,21 +2383,24 @@
   ExpectStderrMatchesText("");
 }
 
-TEST_F(EncodeDecodeTest, UnknownType) {
+TEST_P(EncodeDecodeTest, UnknownType) {
   EXPECT_FALSE(Run("google/protobuf/unittest.proto "
                    "--encode=NoSuchType"));
   ExpectStdoutMatchesText("");
   ExpectStderrMatchesText("Type not defined: NoSuchType\n");
 }
 
-TEST_F(EncodeDecodeTest, ProtoParseError) {
+TEST_P(EncodeDecodeTest, ProtoParseError) {
   EXPECT_FALSE(Run("google/protobuf/no_such_file.proto "
                    "--encode=NoSuchType"));
   ExpectStdoutMatchesText("");
   ExpectStderrMatchesText(
-    "google/protobuf/no_such_file.proto: File not found.\n");
+      "google/protobuf/no_such_file.proto: No such file or directory\n");
 }
 
+INSTANTIATE_TEST_CASE_P(FileDescriptorSetSource,
+                        EncodeDecodeTest,
+                        testing::Values(PROTO_PATH, DESCRIPTOR_SET_IN));
 }  // anonymous namespace
 
 #endif  // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
index fce58c0..f99159f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -125,12 +125,9 @@
     importer.Import("google/protobuf/descriptor.proto");
   const FileDescriptor* plugin_proto_file =
     importer.Import("google/protobuf/compiler/plugin.proto");
-  const FileDescriptor* profile_proto_file =
-    importer.Import("google/protobuf/compiler/profile.proto");
   EXPECT_EQ("", error_collector.text_);
   ASSERT_TRUE(proto_file != NULL);
   ASSERT_TRUE(plugin_proto_file != NULL);
-  ASSERT_TRUE(profile_proto_file != NULL);
 
   CppGenerator generator;
   MockGeneratorContext context;
@@ -141,8 +138,6 @@
   parameter = "dllexport_decl=LIBPROTOC_EXPORT";
   ASSERT_TRUE(generator.Generate(plugin_proto_file, parameter,
                                  &context, &error));
-  ASSERT_TRUE(generator.Generate(profile_proto_file, parameter,
-                                 &context, &error));
 
   context.ExpectFileMatches("google/protobuf/descriptor.pb.h",
                             "google/protobuf/descriptor.pb.h");
@@ -152,10 +147,6 @@
                             "google/protobuf/compiler/plugin.pb.h");
   context.ExpectFileMatches("google/protobuf/compiler/plugin.pb.cc",
                             "google/protobuf/compiler/plugin.pb.cc");
-  context.ExpectFileMatches("google/protobuf/compiler/profile.pb.h",
-                            "google/protobuf/compiler/profile.pb.h");
-  context.ExpectFileMatches("google/protobuf/compiler/profile.pb.cc",
-                            "google/protobuf/compiler/profile.pb.cc");
 }
 
 }  // namespace
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 6a8a83d..3b4b97e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -81,10 +81,16 @@
   std::map<string, string> vars;
   vars["classname"] = classname_;
   vars["short_name"] = descriptor_->name();
-  vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : "");
+  vars["enumbase"] = options_.proto_h ? " : int" : "";
+  // These variables are placeholders to pick out the beginning and ends of
+  // identifiers for annotations (when doing so with existing variables would
+  // be ambiguous or impossible). They should never be set to anything but the
+  // empty string.
+  vars["{"] = "";
+  vars["}"] = "";
 
-  printer->Print(vars, "enum $enumbase$ {\n");
-  printer->Annotate("enumbase", descriptor_);
+  printer->Print(vars, "enum $classname$$enumbase$ {\n");
+  printer->Annotate("classname", descriptor_);
   printer->Indent();
 
   const EnumValueDescriptor* min_value = descriptor_->value(0);
@@ -102,7 +108,8 @@
         " PROTOBUF_DEPRECATED" : "";
 
     if (i > 0) printer->Print(",\n");
-    printer->Print(vars, "$prefix$$name$$deprecation$ = $number$");
+    printer->Print(vars, "${$$prefix$$name$$}$$deprecation$ = $number$");
+    printer->Annotate("{", "}", descriptor_->value(i));
 
     if (descriptor_->value(i)->number() < min_value->number()) {
       min_value = descriptor_->value(i);
@@ -134,14 +141,20 @@
   }
 
   printer->Print(vars,
-    "$dllexport$bool $classname$_IsValid(int value);\n"
-    "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n"
-    "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n");
+                 "$dllexport$bool $classname$_IsValid(int value);\n"
+                 "const $classname$ ${$$prefix$$short_name$_MIN$}$ = "
+                 "$prefix$$min_name$;\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(vars,
+                 "const $classname$ ${$$prefix$$short_name$_MAX$}$ = "
+                 "$prefix$$max_name$;\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (generate_array_size_) {
     printer->Print(vars,
-      "const int $prefix$$short_name$_ARRAYSIZE = "
-      "$prefix$$short_name$_MAX + 1;\n\n");
+                   "const int ${$$prefix$$short_name$_ARRAYSIZE$}$ = "
+                   "$prefix$$short_name$_MAX + 1;\n\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
index c15be94..08a635f 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
@@ -74,9 +74,11 @@
 
 void EnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
+  printer->Annotate("name", descriptor_);
   printer->Print(variables_,
-    "$deprecated_attr$$type$ $name$() const;\n"
-    "$deprecated_attr$void set_$name$($type$ value);\n");
+                 "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void EnumFieldGenerator::
@@ -113,7 +115,7 @@
 
 void EnumFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
 }
 
 void EnumFieldGenerator::
@@ -143,12 +145,14 @@
     if (UseUnknownFieldSet(descriptor_->file(), options_)) {
       printer->Print(variables_,
         "} else {\n"
-        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+        "  mutable_unknown_fields()->AddVarint(\n"
+        "      $number$, static_cast< ::google::protobuf::uint64>(value));\n");
     } else {
       printer->Print(
         "} else {\n"
         "  unknown_fields_stream.WriteVarint32($tag$u);\n"
-        "  unknown_fields_stream.WriteVarint32(value);\n",
+        "  unknown_fields_stream.WriteVarint32(\n"
+        "      static_cast< ::google::protobuf::uint32>(value));\n",
         "tag", SimpleItoa(internal::WireFormat::MakeTag(descriptor_)));
     }
     printer->Print(variables_,
@@ -257,12 +261,23 @@
 void RepeatedEnumFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "$deprecated_attr$$type$ $name$(int index) const;\n"
-    "$deprecated_attr$void set_$name$(int index, $type$ value);\n"
-    "$deprecated_attr$void add_$name$($type$ value);\n");
+                 "$deprecated_attr$$type$ $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(variables_,
-    "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n"
-    "$deprecated_attr$::google::protobuf::RepeatedField<int>* mutable_$name$();\n");
+                 "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$const ::google::protobuf::RepeatedField<int>& $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedField<int>* "
+                 "${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedEnumFieldGenerator::
@@ -292,8 +307,7 @@
   printer->Print(variables,
     "  $name$_.Add(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-    "}\n");
-  printer->Print(variables,
+    "}\n"
     "$inline$const ::google::protobuf::RepeatedField<int>&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
@@ -344,12 +358,14 @@
     if (UseUnknownFieldSet(descriptor_->file(), options_)) {
       printer->Print(variables_,
         "} else {\n"
-        "  mutable_unknown_fields()->AddVarint($number$, value);\n");
+        "  mutable_unknown_fields()->AddVarint(\n"
+        "      $number$, static_cast< ::google::protobuf::uint64>(value));\n");
     } else {
       printer->Print(
         "} else {\n"
         "  unknown_fields_stream.WriteVarint32(tag);\n"
-        "  unknown_fields_stream.WriteVarint32(value);\n");
+        "  unknown_fields_stream.WriteVarint32(\n"
+        "      static_cast< ::google::protobuf::uint32>(value));\n");
     }
     printer->Print("}\n");
   }
@@ -391,7 +407,7 @@
       "::google::protobuf::uint32 length;\n"
       "DO_(input->ReadVarint32(&length));\n"
       "::google::protobuf::io::CodedInputStream::Limit limit = "
-          "input->PushLimit(length);\n"
+          "input->PushLimit(static_cast<int>(length));\n"
       "while (input->BytesUntilLimit() > 0) {\n"
       "  int value;\n"
       "  DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n"
@@ -407,11 +423,13 @@
       "  } else {\n");
       if (UseUnknownFieldSet(descriptor_->file(), options_)) {
         printer->Print(variables_,
-        "    mutable_unknown_fields()->AddVarint($number$, value);\n");
+        "  mutable_unknown_fields()->AddVarint(\n"
+        "      $number$, static_cast< ::google::protobuf::uint64>(value));\n");
       } else {
         printer->Print(variables_,
         "    unknown_fields_stream.WriteVarint32(tag);\n"
-        "    unknown_fields_stream.WriteVarint32(value);\n");
+        "    unknown_fields_stream.WriteVarint32(\n"
+        "        static_cast< ::google::protobuf::uint32>(value));\n");
       }
       printer->Print(
       "  }\n");
@@ -432,7 +450,8 @@
       "    $number$,\n"
       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
       "    output);\n"
-      "  output->WriteVarint32(_$name$_cached_byte_size_);\n"
+      "  output->WriteVarint32(\n"
+      "      static_cast< ::google::protobuf::uint32>(_$name$_cached_byte_size_));\n"
       "}\n");
   }
   printer->Print(variables_,
@@ -460,7 +479,8 @@
       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
       "    target);\n"
       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray("
-      "    _$name$_cached_byte_size_, target);\n"
+      "      static_cast< ::google::protobuf::uint32>(\n"
+      "          _$name$_cached_byte_size_), target);\n"
       "  target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n"
       "    this->$name$_, target);\n"
       "}\n");
@@ -476,19 +496,20 @@
   printer->Print(variables_,
     "{\n"
     "  size_t data_size = 0;\n"
-    "  unsigned int count = this->$name$_size();");
+    "  unsigned int count = static_cast<unsigned int>(this->$name$_size());");
   printer->Indent();
   printer->Print(variables_,
       "for (unsigned int i = 0; i < count; i++) {\n"
       "  data_size += ::google::protobuf::internal::WireFormatLite::EnumSize(\n"
-      "    this->$name$(i));\n"
+      "    this->$name$(static_cast<int>(i)));\n"
       "}\n");
 
   if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (data_size > 0) {\n"
       "  total_size += $tag_size$ +\n"
-      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
+      "        static_cast< ::google::protobuf::int32>(data_size));\n"
       "}\n"
       "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
       "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
index e4fce46..6b1673b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_extension.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_extension.cc
@@ -35,9 +35,10 @@
 #include <google/protobuf/compiler/cpp/cpp_extension.h>
 #include <map>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index 4480a9d..dce9617 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -95,6 +95,13 @@
   // By default, empty string, so that generic code used for both oneofs and
   // singular fields can be written.
   (*variables)["oneof_prefix"] = "";
+
+  // These variables are placeholders to pick out the beginning and ends of
+  // identifiers for annotations (when doing so with existing variables would
+  // be ambiguous or impossible). They should never be set to anything but the
+  // empty string.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor,
@@ -194,7 +201,6 @@
   return *field_generators_[field->index()];
 }
 
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 00dc25d..d9dd385 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -180,10 +180,6 @@
   virtual void GenerateDefaultInstanceAllocator(io::Printer* /*printer*/)
       const {}
 
-  // Generate code that should be run when ShutdownProtobufLibrary() is called,
-  // to delete all dynamically-allocated objects.
-  virtual void GenerateShutdownCode(io::Printer* /*printer*/) const {}
-
   // Generate lines to decode this field, which will be placed inside the
   // message's MergeFromCodedStream() method.
   virtual void GenerateMergeFromCodedStream(io::Printer* printer) const = 0;
@@ -233,7 +229,6 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index e0542ae..a066a6a 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -126,12 +126,20 @@
         new EnumGenerator(file->enum_type(i), options));
     enum_generators_.push_back(enum_generators_owner_[i].get());
   }
+  for (int i = 0; i < enum_generators_.size(); i++) {
+    enum_generators_[i]->index_in_metadata_ = i;
+  }
 
   for (int i = 0; i < file->service_count(); i++) {
     service_generators_owner_[i].reset(
         new ServiceGenerator(file->service(i), options));
     service_generators_.push_back(service_generators_owner_[i].get());
   }
+  if (HasGenericServices(file_, options_)) {
+    for (int i = 0; i < service_generators_.size(); i++) {
+      service_generators_[i]->index_in_metadata_ = i;
+    }
+  }
 
   for (int i = 0; i < file->extension_count(); i++) {
     extension_generators_owner_[i].reset(
@@ -343,9 +351,10 @@
                "::";
     }
     printer->Print(
-        "class $classname$DefaultTypeInternal : "
-        "public ::google::protobuf::internal::ExplicitlyConstructed<$parent$$classname$> "
-        "{\n",
+        "class $classname$DefaultTypeInternal {\n"
+        "public:\n"
+        " ::google::protobuf::internal::ExplicitlyConstructed<$parent$$classname$>\n"
+        "     _instance;\n",
         "parent", parent, "classname", message_generators_[i]->classname_);
     printer->Indent();
     message_generators_[i]->GenerateExtraDefaultFields(printer);
@@ -526,11 +535,10 @@
 void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) {
   // AddDescriptors() is a file-level procedure which adds the encoded
   // FileDescriptorProto for this .proto file to the global DescriptorPool for
-  // generated files (DescriptorPool::generated_pool()). It either runs at
-  // static initialization time (by default) or when default_instance() is
-  // called for the first time (in LITE_RUNTIME mode with
-  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER flag enabled). This procedure also
-  // constructs default instances and registers extensions.
+  // generated files (DescriptorPool::generated_pool()). It ordinarily runs at
+  // static initialization time, but is not used at all in LITE_RUNTIME mode
+  // except when extensions are used. This procedure also constructs default
+  // instances and registers extensions.
   //
   // Its sibling, AssignDescriptors(), actually pulls the compiled
   // FileDescriptor from the DescriptorPool and uses it to populate all of
@@ -546,7 +554,8 @@
   // table-driven parsing.
 
   printer->Print("PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField\n"
-                 "    const TableStruct::entries[] = {\n");
+                 "    const TableStruct::entries[] "
+                 "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
   printer->Indent();
 
   std::vector<size_t> entries;
@@ -567,7 +576,8 @@
       "};\n"
       "\n"
       "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField\n"
-      "    const TableStruct::aux[] = {\n");
+      "    const TableStruct::aux[] "
+      "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
   printer->Indent();
 
   std::vector<size_t> aux_entries;
@@ -586,7 +596,8 @@
   printer->Print(
       "};\n"
       "PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const\n"
-      "    TableStruct::schema[] = {\n");
+      "    TableStruct::schema[] "
+      "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
   printer->Indent();
 
   size_t offset = 0;
@@ -598,7 +609,7 @@
   }
 
   if (message_generators_.empty()) {
-    printer->Print("{ NULL, NULL, 0, -1, -1, false },\n");
+    printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n");
   }
 
   printer->Outdent();
@@ -606,9 +617,47 @@
       "};\n"
       "\n");
 
+  if (!message_generators_.empty() && options_.table_driven_serialization) {
+    printer->Print(
+        "const ::google::protobuf::internal::FieldMetadata TableStruct::field_metadata[] "
+        "= {\n");
+    printer->Indent();
+    std::vector<int> field_metadata_offsets;
+    int idx = 0;
+    for (int i = 0; i < message_generators_.size(); i++) {
+      field_metadata_offsets.push_back(idx);
+      idx += message_generators_[i]->GenerateFieldMetadata(printer);
+    }
+    field_metadata_offsets.push_back(idx);
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "const ::google::protobuf::internal::SerializationTable "
+        "TableStruct::serialization_table[] = {\n");
+    printer->Indent();
+    // We rely on the order we layout the tables to match the order we
+    // calculate them with FlattenMessagesInFile, so we check here that
+    // these match exactly.
+    std::vector<const Descriptor*> calculated_order =
+        FlattenMessagesInFile(file_);
+    GOOGLE_CHECK_EQ(calculated_order.size(), message_generators_.size());
+    for (int i = 0; i < message_generators_.size(); i++) {
+      GOOGLE_CHECK_EQ(calculated_order[i], message_generators_[i]->descriptor_);
+      printer->Print(
+          "{$num_fields$, TableStruct::field_metadata + $index$},\n",
+          "classname", message_generators_[i]->classname_, "num_fields",
+          SimpleItoa(field_metadata_offsets[i + 1] - field_metadata_offsets[i]),
+          "index", SimpleItoa(field_metadata_offsets[i]));
+    }
+    printer->Outdent();
+    printer->Print(
+        "};\n"
+        "\n");
+  }
   if (HasDescriptorMethods(file_, options_)) {
     if (!message_generators_.empty()) {
-      printer->Print("const ::google::protobuf::uint32 TableStruct::offsets[] = {\n");
+      printer->Print("const ::google::protobuf::uint32 TableStruct::offsets[] "
+                     "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
       printer->Indent();
       std::vector<std::pair<size_t, size_t> > pairs;
       for (int i = 0; i < message_generators_.size(); i++) {
@@ -617,8 +666,8 @@
       printer->Outdent();
       printer->Print(
           "};\n"
-          "\n"
-          "static const ::google::protobuf::internal::MigrationSchema schemas[] = {\n");
+          "static const ::google::protobuf::internal::MigrationSchema schemas[] "
+          "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
       printer->Indent();
       {
         int offset = 0;
@@ -649,7 +698,7 @@
       // we still need these symbols to exist
       printer->Print(
           // MSVC doesn't like empty arrays, so we add a dummy.
-          "const ::google::protobuf::uint32 TableStruct::offsets[] = { ~0u };\n"
+          "const ::google::protobuf::uint32 TableStruct::offsets[1] = {};\n"
           "static const ::google::protobuf::internal::MigrationSchema* schemas = NULL;\n"
           "static const ::google::protobuf::Message* const* "
           "file_default_instances = NULL;\n");
@@ -692,7 +741,7 @@
       printer->Print(
           "file_level_metadata[$index$].reflection = "
           "$parent$::$classname$::CreateReflection(file_level_metadata[$index$]"
-          ".descriptor, _$classname$_default_instance_.get_mutable());\n",
+          ".descriptor, _$classname$_default_instance_._instance.get_mutable());\n",
           "index", SimpleItoa(i), "parent",
           ClassName(message_generators_[i]->descriptor_->containing_type(),
                     false),
@@ -739,33 +788,6 @@
       "}  // namespace\n");
   }
 
-  // -----------------------------------------------------------------
-
-  // ShutdownFile():  Deletes descriptors, default instances, etc. on shutdown.
-  printer->Print(
-    "\n"
-    "void TableStruct::Shutdown() {\n");
-  printer->Indent();
-
-  for (int i = 0; i < message_generators_.size(); i++) {
-    message_generators_[i]->GenerateShutdownCode(printer);
-  }
-
-  if (HasDescriptorMethods(file_, options_)) {
-    for (int i = 0; i < message_generators_.size(); i++) {
-      if (!IsMapEntryMessage(message_generators_[i]->descriptor_)) continue;
-      printer->Print(
-          "delete file_level_metadata[$index$].reflection;\n",
-          "index", SimpleItoa(i));
-    }
-  }
-
-  printer->Outdent();
-  printer->Print(
-    "}\n\n");
-
-  // -----------------------------------------------------------------
-
   // Now generate the InitDefaultsImpl() function.
   printer->Print(
       "void TableStruct::InitDefaultsImpl() {\n"
@@ -812,6 +834,7 @@
 
   // Now generate the AddDescriptors() function.
   printer->Print(
+      "namespace {\n"
       "void AddDescriptorsImpl() {\n"
       "  InitDefaults();\n");
 
@@ -826,7 +849,8 @@
     string file_data;
     file_proto.SerializeToString(&file_data);
 
-    printer->Print("static const char descriptor[] = {\n");
+    printer->Print("static const char descriptor[] "
+                   "GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {\n");
     printer->Indent();
 
     if (file_data.size() > 66535) {
@@ -877,31 +901,25 @@
                    file_namespace);
   }
 
-  printer->Print(
-      "::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);\n");
-
   printer->Outdent();
   printer->Print(
       "}\n"
+      "} // anonymous namespace\n"
       "\n"
       "void AddDescriptors() {\n"
       "  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);\n"
       "  ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);\n"
       "}\n");
 
-  if (!StaticInitializersForced(file_, options_)) {
-    printer->Print("#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n");
-  }
-  printer->Print(
-      // With static initializers.
-      "// Force AddDescriptors() to be called at static initialization time.\n"
-      "struct StaticDescriptorInitializer {\n"
-      "  StaticDescriptorInitializer() {\n"
-      "    AddDescriptors();\n"
-      "  }\n"
-      "} static_descriptor_initializer;\n");
-  if (!StaticInitializersForced(file_, options_)) {
-    printer->Print("#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n");
+  if (StaticInitializersForced(file_, options_)) {
+    printer->Print(
+        "// Force AddDescriptors() to be called at dynamic initialization "
+        "time.\n"
+        "struct StaticDescriptorInitializer {\n"
+        "  StaticDescriptorInitializer() {\n"
+        "    AddDescriptors();\n"
+        "  }\n"
+        "} static_descriptor_initializer;\n");
   }
 }
 
@@ -925,19 +943,11 @@
 
 void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
   ForwardDeclarations decls;
-  for (int i = 0; i < file_->dependency_count(); i++) {
-    FileGenerator dependency(file_->dependency(i), options_);
-    dependency.FillForwardDeclarations(&decls);
-  }
   FillForwardDeclarations(&decls);
   decls.Print(printer, options_);
 }
 
 void FileGenerator::FillForwardDeclarations(ForwardDeclarations* decls) {
-  for (int i = 0; i < file_->public_dependency_count(); i++) {
-    FileGenerator dependency(file_->public_dependency(i), options_);
-    dependency.FillForwardDeclarations(decls);
-  }
   for (int i = 0; i < package_parts_.size(); i++) {
     decls = decls->AddOrGetNamespace(package_parts_[i]);
   }
@@ -1033,11 +1043,11 @@
         "#include <google/protobuf/map.h>"
         "  // IWYU pragma: export\n");
     if (HasDescriptorMethods(file_, options_)) {
-      printer->Print(
-          "#include <google/protobuf/map_field_inl.h>\n");
+      printer->Print("#include <google/protobuf/map_entry.h>\n");
+      printer->Print("#include <google/protobuf/map_field_inl.h>\n");
     } else {
-      printer->Print(
-          "#include <google/protobuf/map_field_lite.h>\n");
+      printer->Print("#include <google/protobuf/map_entry_lite.h>\n");
+      printer->Print("#include <google/protobuf/map_field_lite.h>\n");
     }
   }
 
@@ -1104,7 +1114,7 @@
 
 void FileGenerator::GenerateGlobalStateFunctionDeclarations(
     io::Printer* printer) {
-  // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile
+  // Forward-declare the AddDescriptors, AssignDescriptors
   // functions, so that we can declare them to be friends of each class.
   printer->Print(
       "\n"
@@ -1115,12 +1125,14 @@
       "  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];\n"
       "  static const ::google::protobuf::internal::ParseTable schema[];\n"
       "  static const ::google::protobuf::uint32 offsets[];\n"
+      "  static const ::google::protobuf::internal::FieldMetadata field_metadata[];\n"
+      "  static const ::google::protobuf::internal::SerializationTable "
+      "serialization_table[];\n"
       // The following function(s) need to be able to access private members of
       // the messages defined in the file. So we make them static members.
       // This is the internal implementation of InitDefaults. It should only
       // be called by InitDefaults which makes sure it will be called only once.
       "  static void InitDefaultsImpl();\n"
-      "  static void Shutdown();\n"
       "};\n"
       "void $dllexport_decl$AddDescriptors();\n"
       "void $dllexport_decl$InitDefaults();\n"
@@ -1210,6 +1222,13 @@
   //     dependent.
 
   printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
+  // TODO(gerbens) remove pragmas when gcc is no longer used. Current version
+  // of gcc fires a bogus error when compiled with strict-aliasing.
+  printer->Print(
+    "#ifdef __GNUC__\n"
+    "  #pragma GCC diagnostic push\n"
+    "  #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n"
+    "#endif  // __GNUC__\n");
   // Generate class inline methods.
   for (int i = 0; i < message_generators_.size(); i++) {
     if (i > 0) {
@@ -1219,6 +1238,10 @@
     message_generators_[i]->GenerateInlineMethods(printer,
                                                   /* is_inline = */ true);
   }
+  printer->Print(
+    "#ifdef __GNUC__\n"
+    "  #pragma GCC diagnostic pop\n"
+    "#endif  // __GNUC__\n");
   printer->Print("#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS\n");
 
   for (int i = 0; i < message_generators_.size(); i++) {
@@ -1235,13 +1258,8 @@
     io::Printer* printer) {
   // Emit GetEnumDescriptor specializations into google::protobuf namespace:
   if (HasEnumDefinitions(file_)) {
-    // The SWIG conditional is to avoid a null-pointer dereference
-    // (bug 1984964) in swig-1.3.21 resulting from the following syntax:
-    //   namespace X { void Y<Z::W>(); }
-    // which appears in GetEnumDescriptor() specializations.
     printer->Print(
         "\n"
-        "#ifndef SWIG\n"
         "namespace google {\nnamespace protobuf {\n"
         "\n");
     for (int i = 0; i < enum_generators_.size(); i++) {
@@ -1249,8 +1267,7 @@
     }
     printer->Print(
         "\n"
-        "}  // namespace protobuf\n}  // namespace google\n"
-        "#endif  // SWIG\n");
+        "}  // namespace protobuf\n}  // namespace google\n");
   }
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
index cee3122..68abd0e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc
@@ -100,6 +100,8 @@
       file_options.enforce_lite = true;
     } else if (options[i].first == "table_driven_parsing") {
       file_options.table_driven_parsing = true;
+    } else if (options[i].first == "table_driven_serialization") {
+      file_options.table_driven_serialization = true;
     } else {
       *error = "Unknown generator option: " + options[i].first;
       return false;
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 9cddba5..0095979 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -37,14 +37,16 @@
 #include <vector>
 #include <google/protobuf/stubs/hash.h>
 
-#include <google/protobuf/compiler/cpp/cpp_helpers.h>
-#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
 
+
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -167,6 +169,11 @@
   }
 }
 
+string DefaultInstanceName(const Descriptor* descriptor) {
+  string prefix = descriptor->file()->package().empty() ? "" : "::";
+  return prefix + DotsToColons(descriptor->file()->package()) + "::_" +
+      ClassName(descriptor, false) + "_default_instance_";
+}
 
 string DependentBaseClassTemplateName(const Descriptor* descriptor) {
   return ClassName(descriptor, false) + "_InternalBase";
@@ -654,6 +661,26 @@
                         "VerifyUtf8Cord", "VerifyUTF8CordNamedField", printer);
 }
 
+namespace {
+
+void Flatten(const Descriptor* descriptor,
+             std::vector<const Descriptor*>* flatten) {
+  for (int i = 0; i < descriptor->nested_type_count(); i++)
+    Flatten(descriptor->nested_type(i), flatten);
+  flatten->push_back(descriptor);
+}
+
+}  // namespace
+
+std::vector<const Descriptor*> FlattenMessagesInFile(
+    const FileDescriptor* file) {
+  std::vector<const Descriptor*> result;
+  for (int i = 0; i < file->message_type_count(); i++) {
+    Flatten(file->message_type(i), &result);
+  }
+  return result;
+}
+
 bool HasWeakFields(const Descriptor* descriptor) {
   return false;
 }
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index a744a86..6ae6859 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -67,6 +67,9 @@
 string ClassName(const Descriptor* descriptor, bool qualified);
 string ClassName(const EnumDescriptor* enum_descriptor, bool qualified);
 
+// Fully qualified name of the default_instance of this message.
+string DefaultInstanceName(const Descriptor* descriptor);
+
 // Name of the CRTP class template (for use with proto_h).
 // This is a class name, like "ProtoName_InternalBase".
 string DependentBaseClassTemplateName(const Descriptor* descriptor);
@@ -159,8 +162,18 @@
                         const FieldDescriptor* field,
                         const string& prefix);
 
-// Returns true if unknown fields are preseved after parsing.
-inline bool PreserveUnknownFields(const Descriptor* message) {
+// Returns true if unknown fields are always preserved after parsing.
+inline bool AlwaysPreserveUnknownFields(const FileDescriptor* file) {
+  return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+// Returns true if unknown fields are preserved after parsing.
+inline bool AlwaysPreserveUnknownFields(const Descriptor* message) {
+  return AlwaysPreserveUnknownFields(message->file());
+}
+
+// Returns true if generated messages have public unknown fields accessors
+inline bool PublicUnknownFieldsAccessors(const Descriptor* message) {
   return message->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
 }
 
@@ -168,10 +181,8 @@
 ::google::protobuf::FileOptions_OptimizeMode GetOptimizeFor(
     const FileDescriptor* file, const Options& options);
 
-// If PreserveUnknownFields() is true, determines whether unknown
-// fields will be stored in an UnknownFieldSet or a string.
-// If PreserveUnknownFields() is false, this method will not be
-// used.
+// Determines whether unknown fields will be stored in an UnknownFieldSet or
+// a string.
 inline bool UseUnknownFieldSet(const FileDescriptor* file,
                                const Options& options) {
   return GetOptimizeFor(file, options) != FileOptions::LITE_RUNTIME;
@@ -277,6 +288,10 @@
       : file->options().optimize_for();
 }
 
+// This orders the messages in a .pb.cc as it's outputted by file.cc
+std::vector<const Descriptor*> FlattenMessagesInFile(
+    const FileDescriptor* file);
+
 bool HasWeakFields(const Descriptor* desc);
 bool HasWeakFields(const FileDescriptor* desc);
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index 52a3b8b..da33d29 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -150,6 +150,7 @@
                    "    $map_classname$;\n");
   }
   printer->Print(variables_,
+                 "private:\n"
                  "::google::protobuf::internal::MapField$lite$<\n"
                  "    $map_classname$,\n"
                  "    $key_cpp$, $val_cpp$,\n"
@@ -161,11 +162,15 @@
 
 void MapFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
-  printer->Print(variables_,
+  printer->Print(
+      variables_,
       "$deprecated_attr$const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
-      "    $name$() const;\n"
-      "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
-      "    mutable_$name$();\n");
+      "    $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+                 "    ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void MapFieldGenerator::
@@ -256,7 +261,8 @@
     } else {
       printer->Print(variables_,
           "    unknown_fields_stream.WriteVarint32($tag$u);\n"
-          "    unknown_fields_stream.WriteVarint32(data.size());\n"
+          "    unknown_fields_stream.WriteVarint32(\n"
+          "        static_cast<google::protobuf::uint32>(data.size()));\n"
           "    unknown_fields_stream.WriteString(data);\n");
     }
 
@@ -267,12 +273,16 @@
 
   if (key_field->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
-    key_field, options_, true, variables_,
-        StrCat(key, ".data(), ", key, ".length(),\n").data(), printer);
+        key_field, options_, true, variables_,
+        StrCat(key, ".data(), static_cast<int>(", key, ".length()),\n").data(),
+        printer);
   }
   if (value_field->type() == FieldDescriptor::TYPE_STRING) {
-    GenerateUtf8CheckCodeForString(value_field, options_, true, variables_,
-        StrCat(value, ".data(), ", value, ".length(),\n").data(), printer);
+    GenerateUtf8CheckCodeForString(
+        value_field, options_, true, variables_,
+        StrCat(value, ".data(), static_cast<int>(", value, ".length()),\n")
+            .data(),
+        printer);
   }
 
   // If entry is allocated by arena, its desctructor should be avoided.
@@ -376,14 +386,14 @@
     printer->Indent();
     printer->Indent();
     if (string_key) {
-      GenerateUtf8CheckCodeForString(key_field, options_, false, variables,
-                                     "p->first.data(), p->first.length(),\n",
-                                     printer);
+      GenerateUtf8CheckCodeForString(
+          key_field, options_, false, variables,
+          "p->first.data(), static_cast<int>(p->first.length()),\n", printer);
     }
     if (string_value) {
-      GenerateUtf8CheckCodeForString(value_field, options_, false, variables,
-                                     "p->second.data(), p->second.length(),\n",
-                                     printer);
+      GenerateUtf8CheckCodeForString(
+          value_field, options_, false, variables,
+          "p->second.data(), static_cast<int>(p->second.length()),\n", printer);
     }
     printer->Outdent();
     printer->Outdent();
@@ -404,13 +414,14 @@
       "  for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n"
       "      it = this->$name$().begin();\n"
       "      it != this->$name$().end(); ++it, ++n) {\n"
-      "    items[n] = SortItem(&*it);\n"
+      "    items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);\n"
       "  }\n"
-      "  ::std::sort(&items[0], &items[n], Less());\n");
+      "  ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());\n");
   printer->Indent();
   GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_),
-                            utf8_check, "for (size_type i = 0; i < n; i++)",
-                            string_key ? "items[i]" : "items[i].second", false);
+      utf8_check, "for (size_type i = 0; i < n; i++)",
+      string_key ? "items[static_cast<ptrdiff_t>(i)]" :
+                   "items[static_cast<ptrdiff_t>(i)].second", false);
   printer->Outdent();
   printer->Print(
       "} else {\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index d9524f6..63ebb3c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -52,6 +52,8 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/map_entry_lite.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
@@ -280,7 +282,7 @@
   enum Family {
     REPEATED = 0,
     STRING = 1,
-    MESSAGE = 2,
+    MESSAGE = 3,
     ZERO_INITIALIZABLE = 4,
     OTHER = 5,
     kMaxFamily
@@ -452,22 +454,13 @@
 }
 
 
-bool TableDrivenEnabled(const Descriptor* descriptor, const Options& options) {
+bool TableDrivenParsingEnabled(
+    const Descriptor* descriptor, const Options& options) {
   if (!options.table_driven_parsing) {
     return false;
   }
 
   // Consider table-driven parsing.  We only do this if:
-  // - There are no extensions
-  if (descriptor->extension_range_count() != 0) {
-    return false;
-  }
-
-  // - We are not using UnknownFieldSet (part of the non-lite library).
-  if (UseUnknownFieldSet(descriptor->file(), options)) {
-    return false;
-  }
-
   // - We have has_bits for fields.  This avoids a check on every field we set
   //   when are present (the common case).
   if (!HasFieldPresence(descriptor->file())) {
@@ -482,16 +475,6 @@
       max_field_number = field->number();
     }
 
-    // - There are no map fields.
-    if (field->is_map()) {
-      return false;
-    }
-
-    // - There are no oneof fields.
-    if (field->containing_oneof()) {
-      return false;
-    }
-
     // - There are no weak fields.
     if (field->options().weak()) {
       return false;
@@ -503,8 +486,10 @@
     return false;
   }
 
-  // - Field numbers are relatively dense within the actual number of fields
-  if (max_field_number * table_sparseness >= descriptor->field_count()) {
+  // - Field numbers are relatively dense within the actual number of fields.
+  //   We check for strictly greater than in the case where there are no fields
+  //   (only extensions) so max_field_number == descriptor->field_count() == 0.
+  if (max_field_number * table_sparseness > descriptor->field_count()) {
     return false;
   }
 
@@ -516,6 +501,31 @@
   return true;
 }
 
+void SetUnknkownFieldsVariable(const Descriptor* descriptor,
+                               const Options& options,
+                               std::map<string, string>* variables) {
+  if (UseUnknownFieldSet(descriptor->file(), options)) {
+    (*variables)["unknown_fields_type"] = "::google::protobuf::UnknownFieldSet";
+  } else {
+    (*variables)["unknown_fields_type"] = "::std::string";
+  }
+  if (AlwaysPreserveUnknownFields(descriptor)) {
+    (*variables)["have_unknown_fields"] =
+        "_internal_metadata_.have_unknown_fields()";
+    (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields()";
+  } else {
+    (*variables)["have_unknown_fields"] =
+        "(_internal_metadata_.have_unknown_fields() && "
+        " ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())";
+    (*variables)["unknown_fields"] =
+        "(::google::protobuf::internal::GetProto3PreserveUnknownsDefault()"
+        "   ? _internal_metadata_.unknown_fields()"
+        "   : _internal_metadata_.default_instance())";
+  }
+  (*variables)["mutable_unknown_fields"] =
+      "_internal_metadata_.mutable_unknown_fields()";
+}
+
 }  // anonymous namespace
 
 // ===================================================================
@@ -592,7 +602,7 @@
     use_dependent_base_ = true;
   }
 
-  table_driven_ = TableDrivenEnabled(descriptor_, options_);
+  table_driven_ = TableDrivenParsingEnabled(descriptor_, options_);
 }
 
 MessageGenerator::~MessageGenerator() {}
@@ -703,24 +713,29 @@
     }
 
     if (field->is_repeated()) {
-      printer->Print(vars, "$deprecated_attr$int $name$_size() const;\n");
+      printer->Print(vars, "$deprecated_attr$int ${$$name$_size$}$() const;\n");
+      printer->Annotate("{", "}", field);
     } else if (HasHasMethod(field)) {
-      printer->Print(vars, "$deprecated_attr$bool has_$name$() const;\n");
+      printer->Print(vars, "$deprecated_attr$bool ${$has_$name$$}$() const;\n");
+      printer->Annotate("{", "}", field);
     } else if (HasPrivateHasMethod(field)) {
       printer->Print(vars,
-          "private:\n"
-          "bool has_$name$() const;\n"
-          "public:\n");
+                     "private:\n"
+                     "bool ${$has_$name$$}$() const;\n"
+                     "public:\n");
+      printer->Annotate("{", "}", field);
     }
 
     if (!dependent_field) {
       // If this field is dependent, then its clear_() method is in the
       // depenent base class. (See also GenerateDependentAccessorDeclarations.)
-      printer->Print(vars, "$deprecated_attr$void clear_$name$();\n");
+      printer->Print(vars, "$deprecated_attr$void ${$clear_$name$$}$();\n");
+      printer->Annotate("{", "}", field);
     }
     printer->Print(vars,
                    "$deprecated_attr$static const int $constant_name$ = "
                    "$number$;\n");
+    printer->Annotate("constant_name", field);
 
     // Generate type-specific accessor declarations.
     field_generators_.get(field).GenerateAccessorDeclarations(printer);
@@ -1074,32 +1089,39 @@
   printer->Print(" public:\n");
   printer->Indent();
 
-  printer->Print(vars,
-    "$classname$();\n"
-    "virtual ~$classname$();\n"
-    "\n"
-    "$classname$(const $classname$& from);\n"
-    "\n"
-    "inline $classname$& operator=(const $classname$& from) {\n"
-    "  CopyFrom(from);\n"
-    "  return *this;\n"
-    "}\n"
-    "\n");
+  printer->Print(
+      vars,
+      "$classname$();\n"
+      "virtual ~$classname$();\n"
+      "\n"
+      "$classname$(const $classname$& from);\n"
+      "\n"
+      "inline $classname$& operator=(const $classname$& from) {\n"
+      "  CopyFrom(from);\n"
+      "  return *this;\n"
+      "}\n");
+
+  if (options_.table_driven_serialization) {
+    printer->Print(
+      "private:\n"
+      "const void* InternalGetTable() const;\n"
+      "public:\n"
+      "\n");
+  }
 
   // Generate move constructor and move assignment operator for types other than
   // Any.
-  #ifdef PROTO_EXPERIMENTAL_ENABLE_MOVE
   if (!IsAnyMessage(descriptor_)) {
     printer->Print(vars,
       "#if LANG_CXX11\n"
-      "$classname$($classname$&& from)\n"
+      "$classname$($classname$&& from) noexcept\n"
       "  : $classname$() {\n"
       "  *this = ::std::move(from);\n"
       "}\n"
       "\n"
-      "inline $classname$& operator=($classname$&& from) {\n"
+      "inline $classname$& operator=($classname$&& from) noexcept {\n"
       "  if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {\n"
-      "    InternalSwap(&from);\n"
+      "    if (this != &from) InternalSwap(&from);\n"
       "  } else {\n"
       "    CopyFrom(from);\n"
       "  }\n"
@@ -1107,22 +1129,17 @@
       "}\n"
       "#endif\n");
   }
-  #endif
 
-  if (PreserveUnknownFields(descriptor_)) {
-    string type = UseUnknownFieldSet(descriptor_->file(), options_)
-                      ? "::google::protobuf::UnknownFieldSet"
-                      : "::std::string";
-    printer->Print(
-      "inline const $type$& unknown_fields() const {\n"
-      "  return _internal_metadata_.unknown_fields();\n"
-      "}\n"
-      "\n"
-      "inline $type$* mutable_unknown_fields() {\n"
-      "  return _internal_metadata_.mutable_unknown_fields();\n"
-      "}\n"
-      "\n",
-      "type", type );
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  if (PublicUnknownFieldsAccessors(descriptor_)) {
+    printer->Print(vars,
+        "inline const $unknown_fields_type$& unknown_fields() const {\n"
+        "  return $unknown_fields$;\n"
+        "}\n"
+        "inline $unknown_fields_type$* mutable_unknown_fields() {\n"
+        "  return $mutable_unknown_fields$;\n"
+        "}\n"
+        "\n");
   }
 
   // N.B.: We exclude GetArena() when arena support is disabled, falling back on
@@ -1190,7 +1207,6 @@
       "  $message_index$;\n"
       "\n");
 
-
   if (SupportsArenas(descriptor_)) {
     printer->Print(vars,
       "void UnsafeArenaSwap($classname$* other);\n");
@@ -1214,6 +1230,9 @@
 
   printer->Print(vars,
     "void Swap($classname$* other);\n"
+    "friend void swap($classname$& a, $classname$& b) {\n"
+    "  a.Swap(&b);\n"
+    "}\n"
     "\n"
     "// implements Message ----------------------------------------------\n"
     "\n"
@@ -1250,9 +1269,14 @@
         "\n"
         "size_t ByteSizeLong() const PROTOBUF_FINAL;\n"
         "bool MergePartialFromCodedStream(\n"
-        "    ::google::protobuf::io::CodedInputStream* input)$merge_partial_final$;\n"
-        "void SerializeWithCachedSizes(\n"
-        "    ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;\n");
+        "    ::google::protobuf::io::CodedInputStream* input)$merge_partial_final$;\n");
+    if (!options_.table_driven_serialization ||
+        descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+          "void SerializeWithCachedSizes(\n"
+          "    ::google::protobuf::io::CodedOutputStream* output) const "
+          "PROTOBUF_FINAL;\n");
+    }
     // DiscardUnknownFields() is implemented in message.cc using reflections. We
     // need to implement this function in generated code for messages.
     if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
@@ -1278,6 +1302,9 @@
     "final", use_final);
   if (SupportsArenas(descriptor_)) {
     printer->Print(
+      // TODO(gerbens) Make this private! Currently people are deriving from
+      // protos to give access to this constructor, breaking the invariants
+      // we rely on.
       "protected:\n"
       "explicit $classname$(::google::protobuf::Arena* arena);\n"
       "private:\n"
@@ -1443,7 +1470,7 @@
 
   if (SupportsArenas(descriptor_)) {
     printer->Print(
-      "friend class ::google::protobuf::Arena;\n"
+      "template <typename T> friend class ::google::protobuf::Arena::InternalHelper;\n"
       "typedef void InternalArenaConstructable_;\n"
       "typedef void DestructorSkippable_;\n");
   }
@@ -1577,7 +1604,6 @@
   // Generate oneof default instance and weak field instances for reflection
   // usage.
   if (descriptor_->oneof_decl_count() > 0 || num_weak_fields_ > 0) {
-    printer->Print("public:\n");
     for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
       for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
         const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
@@ -1602,7 +1628,7 @@
 bool MessageGenerator::GenerateParseTable(io::Printer* printer, size_t offset,
                                           size_t aux_offset) {
   if (!table_driven_) {
-    printer->Print("{ NULL, NULL, 0, -1, -1, false },\n");
+    printer->Print("{ NULL, NULL, 0, -1, -1, -1, -1, NULL, false },\n");
     return false;
   }
 
@@ -1639,9 +1665,44 @@
       "  $classname$, _has_bits_),\n");
   }
 
+  if (descriptor_->oneof_decl_count() > 0) {
+    printer->Print(vars,
+                   "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
+                   "  $classname$, _oneof_case_),\n");
+  } else {
+    printer->Print("-1,  // no _oneof_case_\n");
+  }
+
+  if (descriptor_->extension_range_count() > 0) {
+    printer->Print(vars,
+        "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+        "_extensions_),\n");
+  } else {
+    printer->Print("-1,  // no _extensions_\n");
+  }
+
+  // TODO(ckennelly): Consolidate this with the calculation for
+  // AuxillaryParseTableField.
+  std::vector<string> package_parts;
+
+  const Descriptor* outer = descriptor_;
+  while (outer->containing_type() != NULL) {
+    outer = outer->containing_type();
+  }
+
+  package_parts = Split(
+      outer->full_name(), ".", true);
+  // outer->full_name() contains the class itself.  Remove it as it is
+  // used in the name of the default instance variable.
+  GOOGLE_DCHECK_NE(package_parts.size(), 0);
+  package_parts.back().clear();
+
+  vars["ns"] = Join(package_parts, "::");
+
   printer->Print(vars,
     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
-    "  $classname$, _internal_metadata_),\n");
+    "  $classname$, _internal_metadata_),\n"
+    "&::$ns$_$classname$_default_instance_,\n");
 
   if (UseUnknownFieldSet(descriptor_->file(), options_)) {
     printer->Print(vars, "true,\n");
@@ -1670,6 +1731,239 @@
                  "{ $offset$, $has_bits_offsets$, sizeof($classname$)},\n");
 }
 
+namespace {
+
+// TODO(gerbens) remove this after the next sync with GitHub code base.
+// Then the opensource testing has gained the functionality to compile
+// the CalcFieldNum given the symbols defined in generated-message-util.
+#ifdef OPENSOURCE_PROTOBUF_CPP_BOOTSTRAP
+// We need a clean version of CalcFieldNum that doesn't use new functionality
+// in the runtime, because this functionality is not yet in the opensource
+// runtime
+
+uint32 CalculateType(uint32 type, uint32 type_class) {
+  return (type - 1) + type_class * 20;
+}
+
+uint32 CalcFieldNum(const FieldDescriptor* field, const Options& options) {
+  bool is_a_map = IsMapEntryMessage(field->containing_type());
+  int type = field->type();
+  if (field->containing_oneof()) {
+    return CalculateType(type, 4);
+  }
+  if (field->is_packed()) {
+    return CalculateType(type, 3);
+  } else if (field->is_repeated()) {
+    return CalculateType(type, 2);
+  } else if (!HasFieldPresence(field->file()) &&
+             field->containing_oneof() == NULL && !is_a_map) {
+    return CalculateType(type, 1);
+  } else {
+    return CalculateType(type, 0);
+  }
+}
+
+#else
+// We need to calculate for each field what function the table driven code
+// should use to serialize it. This returns the index in a lookup table.
+uint32 CalcFieldNum(const FieldDescriptor* field, const Options& options) {
+  bool is_a_map = IsMapEntryMessage(field->containing_type());
+  int type = field->type();
+  if (field->containing_oneof()) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kOneOf);
+  }
+  if (field->is_packed()) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kPacked);
+  } else if (field->is_repeated()) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kRepeated);
+  } else if (!HasFieldPresence(field->file()) &&
+             field->containing_oneof() == NULL && !is_a_map) {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kNoPresence);
+  } else {
+    return internal::FieldMetadata::CalculateType(
+        type, internal::FieldMetadata::kPresence);
+  }
+}
+#endif
+
+int FindMessageIndexInFile(const Descriptor* descriptor) {
+  std::vector<const Descriptor*> flatten =
+      FlattenMessagesInFile(descriptor->file());
+  return std::find(flatten.begin(), flatten.end(), descriptor) -
+         flatten.begin();
+}
+
+}  // namespace
+
+int MessageGenerator::GenerateFieldMetadata(io::Printer* printer) {
+  if (!options_.table_driven_serialization) {
+    return 0;
+  }
+
+  std::vector<const FieldDescriptor*> sorted = SortFieldsByNumber(descriptor_);
+  if (IsMapEntryMessage(descriptor_)) {
+    for (int i = 0; i < 2; i++) {
+      const FieldDescriptor* field = sorted[i];
+      uint32 tag = internal::WireFormatLite::MakeTag(
+          field->number(), WireFormat::WireTypeForFieldType(field->type()));
+
+      std::map<string, string> vars;
+      vars["classname"] = classname_;
+      vars["parent_classname"] =
+          ClassName(descriptor_->containing_type(), false);
+      vars["field_name"] = FieldName(field);
+      vars["tag"] = SimpleItoa(tag);
+      vars["hasbit"] = SimpleItoa(i);
+      vars["type"] = SimpleItoa(CalcFieldNum(field, options_));
+      vars["ptr"] = "NULL";
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        GOOGLE_CHECK(!IsMapEntryMessage(field->message_type()));
+        {
+          vars["ptr"] =
+              QualifiedFileLevelSymbol(
+                  field->message_type()->file()->package(),
+                  FileLevelNamespace(field->message_type()->file()->name())) +
+              "::TableStruct::serialization_table + " +
+              SimpleItoa(FindMessageIndexInFile(field->message_type()));
+        }
+      }
+      vars["extra"] = HasDescriptorMethods(descriptor_->file(), options_)
+                          ? "::SuperType"
+                          : "";
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+                     "::google::protobuf::internal::MapEntryHelper<$parent_classname$::$"
+                     "classname$$extra$>, $field_name$_), $tag$,"
+                     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET("
+                     "::google::protobuf::internal::MapEntryHelper<$parent_classname$::$"
+                     "classname$$extra$>, _has_bits_) * 8 + $hasbit$, $type$, "
+                     "$ptr$},\n");
+    }
+    return 2;
+  }
+  printer->Print(
+      "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+      "_cached_size_), 0, 0, 0, NULL},\n",
+      "classname", classname_);
+  std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+    sorted_extensions.push_back(descriptor_->extension_range(i));
+  }
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeSorter());
+  for (int i = 0, extension_idx = 0; /* no range */; i++) {
+    for (; extension_idx < sorted_extensions.size() &&
+           (i == sorted.size() ||
+            sorted_extensions[extension_idx]->start < sorted[i]->number());
+         extension_idx++) {
+      const Descriptor::ExtensionRange* range =
+          sorted_extensions[extension_idx];
+      printer->Print(
+          "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+          "_extensions_), $start$, $end$, "
+          "::google::protobuf::internal::FieldMetadata::kSpecial, "
+          "reinterpret_cast<const "
+          "void*>(::google::protobuf::internal::ExtensionSerializer)},\n",
+          "classname", classname_, "start", SimpleItoa(range->start), "end",
+          SimpleItoa(range->end));
+    }
+    if (i == sorted.size()) break;
+    const FieldDescriptor* field = sorted[i];
+
+    uint32 tag = internal::WireFormatLite::MakeTag(
+        field->number(), WireFormat::WireTypeForFieldType(field->type()));
+    if (field->is_packed()) {
+      tag = internal::WireFormatLite::MakeTag(
+          field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+    }
+
+    string classfieldname = FieldName(field);
+    if (field->containing_oneof()) {
+      classfieldname = field->containing_oneof()->name();
+    }
+    std::map<string, string> vars;
+    vars["classname"] = classname_;
+    vars["field_name"] = classfieldname;
+    vars["tag"] = SimpleItoa(tag);
+    vars["ptr"] = "NULL";
+    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      if (IsMapEntryMessage(field->message_type())) {
+        vars["idx"] = SimpleItoa(FindMessageIndexInFile(field->message_type()));
+        vars["fieldclassname"] = ClassName(field->message_type(), false);
+        printer->Print(vars,
+                       "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                       "classname$, $field_name$_), $tag$, $idx$, "
+                       "::google::protobuf::internal::FieldMetadata::kSpecial, "
+                       "reinterpret_cast<const void*>(static_cast< "
+                       "::google::protobuf::internal::SpecialSerializer>("
+                       "::google::protobuf::internal::MapFieldSerializer< "
+                       "::google::protobuf::internal::MapEntryToMapField<$classname$::$"
+                       "fieldclassname$>::MapFieldType, "
+                       "TableStruct::serialization_table>))},\n");
+        continue;
+      } else {
+        vars["ptr"] =
+            QualifiedFileLevelSymbol(
+                field->message_type()->file()->package(),
+                FileLevelNamespace(field->message_type()->file()->name())) +
+            "::TableStruct::serialization_table + " +
+            SimpleItoa(FindMessageIndexInFile(field->message_type()));
+      }
+    }
+    vars["type"] = SimpleItoa(CalcFieldNum(field, options_));
+
+
+    if (field->options().weak()) {
+      // TODO(gerbens) merge weak fields into ranges
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, _weak_field_map_), $tag$, $tag$, "
+                     "::google::protobuf::internal::FieldMetadata::kSpecial, "
+                     "reinterpret_cast<const "
+                     "void*>(::google::protobuf::internal::WeakFieldSerializer)},\n");
+    } else if (field->containing_oneof()) {
+      vars["oneofoffset"] =
+          SimpleItoa(sizeof(uint32) * field->containing_oneof()->index());
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, $field_name$_), $tag$, "
+                     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, _oneof_case_) + $oneofoffset$, "
+                     "$type$, $ptr$},\n");
+    } else if (HasFieldPresence(descriptor_->file()) &&
+               has_bit_indices_[field->index()] != -1) {
+      vars["hasbitsoffset"] = SimpleItoa(has_bit_indices_[field->index()]);
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, $field_name$_), $tag$, "
+                     "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, _has_bits_) * 8 + $hasbitsoffset$, $type$, "
+                     "$ptr$},\n");
+    } else {
+      printer->Print(vars,
+                     "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($"
+                     "classname$, $field_name$_), $tag$, ~0u, $type$, "
+                     "$ptr$},\n");
+    }
+  }
+  int num_field_metadata = 1 + sorted.size() + sorted_extensions.size();
+  num_field_metadata++;
+  string serializer = UseUnknownFieldSet(descriptor_->file(), options_)
+                          ? "::google::protobuf::internal::UnknownFieldSetSerializer"
+                          : "::google::protobuf::internal::UnknownFieldSerializerLite";
+  printer->Print(
+      "{GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, "
+      "_internal_metadata_), 0, ~0u, "
+      "::google::protobuf::internal::FieldMetadata::kSpecial, reinterpret_cast<const "
+      "void*>($serializer$)},\n",
+      "classname", classname_, "serializer", serializer);
+  return num_field_metadata;
+}
+
 void MessageGenerator::
 GenerateDefaultInstanceAllocator(io::Printer* printer) {
   // Construct the default instances of all fields, as they will be used
@@ -1682,7 +1976,9 @@
   // Construct the default instance.  We can't call InitAsDefaultInstance() yet
   // because we need to make sure all default instances that this one might
   // depend on are constructed first.
-  printer->Print("_$classname$_default_instance_.DefaultConstruct();\n",
+  printer->Print("_$classname$_default_instance_._instance.DefaultConstruct();\n"
+                 "::google::protobuf::internal::OnShutdownDestroyMessage(\n"
+                 "    &_$classname$_default_instance_);",
                  "classname", classname_);
 }
 
@@ -1690,9 +1986,9 @@
 GenerateDefaultInstanceInitializer(io::Printer* printer) {
   if (IsMapEntryMessage(descriptor_)) {
     printer->Print(
-        "_$classname$_default_instance_.get_mutable()->set_default_instance(_$"
-        "classname$_default_instance_.get_mutable());\n"
-        "_$classname$_default_instance_.get_mutable()->InitAsDefaultInstance();"
+        "_$classname$_default_instance_._instance.get_mutable()->set_default_instance(_$"
+        "classname$_default_instance_._instance.get_mutable());\n"
+        "_$classname$_default_instance_._instance.get_mutable()->InitAsDefaultInstance();"
         "\n",
         "classname", classname_);
     return;
@@ -1715,7 +2011,8 @@
       if (field->containing_oneof() || field->options().weak()) {
         name = "_" + classname_ + "_default_instance_.";
       } else {
-        name = "_" + classname_ + "_default_instance_.get_mutable()->";
+        name =
+            "_" + classname_ + "_default_instance_._instance.get_mutable()->";
       }
       name += FieldName(field);
       printer->Print(
@@ -1732,25 +2029,6 @@
 }
 
 void MessageGenerator::
-GenerateShutdownCode(io::Printer* printer) {
-  if (IsMapEntryMessage(descriptor_)) return;
-
-  printer->Print("_$classname$_default_instance_.Shutdown();\n", "classname",
-                 classname_);
-
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    printer->Print("delete file_level_metadata[$index$].reflection;\n", "index",
-                   SimpleItoa(index_in_file_messages_));
-  }
-
-  // Handle default instances of fields.
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i))
-                     .GenerateShutdownCode(printer);
-  }
-}
-
-void MessageGenerator::
 GenerateClassMethods(io::Printer* printer) {
   if (IsMapEntryMessage(descriptor_)) {
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
@@ -1854,6 +2132,15 @@
   GenerateSwap(printer);
   printer->Print("\n");
 
+  if (options_.table_driven_serialization) {
+    printer->Print(
+      "const void* $classname$::InternalGetTable() const {\n"
+      "  return $file_namespace$::TableStruct::serialization_table + $index$;\n"
+      "}\n"
+      "\n",
+      "classname", classname_, "index", SimpleItoa(index_in_file_messages_),
+      "file_namespace", FileLevelNamespace(descriptor_->file()->name()));
+  }
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
     printer->Print(
         "::google::protobuf::Metadata $classname$::GetMetadata() const {\n"
@@ -1926,13 +2213,25 @@
 
     processing_type |= static_cast<unsigned>(
         field->is_repeated() ?  internal::kRepeatedMask : 0);
+    processing_type |= static_cast<unsigned>(
+        field->containing_oneof() ? internal::kOneofMask : 0);
+
+    if (field->is_map()) {
+      processing_type = internal::TYPE_MAP;
+    }
+
     const unsigned char tag_size =
       WireFormat::TagSize(field->number(), field->type());
 
     std::map<string, string> vars;
     vars["classname"] = classname_;
-    vars["name"] = FieldName(field);
-    vars["has"] = SimpleItoa(has_bit_indices_[field->index()]);
+    if (field->containing_oneof() != NULL) {
+      vars["name"] = field->containing_oneof()->name();
+      vars["presence"] = SimpleItoa(field->containing_oneof()->index());
+    } else {
+      vars["name"] = FieldName(field);
+      vars["presence"] = SimpleItoa(has_bit_indices_[field->index()]);
+    }
     vars["nwtype"] = SimpleItoa(normal_wiretype);
     vars["pwtype"] = SimpleItoa(packed_wiretype);
     vars["ptype"] = SimpleItoa(processing_type);
@@ -1942,7 +2241,7 @@
       "{\n"
       "  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(\n"
       "    $classname$, $name$_),\n"
-      "  static_cast< ::google::protobuf::uint32>($has$),\n"
+      "  static_cast< ::google::protobuf::uint32>($presence$),\n"
       "  $nwtype$, $pwtype$, $ptype$, $tag_size$\n"
       "},\n");
   }
@@ -1977,7 +2276,7 @@
         printer->Print(
             vars,
             "{::google::protobuf::internal::AuxillaryParseTableField::enum_aux{"
-            "$type$_IsValid, \"$type$\" }},\n");
+            "$type$_IsValid}},\n");
         last_field_number++;
         break;
       case FieldDescriptor::CPPTYPE_MESSAGE: {
@@ -1995,7 +2294,17 @@
         GOOGLE_DCHECK_NE(package_parts.size(), 0);
         package_parts.back().clear();
 
-        vars["classname"] = ClassName(field->message_type(), false);
+        if (field->is_map()) {
+          vars["classname"] = ClassName(field->containing_type(), false) +
+                              "::" + ClassName(field->message_type(), false);
+          printer->Print(vars,
+                         "{::google::protobuf::internal::AuxillaryParseTableField::map_"
+                         "aux{&::google::protobuf::internal::ParseMap<$classname$>}},\n");
+          last_field_number++;
+          break;
+        } else {
+          vars["classname"] = ClassName(field->message_type(), false);
+        }
         vars["ns"] = Join(package_parts, "::");
         vars["type"] = FieldMessageTypeName(field);
         vars["file_namespace"] = FileLevelNamespace(outer->file()->name());
@@ -2005,7 +2314,7 @@
             "  &::$ns$_$classname$_default_instance_,\n");
 
         bool dont_emit_table =
-            !TableDrivenEnabled(field->message_type(), options_);
+            !TableDrivenParsingEnabled(field->message_type(), options_);
 
         if (dont_emit_table) {
           printer->Print("  NULL,\n");
@@ -2034,16 +2343,10 @@
             break;
         }
         vars["full_name"] = field->full_name();
-        vars["strict"] =
-          field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3
-          ? "true" : "false";
-        vars["type"] = field->full_name();
         printer->Print(vars,
             "{::google::protobuf::internal::AuxillaryParseTableField::string_aux{\n"
             "  $default$,\n"
-            "  \"$full_name$\",\n"
-            "  $strict$,\n"
-            "  \"$type$\"\n"
+            "  \"$full_name$\"\n"
             "}},\n");
         last_field_number++;
         break;
@@ -2103,8 +2406,7 @@
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->containing_oneof() || field->options().weak()) {
       printer->Print(
-          "GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET("
-          "(&_$classname$_default_instance_), $name$_),\n",
+          "offsetof($classname$DefaultTypeInternal, $name$_),\n",
           "classname", classname_, "name", FieldName(field));
     } else {
       printer->Print(
@@ -2178,6 +2480,7 @@
     // Do nothing when the message is allocated in an arena.
     printer->Print(
       "::google::protobuf::Arena* arena = GetArenaNoVirtual();\n"
+      "GOOGLE_DCHECK(arena == NULL);\n"
       "if (arena != NULL) {\n"
       "  return;\n"
       "}\n"
@@ -2308,12 +2611,13 @@
   if (copy_constructor) {
     pod_template =
         "::memcpy(&$first$_, &from.$first$_,\n"
-        "  reinterpret_cast<char*>(&$last$_) -\n"
-        "  reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n";
+        "  static_cast<size_t>(reinterpret_cast<char*>(&$last$_) -\n"
+        "  reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
   } else {
     pod_template =
-        "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n"
-        "  reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n";
+        "::memset(&$first$_, 0, static_cast<size_t>(\n"
+        "    reinterpret_cast<char*>(&$last$_) -\n"
+        "    reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n";
   }
 
   for (int i = 0; i < optimized_order_.size(); ++i) {
@@ -2384,8 +2688,7 @@
     initializer_with_arena += ", _weak_field_map_(arena)";
   }
 
-  string initializer_null;
-  initializer_null = ", _internal_metadata_(NULL)";
+  string initializer_null = superclass + "(), _internal_metadata_(NULL)";
   if (IsAnyMessage(descriptor_)) {
     initializer_null += ", _any_metadata_(&type_url_, &value_)";
   }
@@ -2395,26 +2698,22 @@
 
   printer->Print(
       "$classname$::$classname$()\n"
-      "  : $superclass$()$initializer$ {\n"
+      "  : $initializer$ {\n"
       "  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {\n"
       "    $file_namespace$::InitDefaults();\n"
       "  }\n"
       "  SharedCtor();\n"
       "  // @@protoc_insertion_point(constructor:$full_name$)\n"
       "}\n",
-      "classname", classname_, "superclass", superclass, "full_name",
-      descriptor_->full_name(), "initializer", initializer_null,
-      "file_namespace", FileLevelNamespace(descriptor_->file()->name()));
+      "classname", classname_, "full_name", descriptor_->full_name(),
+      "initializer", initializer_null, "file_namespace",
+      FileLevelNamespace(descriptor_->file()->name()));
 
   if (SupportsArenas(descriptor_)) {
     printer->Print(
         "$classname$::$classname$(::google::protobuf::Arena* arena)\n"
         "  : $initializer$ {\n"
-        // When arenas are used it's safe to assume we have finished
-        // static init time (protos with arenas are unsafe during static init)
-        "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
         "  $file_namespace$::InitDefaults();\n"
-        "#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n"
         "  SharedCtor();\n"
         "  RegisterArenaDtor(arena);\n"
         "  // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
@@ -2601,7 +2900,6 @@
       "}\n",
       "classname", classname_);
   }
-
 }
 
 // Return the number of bits set in n, a non-negative integer.
@@ -2614,6 +2912,22 @@
   return result;
 }
 
+bool MessageGenerator::MaybeGenerateOptionalFieldCondition(
+    io::Printer* printer, const FieldDescriptor* field,
+    int expected_has_bits_index) {
+  int has_bit_index = has_bit_indices_[field->index()];
+  if (!field->options().weak() &&
+      expected_has_bits_index == has_bit_index / 32) {
+    const string mask =
+        StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+    printer->Print(
+        "if (cached_has_bits & 0x$mask$u) {\n",
+        "mask", mask);
+    return true;
+  }
+  return false;
+}
+
 void MessageGenerator::
 GenerateClear(io::Printer* printer) {
   printer->Print(
@@ -2622,6 +2936,15 @@
       "classname", classname_, "full_name", descriptor_->full_name());
   printer->Indent();
 
+  printer->Print(
+      // TODO(jwb): It would be better to avoid emitting this if it is not used,
+      // rather than emitting a workaround for the resulting warning.
+      "::google::protobuf::uint32 cached_has_bits = 0;\n"
+      "// Prevent compiler warnings about cached_has_bits being unused\n"
+      "(void) cached_has_bits;\n\n");
+
+  int cached_has_bit_index = -1;
+
   // Step 1: Extensions
   if (descriptor_->extension_range_count() > 0) {
     printer->Print("_extensions_.Clear();\n");
@@ -2730,9 +3053,14 @@
         GOOGLE_DCHECK_LE(2, count);
         GOOGLE_DCHECK_GE(8, count);
 
+        if (cached_has_bit_index != last_chunk / 4) {
+          cached_has_bit_index = last_chunk / 4;
+          printer->Print(
+              "cached_has_bits = _has_bits_[$idx$];\n",
+              "idx", SimpleItoa(cached_has_bit_index));
+        }
         printer->Print(
-          "if (_has_bits_[$index$ / 32] & $mask$u) {\n",
-          "index", SimpleItoa(last_chunk * 8),
+          "if (cached_has_bits & $mask$u) {\n",
           "mask", SimpleItoa(last_chunk_mask));
         printer->Indent();
       }
@@ -2750,8 +3078,9 @@
               FieldName(optimized_order_[memset_run_end]);
 
           printer->Print(
-            "::memset(&$first$_, 0, reinterpret_cast<char*>(&$last$_) -\n"
-            "  reinterpret_cast<char*>(&$first$_) + sizeof($last$_));\n",
+            "::memset(&$first$_, 0, static_cast<size_t>(\n"
+            "    reinterpret_cast<char*>(&$last$_) -\n"
+            "    reinterpret_cast<char*>(&$first$_)) + sizeof($last$_));\n",
             "first", first_field_name,
             "last", last_field_name);
         }
@@ -2778,7 +3107,12 @@
         if (should_check_bit &&
             // If no field presence, then always clear strings/messages as well.
             HasFieldPresence(descriptor_->file())) {
-          printer->Print("if (has_$name$()) {\n", "name", fieldname);
+          if (!MaybeGenerateOptionalFieldCondition(printer, field,
+                                                   cached_has_bit_index)) {
+            printer->Print(
+                "if (has_$name$()) {\n",
+                "name", fieldname);
+          }
           printer->Indent();
           have_enclosing_if = true;
         }
@@ -2814,9 +3148,7 @@
     printer->Print("_has_bits_.Clear();\n");
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print("_internal_metadata_.Clear();\n");
-  }
+  printer->Print("_internal_metadata_.Clear();\n");
 
   printer->Outdent();
   printer->Print("}\n");
@@ -2920,6 +3252,7 @@
   printer->Print("void $classname$::InternalSwap($classname$* other) {\n",
                  "classname", classname_);
   printer->Indent();
+  printer->Print("using std::swap;\n");
 
   if (HasGeneratedMethods(descriptor_->file(), options_)) {
     for (int i = 0; i < optimized_order_.size(); i++) {
@@ -2931,24 +3264,22 @@
 
     for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
       printer->Print(
-        "std::swap($oneof_name$_, other->$oneof_name$_);\n"
-        "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n",
+        "swap($oneof_name$_, other->$oneof_name$_);\n"
+        "swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n",
         "oneof_name", descriptor_->oneof_decl(i)->name(),
         "i", SimpleItoa(i));
     }
 
     if (HasFieldPresence(descriptor_->file())) {
       for (int i = 0; i < HasBitsSize() / 4; ++i) {
-        printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
+        printer->Print("swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n",
                        "i", SimpleItoa(i));
       }
     }
 
-    if (PreserveUnknownFields(descriptor_)) {
-      printer->Print("_internal_metadata_.Swap(&other->_internal_metadata_);\n");
-    }
+    printer->Print("_internal_metadata_.Swap(&other->_internal_metadata_);\n");
 
-    printer->Print("std::swap(_cached_size_, other->_cached_size_);\n");
+    printer->Print("swap(_cached_size_, other->_cached_size_);\n");
     if (descriptor_->extension_range_count() > 0) {
       printer->Print("_extensions_.Swap(&other->_extensions_);\n");
     }
@@ -3251,21 +3582,16 @@
 
 void MessageGenerator::
 GenerateMergeFromCodedStream(io::Printer* printer) {
+  std::map<string, string> vars;
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
-    printer->Print(
+    vars["classname"] = classname_;
+    printer->Print(vars,
       "bool $classname$::MergePartialFromCodedStream(\n"
-      "    ::google::protobuf::io::CodedInputStream* input) {\n",
-      "classname", classname_);
-
-    printer->Print(
-        "  return _extensions_.ParseMessageSet(input, "
-        "internal_default_instance(),\n"
-        "                                      mutable_unknown_fields());\n",
-        // Vars.
-        "classname", classname_);
-
-    printer->Print(
+      "    ::google::protobuf::io::CodedInputStream* input) {\n"
+      "  return _extensions_.ParseMessageSet(input,\n"
+      "      internal_default_instance(), $mutable_unknown_fields$);\n"
       "}\n");
     return;
   }
@@ -3281,14 +3607,18 @@
   if (table_driven_) {
     printer->Indent();
 
+    const string lite = UseUnknownFieldSet(descriptor_->file(), options_) ?
+        "" : "Lite";
+
     printer->Print(
-        "return ::google::protobuf::internal::MergePartialFromCodedStream(\n"
+        "return ::google::protobuf::internal::MergePartialFromCodedStream$lite$(\n"
         "    this,\n"
         "    $file_namespace$::TableStruct::schema[\n"
         "      $classname$::kIndexInFileMessages],\n"
         "    input);\n",
         "classname", classname_,
-        "file_namespace", FileLevelNamespace(descriptor_->file()->name()));
+        "file_namespace", FileLevelNamespace(descriptor_->file()->name()),
+        "lite", lite);
 
     printer->Outdent();
 
@@ -3300,8 +3630,7 @@
     "#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure\n"
     "  ::google::protobuf::uint32 tag;\n");
 
-  if (PreserveUnknownFields(descriptor_) &&
-      !UseUnknownFieldSet(descriptor_->file(), options_)) {
+  if (!UseUnknownFieldSet(descriptor_->file(), options_)) {
     // Use LazyStringOutputString to avoid initializing unknown fields string
     // unless it is actually needed. For the same reason, disable eager refresh
     // on the CodedOutputStream.
@@ -3354,13 +3683,12 @@
   }
 
   printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = "
-                 "input->ReadTagWithCutoff$lasttag$($max$u);\n"
+                 "input->ReadTagWithCutoffNoLastTag($max$u);\n"
                  "tag = p.first;\n"
                  "if (!p.second) goto handle_unusual;\n",
                  "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 :
                                    (maxtag <= kCutoff1 ? kCutoff1 :
-                                    maxtag)),
-                 "lasttag", !capture_last_tag ? "NoLastTag" : "");
+                                    maxtag)));
 
   if (descriptor_->field_count() > 0) {
     // We don't even want to print the switch() if we have no fields because
@@ -3395,9 +3723,11 @@
       const FieldGenerator& field_generator = field_generators_.get(field);
 
       // Emit code to parse the common, expected case.
-      printer->Print("if (static_cast< ::google::protobuf::uint8>(tag) ==\n"
-                     "    static_cast< ::google::protobuf::uint8>($commontag$u)) {\n",
-          "commontag", SimpleItoa(WireFormat::MakeTag(field)));
+      printer->Print(
+        "if (static_cast< ::google::protobuf::uint8>(tag) ==\n"
+        "    static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n",
+        "truncated", SimpleItoa(WireFormat::MakeTag(field) & 0xFF),
+        "full", SimpleItoa(WireFormat::MakeTag(field)));
 
       printer->Indent();
       if (field->is_packed()) {
@@ -3411,22 +3741,30 @@
       if (field->is_packed()) {
         internal::WireFormatLite::WireType wiretype =
             WireFormat::WireTypeForFieldType(field->type());
-        printer->Print("} else if (static_cast< ::google::protobuf::uint8>(tag) ==\n"
-                       "           static_cast< ::google::protobuf::uint8>($uncommontag$u)) {\n",
-                       "uncommontag", SimpleItoa(
-                           internal::WireFormatLite::MakeTag(
-                               field->number(), wiretype)));
+        const uint32 tag = internal::WireFormatLite::MakeTag(
+            field->number(), wiretype);
+        printer->Print(
+            "} else if (\n"
+            "    static_cast< ::google::protobuf::uint8>(tag) ==\n"
+            "    static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n",
+            "truncated", SimpleItoa(tag & 0xFF),
+            "full", SimpleItoa(tag));
+
         printer->Indent();
         field_generator.GenerateMergeFromCodedStream(printer);
         printer->Outdent();
       } else if (field->is_packable() && !field->is_packed()) {
         internal::WireFormatLite::WireType wiretype =
             internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
-        printer->Print("} else if (static_cast< ::google::protobuf::uint8>(tag) ==\n"
-                       "           static_cast< ::google::protobuf::uint8>($uncommontag$u)) {\n",
-                       "uncommontag", SimpleItoa(
-                           internal::WireFormatLite::MakeTag(
-                               field->number(), wiretype)));
+         const uint32 tag = internal::WireFormatLite::MakeTag(
+            field->number(), wiretype);
+
+        printer->Print(
+            "} else if (\n"
+            "    static_cast< ::google::protobuf::uint8>(tag) ==\n"
+            "    static_cast< ::google::protobuf::uint8>($truncated$u /* $full$ & 0xFF */)) {\n",
+            "truncated", SimpleItoa(tag & 0xFF),
+            "full", SimpleItoa(tag));
         printer->Indent();
         field_generator.GenerateMergeFromCodedStreamWithPacking(printer);
         printer->Outdent();
@@ -3452,12 +3790,20 @@
   printer->Print("handle_unusual:\n");
   printer->Indent();
   // If tag is 0 or an end-group tag then this must be the end of the message.
-  printer->Print(
-    "if (tag == 0 ||\n"
-    "    ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
-    "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
-    "  goto success;\n"
-    "}\n");
+  if (capture_last_tag) {
+    printer->Print(
+      "if (tag == 0 ||\n"
+      "    ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n"
+      "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n"
+      "  input->SetLastTag(tag);\n"
+      "  goto success;\n"
+      "}\n");
+  } else {
+    printer->Print(
+      "if (tag == 0) {\n"
+      "  goto success;\n"
+      "}\n");
+  }
 
   // Handle extension ranges.
   if (descriptor_->extension_range_count() > 0) {
@@ -3485,23 +3831,16 @@
       }
     }
     printer->Print(") {\n");
-    if (PreserveUnknownFields(descriptor_)) {
-      if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-        printer->Print(
-            "  DO_(_extensions_.ParseField(tag, input, "
-            "internal_default_instance(),\n"
-            "                              mutable_unknown_fields()));\n");
-      } else {
-        printer->Print(
-            "  DO_(_extensions_.ParseField(tag, input, "
-            "internal_default_instance(),\n"
-            "                              &unknown_fields_stream));\n");
-      }
+    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+      printer->Print(vars,
+        "  DO_(_extensions_.ParseField(tag, input,\n"
+        "      internal_default_instance(),\n"
+        "      $mutable_unknown_fields$));\n");
     } else {
       printer->Print(
-          // With static initializers.
-          "  DO_(_extensions_.ParseField(tag, input, "
-          "internal_default_instance());\n");
+        "  DO_(_extensions_.ParseField(tag, input,\n"
+        "      internal_default_instance(),\n"
+        "      &unknown_fields_stream));\n");
     }
     printer->Print(
       "  continue;\n"
@@ -3509,19 +3848,14 @@
   }
 
   // We really don't recognize this tag.  Skip it.
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-      printer->Print(
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
         "DO_(::google::protobuf::internal::WireFormat::SkipField(\n"
-        "      input, tag, mutable_unknown_fields()));\n");
-    } else {
-      printer->Print(
-        "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
-        "    input, tag, &unknown_fields_stream));\n");
-    }
+        "      input, tag, $mutable_unknown_fields$));\n");
   } else {
     printer->Print(
-      "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n");
+        "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n"
+        "    input, tag, &unknown_fields_stream));\n");
   }
 
   if (descriptor_->field_count() > 0) {
@@ -3658,13 +3992,16 @@
       "  _extensions_.SerializeMessageSetWithCachedSizes(output);\n",
       "classname", classname_);
     GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
-    printer->Print(
+    std::map<string, string> vars;
+    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    printer->Print(vars,
       "  ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n"
-      "      unknown_fields(), output);\n");
+      "      $unknown_fields$, output);\n");
     printer->Print(
       "}\n");
     return;
   }
+  if (options_.table_driven_serialization) return;
 
   printer->Print(
     "void $classname$::SerializeWithCachedSizes(\n"
@@ -3699,10 +4036,12 @@
       "               deterministic, target);\n",
       "classname", classname_);
     GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
-    printer->Print(
+    std::map<string, string> vars;
+    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    printer->Print(vars,
       "  target = ::google::protobuf::internal::WireFormat::\n"
       "             SerializeUnknownMessageSetItemsToArray(\n"
-      "               unknown_fields(), target);\n");
+      "               $unknown_fields$, target);\n");
     printer->Print(
       "  return target;\n"
       "}\n");
@@ -3715,6 +4054,7 @@
     "classname", classname_);
   printer->Indent();
 
+  printer->Print("(void)deterministic; // Unused\n");
   printer->Print(
     "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n",
     "full_name", descriptor_->full_name());
@@ -3866,29 +4206,29 @@
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-      printer->Print("if (_internal_metadata_.have_unknown_fields()) {\n");
-      printer->Indent();
-      if (to_array) {
-        printer->Print(
-          "target = "
-              "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
-          "    unknown_fields(), target);\n");
-      } else {
-        printer->Print(
-          "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
-          "    unknown_fields(), output);\n");
-      }
-      printer->Outdent();
-
-      printer->Print(
-        "}\n");
+  std::map<string, string> vars;
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "if ($have_unknown_fields$) {\n");
+    printer->Indent();
+    if (to_array) {
+      printer->Print(vars,
+        "target = "
+        "::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(\n"
+        "    $unknown_fields$, target);\n");
     } else {
-      printer->Print(
-        "output->WriteRaw(unknown_fields().data(),\n"
-        "                 static_cast<int>(unknown_fields().size()));\n");
+      printer->Print(vars,
+        "::google::protobuf::internal::WireFormat::SerializeUnknownFields(\n"
+        "    $unknown_fields$, output);\n");
     }
+    printer->Outdent();
+
+    printer->Print("}\n");
+  } else {
+    printer->Print(vars,
+      "output->WriteRaw($unknown_fields$.data(),\n"
+      "                 static_cast<int>($unknown_fields$.size()));\n");
   }
 }
 
@@ -3932,18 +4272,19 @@
 GenerateByteSize(io::Printer* printer) {
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
-    printer->Print(
-        "size_t $classname$::ByteSizeLong() const {\n"
-        "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
-        "  size_t total_size = _extensions_.MessageSetByteSize();\n",
-        "classname", classname_, "full_name", descriptor_->full_name());
     GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file(), options_));
-    printer->Print(
-      "if (_internal_metadata_.have_unknown_fields()) {\n"
-      "  total_size += ::google::protobuf::internal::WireFormat::\n"
-      "      ComputeUnknownMessageSetItemsSize(unknown_fields());\n"
-      "}\n");
-    printer->Print(
+    std::map<string, string> vars;
+    SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+    vars["classname"] = classname_;
+    vars["full_name"] = descriptor_->full_name();
+    printer->Print(vars,
+      "size_t $classname$::ByteSizeLong() const {\n"
+      "// @@protoc_insertion_point(message_set_byte_size_start:$full_name$)\n"
+      "  size_t total_size = _extensions_.MessageSetByteSize();\n"
+      "  if ($have_unknown_fields$) {\n"
+      "    total_size += ::google::protobuf::internal::WireFormat::\n"
+      "        ComputeUnknownMessageSetItemsSize($unknown_fields$);\n"
+      "  }\n"
       "  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);\n"
       "  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
       "  _cached_size_ = cached_size;\n"
@@ -3997,19 +4338,19 @@
       "\n");
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (UseUnknownFieldSet(descriptor_->file(), options_)) {
-      printer->Print(
-        "if (_internal_metadata_.have_unknown_fields()) {\n"
-        "  total_size +=\n"
-        "    ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
-        "      unknown_fields());\n"
-        "}\n");
-    } else {
-      printer->Print(
-        "total_size += unknown_fields().size();\n"
-        "\n");
-    }
+  std::map<string, string> vars;
+  SetUnknkownFieldsVariable(descriptor_, options_, &vars);
+  if (UseUnknownFieldSet(descriptor_->file(), options_)) {
+    printer->Print(vars,
+      "if ($have_unknown_fields$) {\n"
+      "  total_size +=\n"
+      "    ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(\n"
+      "      $unknown_fields$);\n"
+      "}\n");
+  } else {
+    printer->Print(vars,
+      "total_size += $unknown_fields$.size();\n"
+      "\n");
   }
 
   // Handle required fields (if any).  We expect all of them to be
@@ -4358,7 +4699,6 @@
     "}\n");
 }
 
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 23aaeeb..352069e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -104,10 +104,6 @@
   // allocated before any can be initialized.
   void GenerateDefaultInstanceInitializer(io::Printer* printer);
 
-  // Generates code that should be run when ShutdownProtobufLibrary() is called,
-  // to delete all dynamically-allocated objects.
-  void GenerateShutdownCode(io::Printer* printer);
-
   // Generate all non-inline methods for this class.
   void GenerateClassMethods(io::Printer* printer);
 
@@ -132,6 +128,9 @@
   // of entries generated and the index of the first has_bit entry.
   std::pair<size_t, size_t> GenerateOffsets(io::Printer* printer);
   void GenerateSchema(io::Printer* printer, int offset, int has_offset);
+  // For each field generates a table entry describing the field for the
+  // table driven serializer.
+  int GenerateFieldMetadata(io::Printer* printer);
 
   // Generate constructors and destructor.
   void GenerateStructors(io::Printer* printer);
@@ -147,6 +146,13 @@
   // Generate the arena-specific destructor code.
   void GenerateArenaDestructorCode(io::Printer* printer);
 
+  // Helper for GenerateClear and others.  Optionally emits a condition that
+  // assumes the existence of the cached_has_bits variable, and returns true if
+  // the condition was printed.
+  bool MaybeGenerateOptionalFieldCondition(io::Printer* printer,
+                                           const FieldDescriptor* field,
+                                           int expected_has_bits_index);
+
   // Generate standard Message methods.
   void GenerateClear(io::Printer* printer);
   void GenerateOneofClear(io::Printer* printer);
@@ -179,7 +185,6 @@
       io::Printer* printer, const Descriptor::ExtensionRange* range,
       bool unbounded);
 
-
   // Generates has_foo() functions and variables for singular field has-bits.
   void GenerateSingularFieldHasBits(const FieldDescriptor* field,
                                     std::map<string, string> vars,
diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
index fc3c456..da4c395 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -50,6 +50,8 @@
                          const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = FieldMessageTypeName(descriptor);
+  (*variables)["type_default_instance"] =
+      DefaultInstanceName(descriptor->message_type());
   if (descriptor->options().weak() || !descriptor->containing_oneof()) {
     (*variables)["non_null_ptr_to_name"] =
         StrCat("this->", (*variables)["name"], "_");
@@ -98,6 +100,7 @@
 GenerateGetterDeclaration(io::Printer* printer) const {
   printer->Print(variables_,
       "$deprecated_attr$const $type$& $name$() const;\n");
+  printer->Annotate("name", descriptor_);
 }
 
 void MessageFieldGenerator::
@@ -107,9 +110,14 @@
   }
   // Arena manipulation code is out-of-line in the derived message class.
   printer->Print(variables_,
-    "$deprecated_attr$$type$* mutable_$name$();\n"
-    "$deprecated_attr$$type$* $release_name$();\n"
-    "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
+                 "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n");
+  printer->Annotate("release_name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_allocated_$name$$}$"
+                 "($type$* $name$);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void MessageFieldGenerator::
@@ -130,15 +138,25 @@
   GenerateGetterDeclaration(printer);
   if (!dependent_field_) {
     printer->Print(variables_,
-      "$deprecated_attr$$type$* mutable_$name$();\n"
-      "$deprecated_attr$$type$* $release_name$();\n"
-      "$deprecated_attr$void set_allocated_$name$($type$* $name$);\n");
+                   "$deprecated_attr$$type$* ${$mutable_$name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    printer->Print(variables_, "$deprecated_attr$$type$* $release_name$();\n");
+    printer->Annotate("release_name", descriptor_);
+    printer->Print(variables_,
+                   "$deprecated_attr$void ${$set_allocated_$name$$}$"
+                   "($type$* $name$);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportsArenas(descriptor_)) {
+    printer->Print(
+        variables_,
+        "$deprecated_attr$$type$* ${$unsafe_arena_release_$name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     printer->Print(variables_,
-      "$deprecated_attr$$type$* unsafe_arena_release_$name$();\n"
-      "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
-      "    $type$* $name$);\n");
+                   "$deprecated_attr$void "
+                   "${$unsafe_arena_set_allocated_$name$$}$(\n"
+                   "    $type$* $name$);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -346,30 +364,18 @@
 void MessageFieldGenerator::
 GenerateInlineAccessorDefinitions(io::Printer* printer,
                                   bool is_inline) const {
-  if (dependent_field_) {
-    // for dependent fields we cannot access its internal_default_instance,
-    // because the type is incomplete.
-    // TODO(gerbens) deprecate dependent base class.
-    std::map<string, string> variables(variables_);
-    variables["inline"] = is_inline ? "inline " : "";
-    printer->Print(variables,
-      "$inline$const $type$& $classname$::$name$() const {\n"
-      "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-      "  return $name$_ != NULL ? *$name$_\n"
-      "                         : *internal_default_instance()->$name$_;\n"
-      "}\n");
-    return;
-  }
-
   std::map<string, string> variables(variables_);
   variables["inline"] = is_inline ? "inline " : "";
   printer->Print(variables,
     "$inline$const $type$& $classname$::$name$() const {\n"
+    "  const $type$* p = $name$_;\n"
     "  // @@protoc_insertion_point(field_get:$full_name$)\n"
-    "  return $name$_ != NULL ? *$name$_\n"
-    "                         : *$type$::internal_default_instance();\n"
+    "  return p != NULL ? *p : *reinterpret_cast<const $type$*>(\n"
+    "      &$type_default_instance$);\n"
     "}\n");
 
+  if (dependent_field_) return;
+
   if (SupportsArenas(descriptor_)) {
     printer->Print(variables,
       "$inline$"
@@ -511,18 +517,18 @@
 
 void MessageFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
 }
 
 void MessageFieldGenerator::
 GenerateDestructorCode(io::Printer* printer) const {
+  // TODO(gerbens) Remove this when we don't need to destruct default instances.
   // In google3 a default instance will never get deleted so we don't need to
   // worry about that but in opensource protobuf default instances are deleted
   // in shutdown process and we need to take special care when handling them.
   printer->Print(variables_,
-    "if (this != internal_default_instance()) {\n"
-    "  delete $name$_;\n"
-    "}\n");
+    "if (this != internal_default_instance()) ");
+  printer->Print(variables_, "delete $name$_;\n");
 }
 
 void MessageFieldGenerator::
@@ -899,16 +905,20 @@
 void RepeatedMessageFieldGenerator::
 InternalGenerateTypeDependentAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "$deprecated_attr$$type$* mutable_$name$(int index);\n"
-    "$deprecated_attr$$type$* add_$name$();\n");
+                 "$deprecated_attr$$type$* ${$mutable_$name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_, "$deprecated_attr$$type$* ${$add_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (dependent_getter_) {
     printer->Print(variables_,
       "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
       "    $name$() const;\n");
+    printer->Annotate("name", descriptor_);
   }
   printer->Print(variables_,
-    "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
-    "    mutable_$name$();\n");
+                 "$deprecated_attr$::google::protobuf::RepeatedPtrField< $type$ >*\n"
+                 "    ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedMessageFieldGenerator::
@@ -916,6 +926,7 @@
   if (dependent_getter_) {
     printer->Print(variables_,
       "$deprecated_attr$const $type$& $name$(int index) const;\n");
+    printer->Annotate("name", descriptor_);
   }
   if (dependent_field_) {
     InternalGenerateTypeDependentAccessorDeclarations(printer);
@@ -927,6 +938,7 @@
   if (!dependent_getter_) {
     printer->Print(variables_,
       "$deprecated_attr$const $type$& $name$(int index) const;\n");
+    printer->Annotate("name", descriptor_);
   }
   if (!dependent_field_) {
     InternalGenerateTypeDependentAccessorDeclarations(printer);
@@ -935,6 +947,7 @@
     printer->Print(variables_,
       "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
       "    $name$() const;\n");
+    printer->Annotate("name", descriptor_);
   }
 }
 
@@ -1084,19 +1097,21 @@
 void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizes(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
+    "for (unsigned int i = 0,\n"
+    "    n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
     "  ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
-    "    $number$, this->$name$(i), output);\n"
+    "    $number$, this->$name$(static_cast<int>(i)), output);\n"
     "}\n");
 }
 
 void RepeatedMessageFieldGenerator::
 GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
   printer->Print(variables_,
-    "for (unsigned int i = 0, n = this->$name$_size(); i < n; i++) {\n"
+    "for (unsigned int i = 0,\n"
+    "    n = static_cast<unsigned int>(this->$name$_size()); i < n; i++) {\n"
     "  target = ::google::protobuf::internal::WireFormatLite::\n"
     "    InternalWrite$declared_type$NoVirtualToArray(\n"
-    "      $number$, this->$name$(i), deterministic, target);\n"
+    "      $number$, this->$name$(static_cast<int>(i)), deterministic, target);\n"
     "}\n");
 }
 
@@ -1104,14 +1119,14 @@
 GenerateByteSize(io::Printer* printer) const {
   printer->Print(variables_,
     "{\n"
-    "  unsigned int count = this->$name$_size();\n");
+    "  unsigned int count = static_cast<unsigned int>(this->$name$_size());\n");
   printer->Indent();
   printer->Print(variables_,
     "total_size += $tag_size$UL * count;\n"
     "for (unsigned int i = 0; i < count; i++) {\n"
     "  total_size +=\n"
     "    ::google::protobuf::internal::WireFormatLite::$declared_type$SizeNoVirtual(\n"
-    "      this->$name$(i));\n"
+    "      this->$name$(static_cast<int>(i)));\n"
     "}\n");
   printer->Outdent();
   printer->Print("}\n");
diff --git a/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
new file mode 100644
index 0000000..f72a7d6
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_move_unittest.cc
@@ -0,0 +1,169 @@
+// 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/stubs/common.h>
+#include <google/protobuf/test_util.h>
+#include <google/protobuf/unittest.pb.h>
+#include <gtest/gtest.h>
+
+#if LANG_CXX11
+#include <google/protobuf/stubs/type_traits.h>
+#endif
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+
+// Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
+namespace cpp_unittest {
+
+// Moves are enabled only when compiling with a C++11 compiler or newer.
+#if LANG_CXX11
+
+TEST(MovableMessageTest, MoveConstructor) {
+  protobuf_unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+  const auto* nested = &message1.optional_nested_message();
+
+  protobuf_unittest::TestAllTypes message2(std::move(message1));
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Check if the optional_nested_message was actually moved (and not just
+  // copied).
+  EXPECT_EQ(nested, &message2.optional_nested_message());
+  EXPECT_NE(nested, &message1.optional_nested_message());
+}
+
+TEST(MovableMessageTest, MoveAssignmentOperator) {
+  protobuf_unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+  const auto* nested = &message1.optional_nested_message();
+
+  protobuf_unittest::TestAllTypes message2;
+  message2 = std::move(message1);
+  TestUtil::ExpectAllFieldsSet(message2);
+
+  // Check if the optional_nested_message was actually moved (and not just
+  // copied).
+  EXPECT_EQ(nested, &message2.optional_nested_message());
+  EXPECT_NE(nested, &message1.optional_nested_message());
+}
+
+TEST(MovableMessageTest, SelfMoveAssignment) {
+  // The `self` reference is necessary to defeat -Wself-move.
+  protobuf_unittest::TestAllTypes message, &self = message;
+  TestUtil::SetAllFields(&message);
+  message = std::move(self);
+  TestUtil::ExpectAllFieldsSet(message);
+}
+
+TEST(MovableMessageTest, MoveSameArena) {
+  Arena arena;
+
+  auto* message1_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+  TestUtil::SetAllFields(message1_on_arena);
+  const auto* nested = &message1_on_arena->optional_nested_message();
+
+  auto* message2_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+
+  // Moving messages on the same arena should lead to swapped pointers.
+  *message2_on_arena = std::move(*message1_on_arena);
+  EXPECT_EQ(nested, &message2_on_arena->optional_nested_message());
+}
+
+TEST(MovableMessageTest, MoveDifferentArenas) {
+  Arena arena1, arena2;
+
+  auto* message1_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena1);
+  TestUtil::SetAllFields(message1_on_arena);
+  const auto* nested = &message1_on_arena->optional_nested_message();
+
+  auto* message2_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena2);
+
+  // Moving messages on two different arenas should lead to a copy.
+  *message2_on_arena = std::move(*message1_on_arena);
+  EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
+  TestUtil::ExpectAllFieldsSet(*message1_on_arena);
+  TestUtil::ExpectAllFieldsSet(*message2_on_arena);
+}
+
+TEST(MovableMessageTest, MoveFromArena) {
+  Arena arena;
+
+  auto* message1_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+  TestUtil::SetAllFields(message1_on_arena);
+  const auto* nested = &message1_on_arena->optional_nested_message();
+
+  protobuf_unittest::TestAllTypes message2;
+
+  // Moving from a message on the arena should lead to a copy.
+  message2 = std::move(*message1_on_arena);
+  EXPECT_NE(nested, &message2.optional_nested_message());
+  TestUtil::ExpectAllFieldsSet(*message1_on_arena);
+  TestUtil::ExpectAllFieldsSet(message2);
+}
+
+TEST(MovableMessageTest, MoveToArena) {
+  Arena arena;
+
+  protobuf_unittest::TestAllTypes message1;
+  TestUtil::SetAllFields(&message1);
+  const auto* nested = &message1.optional_nested_message();
+
+  auto* message2_on_arena =
+      Arena::CreateMessage<protobuf_unittest::TestAllTypes>(&arena);
+
+  // Moving to a message on the arena should lead to a copy.
+  *message2_on_arena = std::move(message1);
+  EXPECT_NE(nested, &message2_on_arena->optional_nested_message());
+  TestUtil::ExpectAllFieldsSet(message1);
+  TestUtil::ExpectAllFieldsSet(*message2_on_arena);
+}
+
+TEST(MovableMessageTest, Noexcept) {
+  EXPECT_TRUE(
+      std::is_nothrow_move_constructible<protobuf_unittest::TestAllTypes>());
+  EXPECT_TRUE(std::is_nothrow_move_assignable<protobuf_unittest::TestAllTypes>());
+}
+
+#endif  // LANG_CXX11
+
+}  // namespace cpp_unittest
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
index bdaa12a..0433808 100644
--- a/src/google/protobuf/compiler/cpp/cpp_options.h
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -49,7 +49,8 @@
         transitive_pb_h(true),
         annotate_headers(false),
         enforce_lite(false),
-        table_driven_parsing(false) {}
+        table_driven_parsing(false),
+        table_driven_serialization(false) {}
 
   string dllexport_decl;
   bool safe_boundary_check;
@@ -58,6 +59,7 @@
   bool annotate_headers;
   bool enforce_lite;
   bool table_driven_parsing;
+  bool table_driven_serialization;
   string annotation_pragma_name;
   string annotation_guard_name;
 };
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index 020c194..b05fcc4 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -115,9 +115,11 @@
 
 void PrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_, "$deprecated_attr$$type$ $name$() const;\n");
+  printer->Annotate("name", descriptor_);
   printer->Print(variables_,
-    "$deprecated_attr$$type$ $name$() const;\n"
-    "$deprecated_attr$void set_$name$($type$ value);\n");
+                 "$deprecated_attr$void ${$set_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void PrimitiveFieldGenerator::
@@ -148,7 +150,7 @@
 
 void PrimitiveFieldGenerator::
 GenerateSwappingCode(io::Printer* printer) const {
-  printer->Print(variables_, "std::swap($name$_, other->$name$_);\n");
+  printer->Print(variables_, "swap($name$_, other->$name$_);\n");
 }
 
 void PrimitiveFieldGenerator::
@@ -290,14 +292,23 @@
 void RepeatedPrimitiveFieldGenerator::
 GenerateAccessorDeclarations(io::Printer* printer) const {
   printer->Print(variables_,
-    "$deprecated_attr$$type$ $name$(int index) const;\n"
-    "$deprecated_attr$void set_$name$(int index, $type$ value);\n"
-    "$deprecated_attr$void add_$name$($type$ value);\n");
+                 "$deprecated_attr$$type$ $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(int index, $type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(variables_,
-    "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
-    "    $name$() const;\n"
-    "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
-    "    mutable_$name$();\n");
+                 "$deprecated_attr$void ${$add_$name$$}$($type$ value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$const ::google::protobuf::RepeatedField< $type$ >&\n"
+                 "    $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedField< $type$ >*\n"
+                 "    ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedPrimitiveFieldGenerator::
@@ -316,8 +327,7 @@
     "$inline$void $classname$::add_$name$($type$ value) {\n"
     "  $name$_.Add(value);\n"
     "  // @@protoc_insertion_point(field_add:$full_name$)\n"
-    "}\n");
-  printer->Print(variables,
+    "}\n"
     "$inline$const ::google::protobuf::RepeatedField< $type$ >&\n"
     "$classname$::$name$() const {\n"
     "  // @@protoc_insertion_point(field_list:$full_name$)\n"
@@ -382,7 +392,8 @@
           "$number$, "
           "::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, "
           "output);\n"
-      "  output->WriteVarint32(_$name$_cached_byte_size_);\n");
+      "  output->WriteVarint32(static_cast< ::google::protobuf::uint32>(\n"
+      "      _$name$_cached_byte_size_));\n");
 
     if (FixedSize(descriptor_->type()) > 0) {
       // TODO(ckennelly): Use RepeatedField<T>::unsafe_data() via
@@ -422,7 +433,8 @@
       "    ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,\n"
       "    target);\n"
       "  target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(\n"
-      "    _$name$_cached_byte_size_, target);\n"
+      "      static_cast< ::google::protobuf::uint32>(\n"
+      "          _$name$_cached_byte_size_), target);\n"
       "  target = ::google::protobuf::internal::WireFormatLite::\n"
       "    Write$declared_type$NoTagToArray(this->$name$_, target);\n"
       "}\n");
@@ -444,7 +456,7 @@
       "  $declared_type$Size(this->$name$_);\n");
   } else {
     printer->Print(variables_,
-      "unsigned int count = this->$name$_size();\n"
+      "unsigned int count = static_cast<unsigned int>(this->$name$_size());\n"
       "size_t data_size = $fixed_size$UL * count;\n");
   }
 
@@ -452,7 +464,8 @@
     printer->Print(variables_,
       "if (data_size > 0) {\n"
       "  total_size += $tag_size$ +\n"
-      "    ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);\n"
+      "    ::google::protobuf::internal::WireFormatLite::Int32Size(\n"
+      "        static_cast< ::google::protobuf::int32>(data_size));\n"
       "}\n"
       "int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);\n"
       "GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 7a849e2..fec13b6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -142,28 +142,47 @@
   }
 
   printer->Print(variables_,
-    "$deprecated_attr$const ::std::string& $name$() const;\n"
-    "$deprecated_attr$void set_$name$(const ::std::string& value);\n");
-
-  if (!SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "#if LANG_CXX11\n"
-      "$deprecated_attr$void set_$name$(::std::string&& value);\n"
-      "#endif\n");
-  }
+                 "$deprecated_attr$const ::std::string& $name$() const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(const ::std::string& value);\n");
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Print(variables_,
-    "$deprecated_attr$void set_$name$(const char* value);\n"
-    "$deprecated_attr$void set_$name$(const $pointer_type$* value, size_t size)"
-                 ";\n"
-    "$deprecated_attr$::std::string* mutable_$name$();\n"
-    "$deprecated_attr$::std::string* $release_name$();\n"
-    "$deprecated_attr$void set_allocated_$name$(::std::string* $name$);\n");
+                 "#if LANG_CXX11\n"
+                 "$deprecated_attr$void ${$set_$name$$}$(::std::string&& value);\n"
+                 "#endif\n");
+  printer->Annotate("{", "}", descriptor_);
+
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_$name$$}$(const char* value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_$name$$}$(const $pointer_type$* "
+                 "value, size_t size)"
+                 ";\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::std::string* ${$mutable_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_, "$deprecated_attr$::std::string* $release_name$();\n");
+  printer->Annotate("release_name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$set_allocated_$name$$}$(::std::string* $name$);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportsArenas(descriptor_)) {
-    printer->Print(variables_,
-      "$deprecated_attr$::std::string* unsafe_arena_release_$name$();\n"
-      "$deprecated_attr$void unsafe_arena_set_allocated_$name$(\n"
-      "    ::std::string* $name$);\n");
+    printer->Print(
+        variables_,
+        "$deprecated_attr$::std::string* ${$unsafe_arena_release_$name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecated_attr$void ${$unsafe_arena_set_allocated_$name$$}$(\n"
+        "    ::std::string* $name$);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
 
@@ -191,6 +210,14 @@
         "  $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n"
         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
         "}\n"
+        "#if LANG_CXX11\n"
+        "$inline$void $classname$::set_$name$(::std::string&& value) {\n"
+        "  $set_hasbit$\n"
+        "  $name$_.Set(\n"
+        "    $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+        "}\n"
+        "#endif\n"
         "$inline$void $classname$::set_$name$(const char* value) {\n"
         "  $null_check$"
         "  $set_hasbit$\n"
@@ -456,15 +483,10 @@
     printer->Print(variables_,
                    "$classname$::$default_variable_name$.DefaultConstruct();\n"
                    "*$classname$::$default_variable_name$.get_mutable() = "
-                   "::std::string($default$, $default_length$);\n");
-  }
-}
-
-void StringFieldGenerator::
-GenerateShutdownCode(io::Printer* printer) const {
-  if (!descriptor_->default_value_string().empty()) {
-    printer->Print(variables_,
-                   "$classname$::$default_variable_name$.Shutdown();\n");
+                   "::std::string($default$, $default_length$);\n"
+                   "::google::protobuf::internal::OnShutdownDestroyString(\n"
+                   "    $classname$::$default_variable_name$.get_mutable());\n"
+                   );
   }
 }
 
@@ -477,7 +499,8 @@
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, true, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
 }
 
@@ -486,7 +509,8 @@
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, false, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
   printer->Print(variables_,
     "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
@@ -498,7 +522,8 @@
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, false, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
   printer->Print(variables_,
     "target =\n"
@@ -551,6 +576,19 @@
         "      GetArenaNoVirtual());\n"
         "  // @@protoc_insertion_point(field_set:$full_name$)\n"
         "}\n"
+        "#if LANG_CXX11\n"
+        "$inline$void $classname$::set_$name$(::std::string&& value) {\n"
+        "  // @@protoc_insertion_point(field_set:$full_name$)\n"
+        "  if (!has_$name$()) {\n"
+        "    clear_$oneof_name$();\n"
+        "    set_has_$name$();\n"
+        "    $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n"
+        "  }\n"
+        "  $oneof_prefix$$name$_.Set(\n"
+        "    $default_variable$, ::std::move(value), GetArenaNoVirtual());\n"
+        "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
+        "}\n"
+        "#endif\n"
         "$inline$void $classname$::set_$name$(const char* value) {\n"
         "  $null_check$"
         "  if (!has_$name$()) {\n"
@@ -797,7 +835,8 @@
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, true, variables_,
-        "this->$name$().data(), this->$name$().length(),\n", printer);
+        "this->$name$().data(), static_cast<int>(this->$name$().length()),\n",
+        printer);
   }
 }
 
@@ -833,28 +872,62 @@
   }
 
   printer->Print(variables_,
-    "$deprecated_attr$const ::std::string& $name$(int index) const;\n"
-    "$deprecated_attr$::std::string* mutable_$name$(int index);\n"
-    "$deprecated_attr$void set_$name$(int index, const ::std::string& value);\n"
-    "#if LANG_CXX11\n"
-    "$deprecated_attr$void set_$name$(int index, ::std::string&& value);\n"
-    "#endif\n"
-    "$deprecated_attr$void set_$name$(int index, const char* value);\n"
-    ""
-    "$deprecated_attr$void set_$name$("
-                 "int index, const $pointer_type$* value, size_t size);\n"
-    "$deprecated_attr$::std::string* add_$name$();\n"
-    "$deprecated_attr$void add_$name$(const ::std::string& value);\n"
-    "#if LANG_CXX11\n"
-    "$deprecated_attr$void add_$name$(::std::string&& value);\n"
-    "#endif\n"
-    "$deprecated_attr$void add_$name$(const char* value);\n"
-    "$deprecated_attr$void add_$name$(const $pointer_type$* value, size_t size)"
-                 ";\n"
-    "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
-                 "const;\n"
-    "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+                 "$deprecated_attr$const ::std::string& $name$(int index) const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$::std::string* ${$mutable_$name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_$name$$}$(int index, const "
+                 "::std::string& value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "#if LANG_CXX11\n"
+      "$deprecated_attr$void ${$set_$name$$}$(int index, ::std::string&& value);\n"
+      "#endif\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$set_$name$$}$(int index, const "
+                 "char* value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 ""
+                 "$deprecated_attr$void ${$set_$name$$}$("
+                 "int index, const $pointer_type$* value, size_t size);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::std::string* ${$add_$name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$add_$name$$}$(const ::std::string& value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "#if LANG_CXX11\n"
+                 "$deprecated_attr$void ${$add_$name$$}$(::std::string&& value);\n"
+                 "#endif\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$void ${$add_$name$$}$(const char* value);\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$void ${$add_$name$$}$(const $pointer_type$* "
+                 "value, size_t size)"
                  ";\n");
+  printer->Annotate("{", "}", descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecated_attr$const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() "
+      "const;\n");
+  printer->Annotate("name", descriptor_);
+  printer->Print(variables_,
+                 "$deprecated_attr$::google::protobuf::RepeatedPtrField< ::std::string>* "
+                 "${$mutable_$name$$}$()"
+                 ";\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (unknown_ctype) {
     printer->Outdent();
@@ -969,7 +1042,7 @@
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, true, variables_,
         "this->$name$(this->$name$_size() - 1).data(),\n"
-        "this->$name$(this->$name$_size() - 1).length(),\n",
+        "static_cast<int>(this->$name$(this->$name$_size() - 1).length()),\n",
         printer);
   }
 }
@@ -982,7 +1055,8 @@
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, false, variables_,
-        "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
+        "this->$name$(i).data(), static_cast<int>(this->$name$(i).length()),\n",
+        printer);
   }
   printer->Outdent();
   printer->Print(variables_,
@@ -999,7 +1073,8 @@
   if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
     GenerateUtf8CheckCodeForString(
         descriptor_, options_, false, variables_,
-        "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
+        "this->$name$(i).data(), static_cast<int>(this->$name$(i).length()),\n",
+        printer);
   }
   printer->Outdent();
   printer->Print(variables_,
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
index af263c1..531252b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h
@@ -65,7 +65,6 @@
   void GenerateCopyConstructorCode(io::Printer* printer) const;
   void GenerateDestructorCode(io::Printer* printer) const;
   void GenerateDefaultInstanceAllocator(io::Printer* printer) const;
-  void GenerateShutdownCode(io::Printer* printer) const;
   void GenerateMergeFromCodedStream(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizes(io::Printer* printer) const;
   void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index e56964c..fdde771 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -576,12 +576,73 @@
   EXPECT_EQ(unittest::TestAllTypes::BAR, message2.repeated_nested_enum(1));
 }
 
-TEST(GeneratedMessageTest, CopyConstructor) {
-  unittest::TestAllTypes message1;
+TEST(GeneratedMessageTest, ADLSwap) {
+  unittest::TestAllTypes message1, message2;
   TestUtil::SetAllFields(&message1);
 
-  unittest::TestAllTypes message2(message1);
+  // Note the address of one of the repeated fields, to verify it was swapped
+  // rather than copied.
+  const int32* addr = &message1.repeated_int32().Get(0);
+
+  using std::swap;
+  swap(message1, message2);
+
   TestUtil::ExpectAllFieldsSet(message2);
+  TestUtil::ExpectClear(message1);
+
+  EXPECT_EQ(addr, &message2.repeated_int32().Get(0));
+}
+
+TEST(GeneratedMessageTest, CopyConstructor) {
+  // All set.
+  {
+    unittest::TestAllTypes message1;
+    TestUtil::SetAllFields(&message1);
+
+    unittest::TestAllTypes message2(message1);
+    TestUtil::ExpectAllFieldsSet(message2);
+  }
+
+  // None set.
+  {
+    unittest::TestAllTypes message1;
+    unittest::TestAllTypes message2(message1);
+
+    EXPECT_FALSE(message1.has_optional_string());
+    EXPECT_FALSE(message2.has_optional_string());
+    EXPECT_EQ(&message1.optional_string(),
+              &message2.optional_string());
+
+    EXPECT_FALSE(message1.has_optional_bytes());
+    EXPECT_FALSE(message2.has_optional_bytes());
+    EXPECT_EQ(&message1.optional_bytes(),
+              &message2.optional_bytes());
+
+    EXPECT_FALSE(message1.has_optional_nested_message());
+    EXPECT_FALSE(message2.has_optional_nested_message());
+    EXPECT_EQ(&message1.optional_nested_message(),
+              &message2.optional_nested_message());
+
+    EXPECT_FALSE(message1.has_optional_foreign_message());
+    EXPECT_FALSE(message2.has_optional_foreign_message());
+    EXPECT_EQ(&message1.optional_foreign_message(),
+              &message2.optional_foreign_message());
+
+    EXPECT_FALSE(message1.has_optional_import_message());
+    EXPECT_FALSE(message2.has_optional_import_message());
+    EXPECT_EQ(&message1.optional_import_message(),
+              &message2.optional_import_message());
+
+    EXPECT_FALSE(message1.has_optional_public_import_message());
+    EXPECT_FALSE(message2.has_optional_public_import_message());
+    EXPECT_EQ(&message1.optional_public_import_message(),
+              &message2.optional_public_import_message());
+
+    EXPECT_FALSE(message1.has_optional_lazy_message());
+    EXPECT_FALSE(message2.has_optional_lazy_message());
+    EXPECT_EQ(&message1.optional_lazy_message(),
+              &message2.optional_lazy_message());
+  }
 }
 
 TEST(GeneratedMessageTest, CopyConstructorWithArenas) {
@@ -1340,7 +1401,7 @@
       foo_(descriptor_->FindMethodByName("Foo")),
       bar_(descriptor_->FindMethodByName("Bar")),
       stub_(&mock_channel_),
-      done_(NewPermanentCallback(&DoNothing)) {}
+      done_(::google::protobuf::NewPermanentCallback(&DoNothing)) {}
 
   virtual void SetUp() {
     ASSERT_TRUE(foo_ != NULL);
diff --git a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
index 4e44b57..8c38e52 100644
--- a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
@@ -134,6 +134,14 @@
 };
 
 TEST(CsharpBootstrapTest, GeneratedCsharpDescriptorMatches) {
+  // Skip this whole test if the csharp directory doesn't exist (i.e., a C++11
+  // only distribution).
+  string descriptor_file_name =
+      "../csharp/src/Google.Protobuf/Reflection/Descriptor.cs";
+  if (!File::Exists(TestSourceDir() + "/" + descriptor_file_name)) {
+    return;
+  }
+
   MockErrorCollector error_collector;
   DiskSourceTree source_tree;
   Importer importer(&source_tree, &error_collector);
@@ -176,11 +184,6 @@
                     "../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
 
   generate_test.SetParameter("");
-  source_tree.MapPath("", TestSourceDir() + "/../examples");
-  generate_test.Run(importer.Import("addressbook.proto"),
-                    "Addressbook.cs",
-                    "../csharp/src/AddressBook/Addressbook.cs");
-
   source_tree.MapPath("", TestSourceDir() + "/../conformance");
   generate_test.Run(importer.Import("conformance.proto"),
                     "Conformance.cs",
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index ebb8fbc..ecf29ec 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -54,7 +54,7 @@
 namespace csharp {
 
 void FieldGeneratorBase::SetCommonFieldVariables(
-    map<string, string>* variables) {
+    std::map<string, string>* variables) {
   // Note: this will be valid even though the tag emitted for packed and unpacked versions of
   // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which
   // never effects the tag size.
@@ -92,7 +92,7 @@
 }
 
 void FieldGeneratorBase::SetCommonOneofFieldVariables(
-    map<string, string>* variables) {
+    std::map<string, string>* variables) {
   (*variables)["oneof_name"] = oneof_name();
   (*variables)["has_property_check"] =
     oneof_name() + "Case_ == " + oneof_property_name() +
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index 4109f3c..df26853 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -66,14 +66,14 @@
  protected:
   const FieldDescriptor* descriptor_;
   const int fieldOrdinal_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   void AddDeprecatedFlag(io::Printer* printer);
   void AddNullCheck(io::Printer* printer);
   void AddNullCheck(io::Printer* printer, const std::string& name);
 
   void AddPublicMemberAttributes(io::Printer* printer);
-  void SetCommonOneofFieldVariables(map<string, string>* variables);
+  void SetCommonOneofFieldVariables(std::map<string, string>* variables);
 
   std::string oneof_property_name();
   std::string oneof_name();
@@ -89,7 +89,7 @@
   std::string capitalized_type_name();
 
  private:
-  void SetCommonFieldVariables(map<string, string>* variables);
+  void SetCommonFieldVariables(std::map<string, string>* variables);
   std::string GetStringDefaultValueInternal();
   std::string GetBytesDefaultValueInternal();
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index 0f00a43..5ef0e4e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -105,7 +105,7 @@
 }
 
 void MessageGenerator::Generate(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["class_name"] = class_name();
   vars["access_level"] = class_access_level();
 
@@ -280,7 +280,7 @@
 }
 
 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   WriteGeneratedCodeAttributes(printer);
   vars["class_name"] = class_name();
     printer->Print(
@@ -333,7 +333,7 @@
 }
 
 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["class_name"] = class_name();
 
     // Equality
@@ -432,7 +432,7 @@
   // Note:  These are separate from GenerateMessageSerializationMethods()
   //   because they need to be generated even for messages that are optimized
   //   for code size.
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["class_name"] = class_name();
 
   WriteGeneratedCodeAttributes(printer);
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index 844edc1..4c357aa 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -32,8 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+
 #ifdef _MSC_VER
-#include <io.h>
+#include <direct.h>
 #else
 #include <unistd.h>
 #endif
@@ -53,19 +54,24 @@
 #include <google/protobuf/compiler/parser.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/strutil.h>
 
+#ifdef _WIN32
+#include <ctype.h>
+#endif
+
+#ifdef _MSC_VER
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::open;
+#endif
+
 namespace google {
 namespace protobuf {
 namespace compiler {
 
-#ifdef _WIN32
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
-#endif
-#include <ctype.h>
-#endif
-
 // Returns true if the text looks like a Windows-style absolute path, starting
 // with a drive letter.  Example:  "C:\foo".  TODO(kenton):  Share this with
 // copy in command_line_interface.cc?
@@ -295,10 +301,8 @@
 }
 
 static inline bool ContainsParentReference(const string& path) {
-  return path == ".." ||
-         HasPrefixString(path, "../") ||
-         HasSuffixString(path, "/..") ||
-         path.find("/../") != string::npos;
+  return path == ".." || HasPrefixString(path, "../") ||
+         HasSuffixString(path, "/..") || path.find("/../") != string::npos;
 }
 
 // Maps a file from an old location to a new one.  Typically, old_prefix is
@@ -328,8 +332,7 @@
       // We do not allow the file name to use "..".
       return false;
     }
-    if (HasPrefixString(filename, "/") ||
-        IsWindowsAbsolutePath(filename)) {
+    if (HasPrefixString(filename, "/") || IsWindowsAbsolutePath(filename)) {
       // This is an absolute path, so it isn't matched by the empty string.
       return false;
     }
diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
index b82fb3d..0771d5e 100644
--- a/src/google/protobuf/compiler/java/java_context.cc
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -50,7 +50,7 @@
 Context::~Context() {
 }
 
-ClassNameResolver* Context::GetNameResolver() {
+ClassNameResolver* Context::GetNameResolver() const {
   return name_resolver_.get();
 }
 
@@ -154,7 +154,7 @@
   for (int i = 0; i < fields.size(); ++i) {
     const FieldDescriptor* field = fields[i];
     FieldGeneratorInfo info;
-    info.name = UnderscoresToCamelCase(field);
+    info.name = CamelCaseFieldName(field);
     info.capitalized_name = UnderscoresToCapitalizedCamelCase(field);
     // For fields conflicting with some other fields, we append the field
     // number to their field names in generated code to avoid conflicts.
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
index b22e7e3..9a74c43 100644
--- a/src/google/protobuf/compiler/java/java_context.h
+++ b/src/google/protobuf/compiler/java/java_context.h
@@ -70,7 +70,7 @@
 
   // Get the name resolver associated with this context. The resolver
   // can be used to map descriptors to Java class names.
-  ClassNameResolver* GetNameResolver();
+  ClassNameResolver* GetNameResolver() const;
 
   // Get the FieldGeneratorInfo for a given field.
   const FieldGeneratorInfo* GetFieldGeneratorInfo(
diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
index b9ee00f..d125ebe 100644
--- a/src/google/protobuf/compiler/java/java_enum.cc
+++ b/src/google/protobuf/compiler/java/java_enum.cc
@@ -109,14 +109,16 @@
       printer->Print(vars,
         "$name$($index$, $number$),\n");
     }
+    printer->Annotate("name", canonical_values_[i]);
   }
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
     if (ordinal_is_index) {
-      printer->Print("UNRECOGNIZED(-1),\n");
+      printer->Print("${$UNRECOGNIZED$}$(-1),\n", "{", "", "}", "");
     } else {
-      printer->Print("UNRECOGNIZED(-1, -1),\n");
+      printer->Print("${$UNRECOGNIZED$}$(-1, -1),\n", "{", "", "}", "");
     }
+    printer->Annotate("{", "}", descriptor_);
   }
 
   printer->Print(
@@ -133,15 +135,19 @@
     WriteEnumValueDocComment(printer, aliases_[i].value);
     printer->Print(vars,
       "public static final $classname$ $name$ = $canonical_name$;\n");
+    printer->Annotate("name", aliases_[i].value);
   }
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
     std::map<string, string> vars;
     vars["name"] = descriptor_->value(i)->name();
     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    vars["{"] = "";
+    vars["}"] = "";
     WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
-      "public static final int $name$_VALUE = $number$;\n");
+      "public static final int ${$$name$_VALUE$}$ = $number$;\n");
+    printer->Annotate("{", "}", descriptor_->value(i));
   }
   printer->Print("\n");
 
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 279b9da..9f7bb34 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -183,23 +183,26 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  $type$ result = $type$.$for_number$($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldGenerator::
@@ -209,33 +212,38 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  $name$_ = value;\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  $type$ result = $type$.$for_number$($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
@@ -244,14 +252,16 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+    printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $clear_has_field_bit_builder$\n"
     "  $name$_ = $default_number$;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldGenerator::
@@ -311,12 +321,8 @@
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
       "$type$ value = $type$.$for_number$(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  unknownFields.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_has_field_bit_message$\n"
       "  $name$_ = rawValue;\n"
@@ -386,23 +392,25 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  if ($has_oneof_case_message$) {\n"
       "    return (java.lang.Integer) $oneof_name$_;\n"
       "  }\n"
       "  return $default_number$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $type$ result = $type$.$for_number$(\n"
     "        (java.lang.Integer) $oneof_name$_);\n"
@@ -410,6 +418,7 @@
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumOneofFieldGenerator::
@@ -417,31 +426,35 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  if ($has_oneof_case_message$) {\n"
       "    return ((java.lang.Integer) $oneof_name$_).intValue();\n"
       "  }\n"
       "  return $default_number$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  $set_oneof_case_message$;\n"
       "  $oneof_name$_ = value;\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $type$ result = $type$.$for_number$(\n"
     "        (java.lang.Integer) $oneof_name$_);\n"
@@ -449,9 +462,10 @@
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
@@ -460,9 +474,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
@@ -470,6 +485,7 @@
     "  }\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumOneofFieldGenerator::
@@ -502,12 +518,8 @@
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
       "$type$ value = $type$.$for_number$(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  unknownFields.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_oneof_case_message$;\n"
       "  $oneof_name$_ = rawValue;\n"
@@ -621,32 +633,38 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return new com.google.protobuf.Internal.ListAdapter<\n"
     "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_converter_.convert($name$_.get(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return $name$_.get(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   if (descriptor_->is_packed() &&
@@ -684,23 +702,27 @@
     //   could hold on to the returned list and modify it after the message
     //   has been built, thus mutating the message which is supposed to be
     //   immutable.
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return new com.google.protobuf.Internal.ListAdapter<\n"
     "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_converter_.convert($name$_.get(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
@@ -710,9 +732,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  if (value == null) {\n"
     "    throw new NullPointerException();\n"
     "  }\n"
@@ -721,9 +744,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  for ($type$ value : values) {\n"
@@ -732,47 +756,54 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $name$_ = java.util.Collections.emptyList();\n"
     "  $clear_mutable_bit_builder$;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return java.util.Collections.unmodifiableList($name$_);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return $name$_.get(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
       "    int index, int value) {\n"
       "  ensure$capitalized_name$IsMutable();\n"
       "  $name$_.set(index, value);\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$add$capitalized_name$Value$}$(int value) {\n"
       "  ensure$capitalized_name$IsMutable();\n"
       "  $name$_.add(value);\n"
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
       "    java.lang.Iterable<java.lang.Integer> values) {\n"
       "  ensure$capitalized_name$IsMutable();\n"
       "  for (int value : values) {\n"
@@ -781,6 +812,7 @@
       "  $on_changed$\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -848,12 +880,8 @@
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
       "$type$ value = $type$.$for_number$(rawValue);\n"
-        "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  unknownFields.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  unknownFields.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  if (!$get_mutable_bit_parser$) {\n"
       "    $name$_ = new java.util.ArrayList<java.lang.Integer>();\n"
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index 1eefdcf..a4de1e2 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -165,23 +165,26 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  $type$ result = $type$.forNumber($name$_);\n"
     "  return result == null ? $unknown$ : result;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Generate private setters for the builder to proxy into.
   if (SupportUnknownEnumValue(descriptor_->file())) {
@@ -214,43 +217,50 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return instance.get$capitalized_name$Value();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  copyOnWrite();\n"
       "  instance.set$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldLiteGenerator::
@@ -296,12 +306,8 @@
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
       "$type$ value = $type$.forNumber(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  super.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  super.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_has_field_bit_message$\n"
       "  $name$_ = rawValue;\n"
@@ -372,29 +378,32 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  if ($has_oneof_case_message$) {\n"
       "    return (java.lang.Integer) $oneof_name$_;\n"
       "  }\n"
       "  return $default_number$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $type$ result = $type$.forNumber((java.lang.Integer) $oneof_name$_);\n"
     "    return result == null ? $unknown$ : result;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Generate private setters for the builder to proxy into.
   if (SupportUnknownEnumValue(descriptor_->file())) {
@@ -430,43 +439,50 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value() {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$() {\n"
       "  return instance.get$capitalized_name$Value();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$set$capitalized_name$Value$}$(int value) {\n"
       "  copyOnWrite();\n"
       "  instance.set$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumOneofFieldLiteGenerator::
@@ -487,12 +503,8 @@
     printer->Print(variables_,
       "int rawValue = input.readEnum();\n"
       "$type$ value = $type$.forNumber(rawValue);\n"
-      "if (value == null) {\n");
-    if (PreserveUnknownFields(descriptor_->containing_type())) {
-      printer->Print(variables_,
-        "  super.mergeVarintField($number$, rawValue);\n");
-    }
-    printer->Print(variables_,
+      "if (value == null) {\n"
+      "  super.mergeVarintField($number$, rawValue);\n"
       "} else {\n"
       "  $set_oneof_case_message$;\n"
       "  $oneof_name$_ = rawValue;\n"
@@ -607,35 +619,41 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return new com.google.protobuf.Internal.ListAdapter<\n"
     "      java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_converter_.convert($name$_.getInt(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return $name$_.getInt(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
-  if (descriptor_->options().packed() &&
+  if (descriptor_->is_packed() &&
       context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize;\n");
@@ -714,85 +732,99 @@
 GenerateBuilderMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return instance.get$capitalized_name$List();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public java.util.List<java.lang.Integer>\n"
-      "get$capitalized_name$ValueList() {\n"
+      "${$get$capitalized_name$ValueList$}$() {\n"
       "  return java.util.Collections.unmodifiableList(\n"
       "      instance.get$capitalized_name$ValueList());\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public int get$capitalized_name$Value(int index) {\n"
+      "$deprecation$public int ${$get$capitalized_name$Value$}$(int index) {\n"
       "  return instance.get$capitalized_name$Value(index);\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder set$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$set$capitalized_name$Value$}$(\n"
       "    int index, int value) {\n"
       "  copyOnWrite();\n"
       "  instance.set$capitalized_name$Value(index, value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder add$capitalized_name$Value(int value) {\n"
+      "$deprecation$public Builder "
+      "${$add$capitalized_name$Value$}$(int value) {\n"
       "  instance.add$capitalized_name$Value(value);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public Builder addAll$capitalized_name$Value(\n"
+      "$deprecation$public Builder ${$addAll$capitalized_name$Value$}$(\n"
       "    java.lang.Iterable<java.lang.Integer> values) {\n"
       "  copyOnWrite();\n"
       "  instance.addAll$capitalized_name$Value(values);\n"
       "  return this;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -889,7 +921,7 @@
 
 void RepeatedImmutableEnumFieldLiteGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (get$capitalized_name$List().size() > 0) {\n"
       "  output.writeUInt32NoTag($tag$);\n"
@@ -920,7 +952,7 @@
     "}\n");
   printer->Print(
     "size += dataSize;\n");
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (!get$capitalized_name$List().isEmpty()) {"
       "  size += $tag_size$;\n"
@@ -933,7 +965,7 @@
   }
 
   // cache the data size for packed fields.
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "$name$MemoizedSerializedSize = dataSize;\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
index 38b054e..ab3b332 100644
--- a/src/google/protobuf/compiler/java/java_enum_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_lite.cc
@@ -93,10 +93,12 @@
     }
     printer->Print(vars,
       "$name$($number$),\n");
+    printer->Annotate("name", canonical_values_[i]);
   }
 
   if (SupportUnknownEnumValue(descriptor_->file())) {
-    printer->Print("UNRECOGNIZED(-1),\n");
+    printer->Print("${$UNRECOGNIZED$}$(-1),\n", "{", "", "}", "");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   printer->Print(
@@ -113,15 +115,19 @@
     WriteEnumValueDocComment(printer, aliases_[i].value);
     printer->Print(vars,
       "public static final $classname$ $name$ = $canonical_name$;\n");
+    printer->Annotate("name", aliases_[i].value);
   }
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
     std::map<string, string> vars;
     vars["name"] = descriptor_->value(i)->name();
     vars["number"] = SimpleItoa(descriptor_->value(i)->number());
+    vars["{"] = "";
+    vars["}"] = "";
     WriteEnumValueDocComment(printer, descriptor_->value(i));
     printer->Print(vars,
-      "public static final int $name$_VALUE = $number$;\n");
+      "public static final int ${$$name$_VALUE$}$ = $number$;\n");
+    printer->Annotate("{", "}", descriptor_->value(i));
   }
   printer->Print("\n");
 
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index cb237bf..9b9be55 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -75,7 +75,7 @@
   vars["default"] = descriptor->is_repeated() ?
       "" : DefaultValue(descriptor, immutable, name_resolver);
   vars["type_constant"] = FieldTypeName(GetType(descriptor));
-  vars["packed"] = descriptor->options().packed() ? "true" : "false";
+  vars["packed"] = descriptor->is_packed() ? "true" : "false";
   vars["enum_map"] = "null";
   vars["prototype"] = "null";
 
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
index 0491729..1ab1862 100644
--- a/src/google/protobuf/compiler/java/java_field.cc
+++ b/src/google/protobuf/compiler/java/java_field.cc
@@ -45,8 +45,6 @@
 #include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_enum_field_lite.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/compiler/java/java_lazy_message_field.h>
-#include <google/protobuf/compiler/java/java_lazy_message_field_lite.h>
 #include <google/protobuf/compiler/java/java_map_field.h>
 #include <google/protobuf/compiler/java/java_map_field_lite.h>
 #include <google/protobuf/compiler/java/java_message_field.h>
@@ -77,13 +75,8 @@
           return new ImmutableMapFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
         } else {
-          if (IsLazy(field, context->EnforceLite())) {
-            return new RepeatedImmutableLazyMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new RepeatedImmutableMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new RepeatedImmutableMessageFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         }
       case JAVATYPE_ENUM:
         return new RepeatedImmutableEnumFieldGenerator(
@@ -99,13 +92,8 @@
     if (field->containing_oneof()) {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field, context->EnforceLite())) {
-            return new ImmutableLazyMessageOneofFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageOneofFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageOneofFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumOneofFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -119,13 +107,8 @@
     } else {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field, context->EnforceLite())) {
-            return new ImmutableLazyMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageFieldGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageFieldGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumFieldGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -150,13 +133,8 @@
           return new ImmutableMapFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
         } else {
-          if (IsLazy(field, context->EnforceLite())) {
-            return new RepeatedImmutableLazyMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new RepeatedImmutableMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new RepeatedImmutableMessageFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         }
       case JAVATYPE_ENUM:
         return new RepeatedImmutableEnumFieldLiteGenerator(
@@ -172,13 +150,8 @@
     if (field->containing_oneof()) {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field, context->EnforceLite())) {
-            return new ImmutableLazyMessageOneofFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageOneofFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageOneofFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumOneofFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -192,13 +165,8 @@
     } else {
       switch (GetJavaType(field)) {
         case JAVATYPE_MESSAGE:
-          if (IsLazy(field, context->EnforceLite())) {
-            return new ImmutableLazyMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          } else {
-            return new ImmutableMessageFieldLiteGenerator(
-                field, messageBitIndex, builderBitIndex, context);
-          }
+          return new ImmutableMessageFieldLiteGenerator(
+              field, messageBitIndex, builderBitIndex, context);
         case JAVATYPE_ENUM:
           return new ImmutableEnumFieldLiteGenerator(
               field, messageBitIndex, builderBitIndex, context);
@@ -293,10 +261,17 @@
                              std::map<string, string>* variables) {
   (*variables)["field_name"] = descriptor->name();
   (*variables)["name"] = info->name;
+  (*variables)["classname"] = descriptor->containing_type()->name();
   (*variables)["capitalized_name"] = info->capitalized_name;
   (*variables)["disambiguated_reason"] = info->disambiguated_reason;
   (*variables)["constant_name"] = FieldConstantName(descriptor);
   (*variables)["number"] = SimpleItoa(descriptor->number());
+  // These variables are placeholders to pick out the beginning and ends of
+  // identifiers for annotations (when doing so with existing variables would
+  // be ambiguous or impossible). They should never be set to anything but the
+  // empty string.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index 0fda166..2d5465b 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -499,19 +499,57 @@
     // Try to load immutable messages' outer class. Its initialization code
     // will take care of interpreting custom options.
     printer->Print(
-      "try {\n"
-      // Note that we have to load the immutable class dynamically here as
-      // we want the mutable code to be independent from the immutable code
-      // at compile time. It is required to implement dual-compile for
-      // mutable and immutable API in blaze.
-      "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
-      "      \"$immutable_classname$\");\n"
-      "} catch (java.lang.ClassNotFoundException e) {\n"
-      // The immutable class can not be found. Custom options are left
-      // as unknown fields.
-      // TODO(xiaofeng): inform the user with a warning?
-      "}\n",
-      "immutable_classname", name_resolver_->GetImmutableClassName(file_));
+        "try {\n"
+        // Note that we have to load the immutable class dynamically here as
+        // we want the mutable code to be independent from the immutable code
+        // at compile time. It is required to implement dual-compile for
+        // mutable and immutable API in blaze.
+        "  java.lang.Class immutableClass = java.lang.Class.forName(\n"
+        "      \"$immutable_classname$\");\n"
+        "} catch (java.lang.ClassNotFoundException e) {\n",
+        "immutable_classname", name_resolver_->GetImmutableClassName(file_));
+    printer->Indent();
+
+    // The immutable class can not be found. We try our best to collect all
+    // custom option extensions to interpret the custom options.
+    printer->Print(
+        "com.google.protobuf.ExtensionRegistry registry =\n"
+        "    com.google.protobuf.ExtensionRegistry.newInstance();\n"
+        "com.google.protobuf.MessageLite defaultExtensionInstance = null;\n");
+    FieldDescriptorSet::iterator it;
+    for (it = extensions.begin(); it != extensions.end(); it++) {
+      const FieldDescriptor* field = *it;
+      string scope;
+      if (field->extension_scope() != NULL) {
+        scope = name_resolver_->GetMutableClassName(field->extension_scope()) +
+                ".getDescriptor()";
+      } else {
+        scope = FileJavaPackage(field->file(), true) + "." +
+                name_resolver_->GetDescriptorClassName(field->file()) +
+                ".descriptor";
+      }
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        printer->Print(
+            "defaultExtensionInstance = com.google.protobuf.Internal\n"
+            "    .getDefaultInstance(\"$class$\");\n"
+            "if (defaultExtensionInstance != null) {\n"
+            "  registry.add(\n"
+            "      $scope$.getExtensions().get($index$),\n"
+            "      (com.google.protobuf.Message) defaultExtensionInstance);\n"
+            "}\n",
+            "scope", scope, "index", SimpleItoa(field->index()), "class",
+            name_resolver_->GetImmutableClassName(field->message_type()));
+      } else {
+        printer->Print("registry.add($scope$.getExtensions().get($index$));\n",
+                       "scope", scope, "index", SimpleItoa(field->index()));
+      }
+    }
+    printer->Print(
+        "com.google.protobuf.Descriptors.FileDescriptor\n"
+        "    .internalUpdateFileDescriptor(descriptor, registry);\n");
+
+    printer->Outdent();
+    printer->Print("}\n");
   }
 
   // Force descriptor initialization of all dependencies.
diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
index 0214121..84a3b90 100644
--- a/src/google/protobuf/compiler/java/java_generator.cc
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -42,6 +42,7 @@
 #include <google/protobuf/compiler/java/java_file.h>
 #include <google/protobuf/compiler/java/java_generator_factory.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
+#include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/compiler/java/java_options.h>
 #include <google/protobuf/compiler/java/java_shared_code_generator.h>
 #include <google/protobuf/io/printer.h>
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 8469740..d8ac2db 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -43,6 +43,8 @@
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+
+
 #include <google/protobuf/stubs/hash.h>  // for hash<T *>
 
 namespace google {
@@ -167,6 +169,14 @@
   return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
 }
 
+string CamelCaseFieldName(const FieldDescriptor* field) {
+  string fieldName = UnderscoresToCamelCase(field);
+  if ('0' <= fieldName[0] && fieldName[0] <= '9') {
+    return '_' + fieldName;
+  }
+  return fieldName;
+}
+
 string StripProto(const string& filename) {
   if (HasSuffixString(filename, ".protodevel")) {
     return StripSuffixString(filename, ".protodevel");
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 829ec3d..bd565ce 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -74,6 +74,10 @@
 // of lower-casing the first letter of the name.)
 string UnderscoresToCamelCase(const MethodDescriptor* method);
 
+// Similar to UnderscoresToCamelCase, but guarentees that the result is a
+// complete Java identifier by adding a _ if needed.
+string CamelCaseFieldName(const FieldDescriptor* field);
+
 // Get an identifier that uniquely identifies this type within the file.
 // This is used to declare static variables related to this type at the
 // outermost file scope.
@@ -242,15 +246,6 @@
          file->options().java_generic_services();
 }
 
-inline bool IsLazy(const FieldDescriptor* descriptor, bool enforce_lite) {
-  // Currently, the proto-lite version supports lazy field.
-  // TODO(niwasaki): Support lazy fields also for other proto runtimes.
-  if (HasDescriptorMethods(descriptor->file(), enforce_lite)) {
-    return false;
-  }
-  return descriptor->options().lazy();
-}
-
 // Methods for shared bitfields.
 
 // Gets the name of the shared bitfield for the given index.
@@ -372,10 +367,6 @@
   return descriptor->is_map();
 }
 
-inline bool PreserveUnknownFields(const Descriptor* descriptor) {
-  return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
-}
-
 inline bool IsAnyMessage(const Descriptor* descriptor) {
   return descriptor->full_name() == "google.protobuf.Any";
 }
diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
index 608b537..b22a219 100644
--- a/src/google/protobuf/compiler/java/java_map_field.cc
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -183,12 +183,14 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
-      "$deprecation$int get$capitalized_name$Count();\n");
+      "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
-      "$deprecation$boolean contains$capitalized_name$(\n"
+      "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
       "    $key_type$ key);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -197,23 +199,27 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$Map();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$$value_enum_type$ get$capitalized_name$OrDefault(\n"
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_enum_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$$value_enum_type$ get$capitalized_name$OrThrow(\n"
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
       printer->Print(
           variables_,
@@ -222,25 +228,29 @@
           " */\n"
           "@java.lang.Deprecated\n"
           "java.util.Map<$type_parameters$>\n"
-          "get$capitalized_name$Value();\n");
+          "${$get$capitalized_name$Value$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$java.util.Map<$type_parameters$>\n"
-          "get$capitalized_name$ValueMap();\n");
+          "${$get$capitalized_name$ValueMap$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "$value_type$ get$capitalized_name$ValueOrDefault(\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ defaultValue);\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "$value_type$ get$capitalized_name$ValueOrThrow(\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
           "    $key_type$ key);\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
     printer->Print(
@@ -250,25 +260,29 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "java.util.Map<$type_parameters$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$type_parameters$>\n"
-        "get$capitalized_name$Map();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "$value_type$ get$capitalized_name$OrDefault(\n"
+        "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "$value_type$ get$capitalized_name$OrThrow(\n"
+        "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -349,23 +363,27 @@
       "  return $name$_;\n"
       "}\n");
   GenerateMapGetters(printer);
-  printer->Print(variables_,
-                 "$deprecation$\n"
-                 "public Builder clear$capitalized_name$() {\n"
-                 "  internalGetMutable$capitalized_name$().getMutableMap()\n"
-                 "      .clear();\n"
-                 "  return this;\n"
-                 "}\n");
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public Builder ${$clear$capitalized_name$$}$() {\n"
+      "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+      "      .clear();\n"
+      "  return this;\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
-  printer->Print(variables_,
-                 "$deprecation$\n"
-                 "public Builder remove$capitalized_name$(\n"
-                 "    $key_type$ key) {\n"
-                 "  $key_null_check$\n"
-                 "  internalGetMutable$capitalized_name$().getMutableMap()\n"
-                 "      .remove(key);\n"
-                 "  return this;\n"
-                 "}\n");
+  printer->Print(
+      variables_,
+      "$deprecation$\n"
+      "public Builder ${$remove$capitalized_name$$}$(\n"
+      "    $key_type$ key) {\n"
+      "  $key_null_check$\n"
+      "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+      "      .remove(key);\n"
+      "  return this;\n"
+      "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -374,13 +392,14 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "getMutable$capitalized_name$() {\n"
+        "${$getMutable$capitalized_name$$}$() {\n"
         "  return internalGetAdapted$capitalized_name$Map(\n"
         "       internalGetMutable$capitalized_name$().getMutableMap());\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-                   "$deprecation$public Builder put$capitalized_name$(\n"
+                   "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
                    "    $key_type$ key,\n"
                    "    $value_enum_type$ value) {\n"
                    "  $key_null_check$\n"
@@ -389,16 +408,18 @@
                    "      .put(key, $name$ValueConverter.doBackward(value));\n"
                    "  return this;\n"
                    "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$public Builder putAll$capitalized_name$(\n"
+        "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
         "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
         "  internalGetAdapted$capitalized_name$Map(\n"
         "      internalGetMutable$capitalized_name$().getMutableMap())\n"
         "          .putAll(values);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
       printer->Print(
           variables_,
@@ -407,13 +428,14 @@
           " */\n"
           "@java.lang.Deprecated\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "getMutable$capitalized_name$Value() {\n"
+          "${$getMutable$capitalized_name$Value$}$() {\n"
           "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$public Builder put$capitalized_name$Value(\n"
+          "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ value) {\n"
           "  $key_null_check$\n"
@@ -421,15 +443,17 @@
           "      .put(key, value);\n"
           "  return this;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+          "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
           "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
           "  internalGetMutable$capitalized_name$().getMutableMap()\n"
           "      .putAll(values);\n"
           "  return this;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
     printer->Print(
@@ -439,30 +463,35 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "public java.util.Map<$type_parameters$>\n"
-        "getMutable$capitalized_name$() {\n"
+        "${$getMutable$capitalized_name$$}$() {\n"
         "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-                   "$deprecation$"
-                   "public Builder put$capitalized_name$(\n"
-                   "    $key_type$ key,\n"
-                   "    $value_type$ value) {\n"
-                   "  $key_null_check$\n"
-                   "  $value_null_check$\n"
-                   "  internalGetMutable$capitalized_name$().getMutableMap()\n"
-                   "      .put(key, value);\n"
-                   "  return this;\n"
-                   "}\n");
+    printer->Print(
+        variables_,
+        "$deprecation$"
+        "public Builder ${$put$capitalized_name$$}$(\n"
+        "    $key_type$ key,\n"
+        "    $value_type$ value) {\n"
+        "  $key_null_check$\n"
+        "  $value_null_check$\n"
+        "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+        "      .put(key, value);\n"
+        "  return this;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-                   "$deprecation$\n"
-                   "public Builder putAll$capitalized_name$(\n"
-                   "    java.util.Map<$type_parameters$> values) {\n"
-                   "  internalGetMutable$capitalized_name$().getMutableMap()\n"
-                   "      .putAll(values);\n"
-                   "  return this;\n"
-                   "}\n");
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public Builder ${$putAll$capitalized_name$$}$(\n"
+        "    java.util.Map<$type_parameters$> values) {\n"
+        "  internalGetMutable$capitalized_name$().getMutableMap()\n"
+        "      .putAll(values);\n"
+        "  return this;\n"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -471,18 +500,20 @@
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public int get$capitalized_name$Count() {\n"
+      "public int ${$get$capitalized_name$Count$}$() {\n"
       "  return internalGet$capitalized_name$().getMap().size();\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public boolean contains$capitalized_name$(\n"
+      "public boolean ${$contains$capitalized_name$$}$(\n"
       "    $key_type$ key) {\n"
       "  $key_null_check$\n"
       "  return internalGet$capitalized_name$().getMap().containsKey(key);\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -491,22 +522,25 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
+        "${$get$capitalized_name$$}$() {\n"
         "  return get$capitalized_name$Map();\n"
         "}\n");
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-                   "$deprecation$\n"
-                   "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-                   "get$capitalized_name$Map() {\n"
-                   "  return internalGetAdapted$capitalized_name$Map(\n"
-                   "      internalGet$capitalized_name$().getMap());"
-                   "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_enum_type$ get$capitalized_name$OrDefault(\n"
+        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+        "${$get$capitalized_name$Map$}$() {\n"
+        "  return internalGetAdapted$capitalized_name$Map(\n"
+        "      internalGet$capitalized_name$().getMap());"
+        "}\n");
+    printer->Annotate("{", "}", descriptor_);
+    WriteFieldDocComment(printer, descriptor_);
+    printer->Print(
+        variables_,
+        "$deprecation$\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_enum_type$ defaultValue) {\n"
         "  $key_null_check$\n"
@@ -516,11 +550,12 @@
         "         ? $name$ValueConverter.doForward(map.get(key))\n"
         "         : defaultValue;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_enum_type$ get$capitalized_name$OrThrow(\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@@ -530,6 +565,7 @@
         "  }\n"
         "  return $name$ValueConverter.doForward(map.get(key));\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
       printer->Print(
           variables_,
@@ -538,22 +574,24 @@
           " */\n"
           "@java.lang.Deprecated\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
+          "${$get$capitalized_name$Value$}$() {\n"
           "  return get$capitalized_name$ValueMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$ValueMap() {\n"
+          "${$get$capitalized_name$ValueMap$}$() {\n"
           "  return internalGet$capitalized_name$().getMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "public $value_type$ get$capitalized_name$ValueOrDefault(\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ defaultValue) {\n"
           "  $key_null_check$\n"
@@ -561,11 +599,12 @@
           "      internalGet$capitalized_name$().getMap();\n"
           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "public $value_type$ get$capitalized_name$ValueOrThrow(\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
           "    $key_type$ key) {\n"
           "  $key_null_check$\n"
           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@@ -575,6 +614,7 @@
           "  }\n"
           "  return map.get(key);\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
     printer->Print(
@@ -583,21 +623,25 @@
         " * Use {@link #get$capitalized_name$Map()} instead.\n"
         " */\n"
         "@java.lang.Deprecated\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$$}$() {\n"
         "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$Map() {\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$Map$}$() {\n"
         "  return internalGet$capitalized_name$().getMap();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_type$ get$capitalized_name$OrDefault(\n"
+        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_type$ defaultValue) {\n"
         "  $key_null_check$\n"
@@ -605,11 +649,12 @@
         "      internalGet$capitalized_name$().getMap();\n"
         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_type$ get$capitalized_name$OrThrow(\n"
+        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$type_parameters$> map =\n"
@@ -619,6 +664,7 @@
         "  }\n"
         "  return map.get(key);\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index 073d1cf..f19ec27 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -166,12 +166,14 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
-      "$deprecation$int get$capitalized_name$Count();\n");
+      "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
-      "$deprecation$boolean contains$capitalized_name$(\n"
+      "$deprecation$boolean ${$contains$capitalized_name$$}$(\n"
       "    $key_type$ key);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -180,23 +182,27 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$Map();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$$value_enum_type$ get$capitalized_name$OrDefault(\n"
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_enum_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$$value_enum_type$ get$capitalized_name$OrThrow(\n"
+        "$deprecation$$value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
       printer->Print(
           variables_,
@@ -205,25 +211,29 @@
           " */\n"
           "@java.lang.Deprecated\n"
           "java.util.Map<$type_parameters$>\n"
-          "get$capitalized_name$Value();\n");
+          "${$get$capitalized_name$Value$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$java.util.Map<$type_parameters$>\n"
-          "get$capitalized_name$ValueMap();\n");
+          "${$get$capitalized_name$ValueMap$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "$value_type$ get$capitalized_name$ValueOrDefault(\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ defaultValue);\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "$value_type$ get$capitalized_name$ValueOrThrow(\n"
+          "$value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
           "    $key_type$ key);\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
     printer->Print(
@@ -233,25 +243,29 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "java.util.Map<$type_parameters$>\n"
-        "get$capitalized_name$();\n");
+        "${$get$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$java.util.Map<$type_parameters$>\n"
-        "get$capitalized_name$Map();\n");
+        "${$get$capitalized_name$Map$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "$value_type$ get$capitalized_name$OrDefault(\n"
+        "$value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_type$ defaultValue);\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "$value_type$ get$capitalized_name$OrThrow(\n"
+        "$value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -288,18 +302,20 @@
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public int get$capitalized_name$Count() {\n"
+      "public int ${$get$capitalized_name$Count$}$() {\n"
       "  return internalGet$capitalized_name$().size();\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public boolean contains$capitalized_name$(\n"
+      "public boolean ${$contains$capitalized_name$$}$(\n"
       "    $key_type$ key) {\n"
       "  $key_null_check$\n"
       "  return internalGet$capitalized_name$().containsKey(key);\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -316,26 +332,28 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
+        "${$get$capitalized_name$$}$() {\n"
         "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$Map() {\n"
+        "${$get$capitalized_name$Map$}$() {\n"
         "  return java.util.Collections.unmodifiableMap(\n"
         "      new com.google.protobuf.Internal.MapAdapter<\n"
         "        $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n"
         "            internalGet$capitalized_name$(),\n"
         "            $name$ValueConverter));\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_enum_type$ get$capitalized_name$OrDefault(\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_enum_type$ defaultValue) {\n"
         "  $key_null_check$\n"
@@ -345,11 +363,12 @@
         "         ? $name$ValueConverter.doForward(map.get(key))\n"
         "         : defaultValue;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_enum_type$ get$capitalized_name$OrThrow(\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@@ -359,6 +378,7 @@
         "  }\n"
         "  return $name$ValueConverter.doForward(map.get(key));\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
       printer->Print(
           variables_,
@@ -367,23 +387,25 @@
           " */\n"
           "@java.lang.Deprecated\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
+          "${$get$capitalized_name$Value$}$() {\n"
           "  return get$capitalized_name$ValueMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$ValueMap() {\n"
+          "${$get$capitalized_name$ValueMap$}$() {\n"
           "  return java.util.Collections.unmodifiableMap(\n"
           "      internalGet$capitalized_name$());\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "public $value_type$ get$capitalized_name$ValueOrDefault(\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ defaultValue) {\n"
           "  $key_null_check$\n"
@@ -391,11 +413,12 @@
           "      internalGet$capitalized_name$();\n"
           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "public $value_type$ get$capitalized_name$ValueOrThrow(\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
           "    $key_type$ key) {\n"
           "  $key_null_check$\n"
           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@@ -405,6 +428,7 @@
           "  }\n"
           "  return map.get(key);\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
     printer->Print(
@@ -413,22 +437,26 @@
         " * Use {@link #get$capitalized_name$Map()} instead.\n"
         " */\n"
         "@java.lang.Deprecated\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$$}$() {\n"
         "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$Map() {\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$Map$}$() {\n"
         "  return java.util.Collections.unmodifiableMap(\n"
         "      internalGet$capitalized_name$());\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_type$ get$capitalized_name$OrDefault(\n"
+        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_type$ defaultValue) {\n"
         "  $key_null_check$\n"
@@ -436,11 +464,12 @@
         "      internalGet$capitalized_name$();\n"
         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_type$ get$capitalized_name$OrThrow(\n"
+        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$type_parameters$> map =\n"
@@ -450,6 +479,7 @@
         "  }\n"
         "  return map.get(key);\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   // Generate private setters for the builder to proxy into.
@@ -490,37 +520,41 @@
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public int get$capitalized_name$Count() {\n"
+      "public int ${$get$capitalized_name$Count$}$() {\n"
       "  return instance.get$capitalized_name$Map().size();\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public boolean contains$capitalized_name$(\n"
+      "public boolean ${$contains$capitalized_name$$}$(\n"
       "    $key_type$ key) {\n"
       "  $key_null_check$\n"
       "  return instance.get$capitalized_name$Map().containsKey(key);\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public Builder clear$capitalized_name$() {\n"
+      "public Builder ${$clear$capitalized_name$$}$() {\n"
       "  copyOnWrite();\n"
       "  instance.getMutable$capitalized_name$Map().clear();\n"
       "  return this;\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(
       variables_,
       "$deprecation$\n"
-      "public Builder remove$capitalized_name$(\n"
+      "public Builder ${$remove$capitalized_name$$}$(\n"
       "    $key_type$ key) {\n"
       "  $key_null_check$\n"
       "  copyOnWrite();\n"
       "  instance.getMutable$capitalized_name$Map().remove(key);\n"
       "  return this;\n"
       "}\n");
+  printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
     printer->Print(
         variables_,
@@ -529,23 +563,25 @@
         " */\n"
         "@java.lang.Deprecated\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$() {\n"
+        "${$get$capitalized_name$$}$() {\n"
         "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
         "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "get$capitalized_name$Map() {\n"
+        "${$get$capitalized_name$Map$}$() {\n"
         "  return java.util.Collections.unmodifiableMap(\n"
         "      instance.get$capitalized_name$Map());\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_enum_type$ get$capitalized_name$OrDefault(\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_enum_type$ defaultValue) {\n"
         "  $key_null_check$\n"
@@ -555,11 +591,12 @@
         "         ? map.get(key)\n"
         "         : defaultValue;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_enum_type$ get$capitalized_name$OrThrow(\n"
+        "public $value_enum_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$boxed_key_type$, $value_enum_type$> map =\n"
@@ -569,10 +606,11 @@
         "  }\n"
         "  return map.get(key);\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$public Builder put$capitalized_name$(\n"
+        "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
         "    $key_type$ key,\n"
         "    $value_enum_type$ value) {\n"
         "  $key_null_check$\n"
@@ -581,15 +619,17 @@
         "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
-        "$deprecation$public Builder putAll$capitalized_name$(\n"
+        "$deprecation$public Builder ${$putAll$capitalized_name$$}$(\n"
         "    java.util.Map<$boxed_key_type$, $value_enum_type$> values) {\n"
         "  copyOnWrite();\n"
         "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     if (SupportUnknownEnumValue(descriptor_->file())) {
       printer->Print(
           variables_,
@@ -598,23 +638,25 @@
           " */\n"
           "@java.lang.Deprecated\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$Value() {\n"
+          "${$get$capitalized_name$Value$}$() {\n"
           "  return get$capitalized_name$ValueMap();\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
           "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "get$capitalized_name$ValueMap() {\n"
+          "${$get$capitalized_name$ValueMap$}$() {\n"
           "  return java.util.Collections.unmodifiableMap(\n"
           "      instance.get$capitalized_name$ValueMap());\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "public $value_type$ get$capitalized_name$ValueOrDefault(\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ defaultValue) {\n"
           "  $key_null_check$\n"
@@ -622,11 +664,12 @@
           "      instance.get$capitalized_name$ValueMap();\n"
           "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
           "$deprecation$\n"
-          "public $value_type$ get$capitalized_name$ValueOrThrow(\n"
+          "public $value_type$ ${$get$capitalized_name$ValueOrThrow$}$(\n"
           "    $key_type$ key) {\n"
           "  $key_null_check$\n"
           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
@@ -636,10 +679,11 @@
           "  }\n"
           "  return map.get(key);\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$public Builder put$capitalized_name$Value(\n"
+          "$deprecation$public Builder ${$put$capitalized_name$Value$}$(\n"
           "    $key_type$ key,\n"
           "    $value_type$ value) {\n"
           "  $key_null_check$\n"
@@ -647,15 +691,17 @@
           "  instance.getMutable$capitalized_name$ValueMap().put(key, value);\n"
           "  return this;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
-          "$deprecation$public Builder putAll$capitalized_name$Value(\n"
+          "$deprecation$public Builder ${$putAll$capitalized_name$Value$}$(\n"
           "    java.util.Map<$boxed_key_type$, $boxed_value_type$> values) {\n"
           "  copyOnWrite();\n"
           "  instance.getMutable$capitalized_name$ValueMap().putAll(values);\n"
           "  return this;\n"
           "}\n");
+      printer->Annotate("{", "}", descriptor_);
     }
   } else {
     printer->Print(
@@ -664,22 +710,26 @@
         " * Use {@link #get$capitalized_name$Map()} instead.\n"
         " */\n"
         "@java.lang.Deprecated\n"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$$}$() {\n"
         "  return get$capitalized_name$Map();\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$"
-        "public java.util.Map<$type_parameters$> get$capitalized_name$Map() {\n"
+        "public java.util.Map<$type_parameters$> "
+        "${$get$capitalized_name$Map$}$() {\n"
         "  return java.util.Collections.unmodifiableMap(\n"
         "      instance.get$capitalized_name$Map());\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_type$ get$capitalized_name$OrDefault(\n"
+        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
         "    $value_type$ defaultValue) {\n"
         "  $key_null_check$\n"
@@ -687,11 +737,12 @@
         "      instance.get$capitalized_name$Map();\n"
         "  return map.containsKey(key) ? map.get(key) : defaultValue;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$\n"
-        "public $value_type$ get$capitalized_name$OrThrow(\n"
+        "public $value_type$ ${$get$capitalized_name$OrThrow$}$(\n"
         "    $key_type$ key) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$type_parameters$> map =\n"
@@ -701,11 +752,12 @@
         "  }\n"
         "  return map.get(key);\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$"
-        "public Builder put$capitalized_name$(\n"
+        "public Builder ${$put$capitalized_name$$}$(\n"
         "    $key_type$ key,\n"
         "    $value_type$ value) {\n"
         "  $key_null_check$\n"
@@ -714,16 +766,18 @@
         "  instance.getMutable$capitalized_name$Map().put(key, value);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
         "$deprecation$"
-        "public Builder putAll$capitalized_name$(\n"
+        "public Builder ${$putAll$capitalized_name$$}$(\n"
         "    java.util.Map<$type_parameters$> values) {\n"
         "  copyOnWrite();\n"
         "  instance.getMutable$capitalized_name$Map().putAll(values);\n"
         "  return this;\n"
         "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index 6e3b4a7..ecc6757 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -56,8 +56,9 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -253,7 +254,7 @@
                                 /* immutable = */ true, "OrBuilder");
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-        "$deprecation$public interface $classname$OrBuilder$idend$ extends\n"
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
         "    $extra_interfaces$\n"
         "    com.google.protobuf.GeneratedMessage$ver$.\n"
         "        ExtendableMessageOrBuilder<$classname$> {\n",
@@ -261,19 +262,19 @@
             "@java.lang.Deprecated " : "",
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "classname", descriptor_->name(),
-        "idend", "", "ver", GeneratedCodeVersionSuffix());
+        "{", "", "}", "", "ver", GeneratedCodeVersionSuffix());
   } else {
     printer->Print(
-        "$deprecation$public interface $classname$OrBuilder$idend$ extends\n"
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
         "    $extra_interfaces$\n"
         "    com.google.protobuf.MessageOrBuilder {\n",
         "deprecation", descriptor_->options().deprecated() ?
             "@java.lang.Deprecated " : "",
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "classname", descriptor_->name(),
-        "idend", "");
+        "{", "", "}", "");
   }
-  printer->Annotate("classname", "idend", descriptor_);
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -345,6 +346,9 @@
         "com.google.protobuf.GeneratedMessage$0.Builder<?>",
         GeneratedCodeVersionSuffix());
   }
+  printer->Print(
+    "private static final long serialVersionUID = 0L;\n");
+
   printer->Indent();
   // Using builder_type, instead of Builder, prevents the Builder class from
   // being loaded into PermGen space when the default instance is created.
@@ -370,15 +374,8 @@
   printer->Print(
     "@java.lang.Override\n"
     "public final com.google.protobuf.UnknownFieldSet\n"
-    "getUnknownFields() {\n");
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "  return this.unknownFields;\n");
-  } else {
-    printer->Print(
-      "  return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n");
-  }
-  printer->Print(
+    "getUnknownFields() {\n"
+    "  return this.unknownFields;\n"
     "}\n");
 
   if (context_->HasGeneratedMethods(descriptor_)) {
@@ -623,14 +620,12 @@
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
+  if (descriptor_->options().message_set_wire_format()) {
+    printer->Print(
         "unknownFields.writeAsMessageSetTo(output);\n");
-    } else {
-      printer->Print(
+  } else {
+    printer->Print(
         "unknownFields.writeTo(output);\n");
-    }
   }
 
   printer->Outdent();
@@ -658,14 +653,12 @@
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
+  if (descriptor_->options().message_set_wire_format()) {
+    printer->Print(
         "size += unknownFields.getSerializedSizeAsMessageSet();\n");
-    } else {
-      printer->Print(
+  } else {
+    printer->Print(
         "size += unknownFields.getSerializedSize();\n");
-    }
   }
 
   printer->Outdent();
@@ -674,9 +667,6 @@
     "  return size;\n"
     "}\n"
     "\n");
-
-  printer->Print(
-    "private static final long serialVersionUID = 0L;\n");
 }
 
 void ImmutableMessageGenerator::
@@ -1078,13 +1068,11 @@
     printer->Print("}\n");
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    // Always consider unknown fields for equality. This will sometimes return
-    // false for non-canonical ordering when running in LITE_RUNTIME but it's
-    // the best we can do.
-    printer->Print(
+  // Always consider unknown fields for equality. This will sometimes return
+  // false for non-canonical ordering when running in LITE_RUNTIME but it's
+  // the best we can do.
+  printer->Print(
       "result = result && unknownFields.equals(other.unknownFields);\n");
-  }
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
       "result = result &&\n"
@@ -1226,11 +1214,9 @@
       "bit_field_name", GetBitFieldName(i));
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
+  printer->Print(
       "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n"
       "    com.google.protobuf.UnknownFieldSet.newBuilder();\n");
-  }
 
   printer->Print(
       "try {\n");
@@ -1247,28 +1233,19 @@
   printer->Indent();
 
   printer->Print(
-    "case 0:\n"          // zero signals EOF / limit reached
+    "case 0:\n"  // zero signals EOF / limit reached
     "  done = true;\n"
-    "  break;\n");
-
-  if (PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "default: {\n"
-      "  if (!parseUnknownField(input, unknownFields,\n"
-      "                         extensionRegistry, tag)) {\n"
-      "    done = true;\n"  // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n");
-  } else {
-    printer->Print(
-      "default: {\n"
-      "  if (!input.skipField(tag)) {\n"
-      "    done = true;\n"  // it's an endgroup tag
-      "  }\n"
-      "  break;\n"
-      "}\n");
-  }
+    "  break;\n"
+    "default: {\n"
+    "  if (!parseUnknownField$suffix$(\n"
+    "      input, unknownFields, extensionRegistry, tag)) {\n"
+    "    done = true;\n"  // it's an endgroup tag
+    "  }\n"
+    "  break;\n"
+    "}\n",
+    "suffix",
+    descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 ? "Proto3"
+                                                                   : "");
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = sorted_fields[i];
@@ -1328,10 +1305,8 @@
     field_generators_.get(field).GenerateParsingDoneCode(printer);
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    // Make unknown fields immutable.
-    printer->Print("this.unknownFields = unknownFields.build();\n");
-  }
+  // Make unknown fields immutable.
+  printer->Print("this.unknownFields = unknownFields.build();\n");
 
   // Make extensions immutable.
   printer->Print(
diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
index f5643ab..f9bbfbf 100644
--- a/src/google/protobuf/compiler/java/java_message_builder.cc
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -54,8 +54,9 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -171,36 +172,25 @@
                      .GenerateBuilderMembers(printer);
   }
 
-  if (!PreserveUnknownFields(descriptor_)) {
-    printer->Print(
-      "public final Builder setUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n"
-      "public final Builder mergeUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return this;\n"
-      "}\n"
-      "\n");
-  } else {
+  bool is_proto3 =
+      descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
     // Override methods declared in GeneratedMessage to return the concrete
     // generated type so callsites won't depend on GeneratedMessage. This
     // is needed to keep binary compatibility when we change generated code
     // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
     // we changed all generated code to subclass GeneratedMessageV3).
-    printer->Print(
-      "public final Builder setUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return super.setUnknownFields(unknownFields);\n"
-      "}\n"
-      "\n"
-      "public final Builder mergeUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return super.mergeUnknownFields(unknownFields);\n"
-      "}\n"
-      "\n");
-  }
+  printer->Print(
+    "public final Builder setUnknownFields(\n"
+    "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+    "  return super.setUnknownFields$suffix$(unknownFields);\n"
+    "}\n"
+    "\n"
+    "public final Builder mergeUnknownFields(\n"
+    "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+    "  return super.mergeUnknownFields(unknownFields);\n"
+    "}\n"
+    "\n",
+    "suffix", is_proto3 ? "Proto3" : "");
 
   printer->Print(
     "\n"
@@ -472,7 +462,7 @@
     "}\n"
     "public Builder setField(\n"
     "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
-    "    Object value) {\n"
+    "    java.lang.Object value) {\n"
     "  return (Builder) super.setField(field, value);\n"
     "}\n"
     "public Builder clearField(\n"
@@ -485,12 +475,12 @@
     "}\n"
     "public Builder setRepeatedField(\n"
     "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
-    "    int index, Object value) {\n"
+    "    int index, java.lang.Object value) {\n"
     "  return (Builder) super.setRepeatedField(field, index, value);\n"
     "}\n"
     "public Builder addRepeatedField(\n"
     "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
-    "    Object value) {\n"
+    "    java.lang.Object value) {\n"
     "  return (Builder) super.addRepeatedField(field, value);\n"
     "}\n");
 
@@ -594,10 +584,8 @@
         "  this.mergeExtensionFields(other);\n");
     }
 
-    if (PreserveUnknownFields(descriptor_)) {
-      printer->Print(
-        "  this.mergeUnknownFields(other.unknownFields);\n");
-    }
+    printer->Print(
+      "  this.mergeUnknownFields(other.unknownFields);\n");
 
     printer->Print(
       "  onChanged();\n");
diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
index ae84db1..baa7f87 100644
--- a/src/google/protobuf/compiler/java/java_message_field.cc
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -150,12 +150,9 @@
   // interface so that builders can choose dynamically to either return a
   // message or a nested builder, so that asking for the interface doesn't
   // cause a message to ever be built.
-  if (SupportFieldPresence(descriptor_->file()) ||
-      descriptor_->containing_oneof() == NULL) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$boolean has$capitalized_name$();\n");
-  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
@@ -174,39 +171,45 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
 
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$OrBuilder "
-      "get$capitalized_name$OrBuilder() {\n"
+      "${$get$capitalized_name$OrBuilder$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   } else {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $name$_ != null;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
 
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
       "$deprecation$public $type$OrBuilder "
-      "get$capitalized_name$OrBuilder() {\n"
+      "${$get$capitalized_name$OrBuilder$}$() {\n"
       "  return get$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
@@ -232,6 +235,7 @@
     const char* nested_builder_case,
     const char* trailing_code) const {
   printer->Print(variables_, method_prototype);
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(" {\n");
   printer->Indent();
   PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
@@ -267,20 +271,22 @@
   WriteFieldDocComment(printer, descriptor_);
   if (support_field_presence) {
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   } else {
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $name$Builder_ != null || $name$_ != null;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public $type$ get$capitalized_name$()",
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$()",
     "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n",
     "return $name$Builder_.getMessage();\n",
     NULL);
@@ -288,7 +294,7 @@
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)",
 
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -304,7 +310,7 @@
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue)",
 
     "$name$_ = builderForValue.build();\n"
@@ -318,7 +324,7 @@
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
 
     support_field_presence
         ? "if ($get_has_field_bit_builder$ &&\n"
@@ -346,7 +352,7 @@
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder clear$capitalized_name$()",
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
 
     "$name$_ = null;\n"
     "$on_changed$\n",
@@ -361,14 +367,17 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "$deprecation$public $type$.Builder "
+    "${$get$capitalized_name$Builder$}$() {\n"
     "  $set_has_field_bit_builder$\n"
     "  $on_changed$\n"
     "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$() {\n"
     "  if ($name$Builder_ != null) {\n"
     "    return $name$Builder_.getMessageOrBuilder();\n"
     "  } else {\n"
@@ -376,6 +385,7 @@
     "        $type$.getDefaultInstance() : $name$_;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
@@ -530,30 +540,32 @@
 void ImmutableMessageOneofFieldGenerator::
 GenerateMembers(io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_->file())) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return $has_oneof_case_message$;\n"
-      "}\n");
-  }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "     return ($type$) $oneof_name$_;\n"
     "  }\n"
     "  return $type$.getDefaultInstance();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "     return ($type$) $oneof_name$_;\n"
     "  }\n"
     "  return $type$.getDefaultInstance();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageOneofFieldGenerator::
@@ -571,19 +583,18 @@
   // The comments above the methods below are based on a hypothetical
   // field of type "Field" called "Field".
 
-  if (SupportFieldPresence(descriptor_->file())) {
-    // boolean hasField()
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return $has_oneof_case_message$;\n"
-      "}\n");
-  }
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public $type$ get$capitalized_name$()",
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$()",
 
     "if ($has_oneof_case_message$) {\n"
     "  return ($type$) $oneof_name$_;\n"
@@ -600,7 +611,7 @@
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value)",
 
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -616,7 +627,7 @@
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue)",
 
     "$oneof_name$_ = builderForValue.build();\n"
@@ -630,7 +641,7 @@
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$merge$capitalized_name$$}$($type$ value)",
 
     "if ($has_oneof_case_message$ &&\n"
     "    $oneof_name$_ != $type$.getDefaultInstance()) {\n"
@@ -652,7 +663,7 @@
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder clear$capitalized_name$()",
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
 
     "if ($has_oneof_case_message$) {\n"
     "  $clear_oneof_case_message$;\n"
@@ -670,12 +681,15 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n"
+    "$deprecation$public $type$.Builder "
+    "${$get$capitalized_name$Builder$}$() {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilder();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$() {\n"
     "  if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n"
     "    return $name$Builder_.getMessageOrBuilder();\n"
     "  } else {\n"
@@ -685,11 +699,12 @@
     "    return $type$.getDefaultInstance();\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "private com.google.protobuf.SingleFieldBuilder$ver$<\n"
     "    $type$, $type$.Builder, $type$OrBuilder> \n"
-    "    get$capitalized_name$FieldBuilder() {\n"
+    "    ${$get$capitalized_name$FieldBuilder$}$() {\n"
     "  if ($name$Builder_ == null) {\n"
     "    if (!($has_oneof_case_message$)) {\n"
     "      $oneof_name$_ = $type$.getDefaultInstance();\n"
@@ -705,6 +720,7 @@
     "  $on_changed$;\n"
     "  return $name$Builder_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageOneofFieldGenerator::
@@ -833,31 +849,38 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
-    "    get$capitalized_name$OrBuilderList() {\n"
+    "    ${$get$capitalized_name$OrBuilderList$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$(\n"
     "    int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
 }
 
@@ -883,6 +906,7 @@
     const char* nested_builder_case,
     const char* trailing_code) const {
   printer->Print(variables_, method_prototype);
+  printer->Annotate("{", "}", descriptor_);
   printer->Print(" {\n");
   printer->Indent();
   PrintNestedBuilderCondition(printer, regular_case, nested_builder_case);
@@ -934,7 +958,8 @@
   // List<Field> getRepeatedFieldList()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List()",
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$()",
 
     "return java.util.Collections.unmodifiableList($name$_);\n",
     "return $name$Builder_.getMessageList();\n",
@@ -944,7 +969,7 @@
   // int getRepeatedFieldCount()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public int get$capitalized_name$Count()",
+    "$deprecation$public int ${$get$capitalized_name$Count$}$()",
 
     "return $name$_.size();\n",
     "return $name$Builder_.getCount();\n",
@@ -954,7 +979,7 @@
   // Field getRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public $type$ get$capitalized_name$(int index)",
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index)",
 
     "return $name$_.get(index);\n",
 
@@ -965,7 +990,7 @@
   // Builder setRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value)",
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -979,7 +1004,7 @@
   // Builder setRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -993,7 +1018,7 @@
   // Builder addRepeatedField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$($type$ value)",
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value)",
 
     "if (value == null) {\n"
     "  throw new NullPointerException();\n"
@@ -1010,7 +1035,7 @@
   // Builder addRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$ value)",
 
     "if (value == null) {\n"
@@ -1027,7 +1052,7 @@
   // Builder addRepeatedField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -1041,7 +1066,7 @@
   // Builder addRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -1055,7 +1080,7 @@
   // Builder addAllRepeatedField(Iterable<Field> values)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values)",
 
     "ensure$capitalized_name$IsMutable();\n"
@@ -1070,7 +1095,7 @@
   // Builder clearAllRepeatedField()
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder clear$capitalized_name$()",
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$()",
 
     "$name$_ = java.util.Collections.emptyList();\n"
     "$clear_mutable_bit_builder$;\n"
@@ -1083,7 +1108,7 @@
   // Builder removeRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   PrintNestedBuilderFunction(printer,
-    "$deprecation$public Builder remove$capitalized_name$(int index)",
+    "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index)",
 
     "ensure$capitalized_name$IsMutable();\n"
     "$name$_.remove(index);\n"
@@ -1095,14 +1120,16 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n"
+    "$deprecation$public $type$.Builder ${$get$capitalized_name$Builder$}$(\n"
     "    int index) {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilder(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$(\n"
     "    int index) {\n"
     "  if ($name$Builder_ == null) {\n"
     "    return $name$_.get(index);"
@@ -1110,35 +1137,40 @@
     "    return $name$Builder_.getMessageOrBuilder(index);\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
-    "     get$capitalized_name$OrBuilderList() {\n"
+    "     ${$get$capitalized_name$OrBuilderList$}$() {\n"
     "  if ($name$Builder_ != null) {\n"
     "    return $name$Builder_.getMessageOrBuilderList();\n"
     "  } else {\n"
     "    return java.util.Collections.unmodifiableList($name$_);\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
-    "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n"
+    "$deprecation$public $type$.Builder "
+    "${$add$capitalized_name$Builder$}$() {\n"
     "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
     "      $type$.getDefaultInstance());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
-    "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n"
+    "$deprecation$public $type$.Builder ${$add$capitalized_name$Builder$}$(\n"
     "    int index) {\n"
     "  return get$capitalized_name$FieldBuilder().addBuilder(\n"
     "      index, $type$.getDefaultInstance());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
     "$deprecation$public java.util.List<$type$.Builder> \n"
-    "     get$capitalized_name$BuilderList() {\n"
+    "     ${$get$capitalized_name$BuilderList$}$() {\n"
     "  return get$capitalized_name$FieldBuilder().getBuilderList();\n"
     "}\n"
     "private com.google.protobuf.RepeatedFieldBuilder$ver$<\n"
@@ -1155,6 +1187,7 @@
     "  }\n"
     "  return $name$Builder_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableMessageFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index c71e910..df3e80d 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -129,16 +129,9 @@
 
 void ImmutableMessageFieldLiteGenerator::
 GenerateInterfaceMembers(io::Printer* printer) const {
-  // TODO(jonp): In the future, consider having a method specific to the
-  // interface so that builders can choose dynamically to either return a
-  // message or a nested builder, so that asking for the interface doesn't
-  // cause a message to ever be built.
-  if (SupportFieldPresence(descriptor_->file()) ||
-      descriptor_->containing_oneof() == NULL) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$boolean has$capitalized_name$();\n");
-  }
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$boolean has$capitalized_name$();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$$type$ get$capitalized_name$();\n");
@@ -154,25 +147,29 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   } else {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $name$_ != null;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public $type$ get$capitalized_name$() {\n"
+      "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
       "  return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   // Field.Builder setField(Field value)
@@ -226,53 +223,60 @@
   // boolean hasField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
     "  return instance.has$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "  }\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder "
+    "${$merge$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.merge$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageFieldLiteGenerator::
@@ -390,21 +394,21 @@
 void ImmutableMessageOneofFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
   PrintExtraFieldInfo(variables_, printer);
-  if (SupportFieldPresence(descriptor_->file())) {
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return $has_oneof_case_message$;\n"
-      "}\n");
-  }
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return $has_oneof_case_message$;\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "     return ($type$) $oneof_name$_;\n"
     "  }\n"
     "  return $type$.getDefaultInstance();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
@@ -457,58 +461,63 @@
   // The comments above the methods below are based on a hypothetical
   // field of type "Field" called "Field".
 
-  if (SupportFieldPresence(descriptor_->file())) {
-    // boolean hasField()
-    WriteFieldDocComment(printer, descriptor_);
-    printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
-      "  return instance.has$capitalized_name$();\n"
-      "}\n");
-  }
+  // boolean hasField()
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(variables_,
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
+    "  return instance.has$capitalized_name$();\n"
+    "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder setField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder mergeField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder "
+    "${$merge$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.merge$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field.Builder clearField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageOneofFieldLiteGenerator::
@@ -615,31 +624,38 @@
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<? extends $type$OrBuilder> \n"
-    "    get$capitalized_name$OrBuilderList() {\n"
+    "    ${$get$capitalized_name$OrBuilderList$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n"
+    "$deprecation$public $type$OrBuilder "
+    "${$get$capitalized_name$OrBuilder$}$(\n"
     "    int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
@@ -745,110 +761,123 @@
   // List<Field> getRepeatedFieldList()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<$type$> "
+    "${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList(\n"
     "      instance.get$capitalized_name$List());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // int getRepeatedFieldCount()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}");
+  printer->Annotate("{", "}", descriptor_);
 
   // Field getRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder setRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder setRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addRepeatedField(Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addRepeatedField(int index, Field value)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   // Builder addRepeatedField(Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addRepeatedField(int index, Field.Builder builderForValue)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    int index, $type$.Builder builderForValue) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(index, builderForValue);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder addAllRepeatedField(Iterable<Field> values)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $type$> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder clearAllRepeatedField()
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   // Builder removeRepeatedField(int index)
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder remove$capitalized_name$(int index) {\n"
+    "$deprecation$public Builder ${$remove$capitalized_name$$}$(int index) {\n"
     "  copyOnWrite();\n"
     "  instance.remove$capitalized_name$(index);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 5007ece..26f1643 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -56,8 +56,9 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
+#include <google/protobuf/stubs/strutil.h>
+
 
 namespace google {
 namespace protobuf {
@@ -124,7 +125,7 @@
                                 /* immutable = */ true, "OrBuilder");
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
-        "$deprecation$public interface $classname$OrBuilder$idend$ extends \n"
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends \n"
         "    $extra_interfaces$\n"
         "     com.google.protobuf.GeneratedMessageLite.\n"
         "          ExtendableMessageOrBuilder<\n"
@@ -133,19 +134,19 @@
             "@java.lang.Deprecated " : "",
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "classname", descriptor_->name(),
-        "idend", "");
+        "{", "", "}", "");
   } else {
     printer->Print(
-        "$deprecation$public interface $classname$OrBuilder$idend$ extends\n"
+        "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
         "    $extra_interfaces$\n"
         "    com.google.protobuf.MessageLiteOrBuilder {\n",
         "deprecation", descriptor_->options().deprecated() ?
             "@java.lang.Deprecated " : "",
         "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
         "classname", descriptor_->name(),
-        "idend", "");
+        "{", "", "}", "");
   }
-  printer->Annotate("classname", "idend", descriptor_);
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Indent();
     for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -345,15 +346,15 @@
   }
 
   printer->Print(
-    "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n"
-    "protected final Object dynamicMethod(\n"
-    "    com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
-    "    Object arg0, Object arg1) {\n"
-    "  switch (method) {\n"
-    "    case NEW_MUTABLE_INSTANCE: {\n"
-    "      return new $classname$();\n"
-    "    }\n",
-    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+      "@java.lang.SuppressWarnings({\"unchecked\", \"fallthrough\"})\n"
+      "protected final java.lang.Object dynamicMethod(\n"
+      "    com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n"
+      "    java.lang.Object arg0, java.lang.Object arg1) {\n"
+      "  switch (method) {\n"
+      "    case NEW_MUTABLE_INSTANCE: {\n"
+      "      return new $classname$();\n"
+      "    }\n",
+      "classname", name_resolver_->GetImmutableClassName(descriptor_));
 
   printer->Indent();
   printer->Indent();
@@ -530,14 +531,12 @@
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "unknownFields.writeAsMessageSetTo(output);\n");
-    } else {
-      printer->Print(
-        "unknownFields.writeTo(output);\n");
-    }
+  if (descriptor_->options().message_set_wire_format()) {
+    printer->Print(
+      "unknownFields.writeAsMessageSetTo(output);\n");
+  } else {
+    printer->Print(
+      "unknownFields.writeTo(output);\n");
   }
 
   printer->Outdent();
@@ -565,14 +564,12 @@
     }
   }
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->options().message_set_wire_format()) {
-      printer->Print(
-        "size += unknownFields.getSerializedSizeAsMessageSet();\n");
-    } else {
-      printer->Print(
-        "size += unknownFields.getSerializedSize();\n");
-    }
+  if (descriptor_->options().message_set_wire_format()) {
+    printer->Print(
+      "size += unknownFields.getSerializedSizeAsMessageSet();\n");
+  } else {
+    printer->Print(
+      "size += unknownFields.getSerializedSize();\n");
   }
 
   printer->Outdent();
@@ -968,41 +965,31 @@
     "  done = true;\n"
     "  break;\n");
 
-  if (PreserveUnknownFields(descriptor_)) {
-    if (descriptor_->extension_range_count() > 0) {
-      if (descriptor_->options().message_set_wire_format()) {
-        printer->Print(
-            "default: {\n"
-            "  if (!parseUnknownFieldAsMessageSet(\n"
-            "      getDefaultInstanceForType(), input, extensionRegistry,\n"
-            "      tag)) {\n"
-            "    done = true;\n"  // it's an endgroup tag
-            "  }\n"
-            "  break;\n"
-            "}\n");
-      } else {
-        printer->Print(
-            "default: {\n"
-            "  if (!parseUnknownField(getDefaultInstanceForType(),\n"
-            "      input, extensionRegistry, tag)) {\n"
-            "    done = true;\n"  // it's an endgroup tag
-            "  }\n"
-            "  break;\n"
-            "}\n");
-      }
+  if (descriptor_->extension_range_count() > 0) {
+    if (descriptor_->options().message_set_wire_format()) {
+      printer->Print(
+          "default: {\n"
+          "  if (!parseUnknownFieldAsMessageSet(\n"
+          "      getDefaultInstanceForType(), input, extensionRegistry,\n"
+          "      tag)) {\n"
+          "    done = true;\n"  // it's an endgroup tag
+          "  }\n"
+          "  break;\n"
+          "}\n");
     } else {
       printer->Print(
-        "default: {\n"
-        "  if (!parseUnknownField(tag, input)) {\n"
-        "    done = true;\n"  // it's an endgroup tag
-        "  }\n"
-        "  break;\n"
-        "}\n");
+          "default: {\n"
+          "  if (!parseUnknownField(getDefaultInstanceForType(),\n"
+          "      input, extensionRegistry, tag)) {\n"
+          "    done = true;\n"  // it's an endgroup tag
+          "  }\n"
+          "  break;\n"
+          "}\n");
     }
   } else {
     printer->Print(
       "default: {\n"
-      "  if (!input.skipField(tag)) {\n"
+      "  if (!parseUnknownField(tag, input)) {\n"
       "    done = true;\n"  // it's an endgroup tag
       "  }\n"
       "  break;\n"
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
index bffe4f1..1673b4e 100644
--- a/src/google/protobuf/compiler/java/java_name_resolver.cc
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -33,6 +33,7 @@
 #include <map>
 #include <string>
 
+
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/stubs/substitute.h>
 
diff --git a/src/google/protobuf/compiler/java/java_options.h b/src/google/protobuf/compiler/java/java_options.h
index 7bce144..e4e7d5e 100644
--- a/src/google/protobuf/compiler/java/java_options.h
+++ b/src/google/protobuf/compiler/java/java_options.h
@@ -59,10 +59,10 @@
   bool annotate_code;
   // Name of a file where we will write a list of generated .meta file names,
   // one per line.
-  string annotation_list_file;
+  std::string annotation_list_file;
   // Name of a file where we will write a list of generated file names, one
   // per line.
-  string output_list_file;
+  std::string output_list_file;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 840252e..074a6be 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -190,16 +190,18 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveFieldGenerator::
@@ -210,31 +212,35 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "$null_check$"
     "  $set_has_field_bit_builder$\n"
     "  $name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $clear_has_field_bit_builder$\n");
+  printer->Annotate("{", "}", descriptor_);
   JavaType type = GetJavaType(descriptor_);
   if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) {
     // The default value is not a simple literal so we want to avoid executing
@@ -441,19 +447,21 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    return ($boxed_type$) $oneof_name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 
@@ -462,33 +470,36 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    return ($boxed_type$) $oneof_name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "$null_check$"
     "  $set_oneof_case_message$;\n"
     "  $oneof_name$_ = value;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
@@ -496,6 +507,7 @@
     "  }\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveOneofFieldGenerator::
@@ -604,19 +616,22 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   if (descriptor_->is_packed() &&
       context_->HasGeneratedMethods(descriptor_->containing_type())) {
@@ -654,22 +669,25 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList($name$_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
@@ -677,18 +695,20 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
     "  $name$_.add(value);\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
@@ -696,14 +716,16 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $name$_ = $empty_list$;\n"
     "  $clear_mutable_bit_builder$;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutablePrimitiveFieldGenerator::
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index 0e8e492..f929317 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -222,16 +222,18 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -264,32 +266,36 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveFieldLiteGenerator::
@@ -482,19 +488,21 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    return ($boxed_type$) $oneof_name$_;\n"
     "  }\n"
     "  return $default$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -520,32 +528,36 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$() {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::
@@ -634,21 +646,24 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return $repeated_get$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
-  if (descriptor_->options().packed() &&
+  if (descriptor_->is_packed() &&
       context_->HasGeneratedMethods(descriptor_->containing_type())) {
     printer->Print(variables_,
       "private int $name$MemoizedSerializedSize = -1;\n");
@@ -697,50 +712,57 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public java.util.List<$boxed_type$>\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList(\n"
     "      instance.get$capitalized_name$List());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public $type$ get$capitalized_name$(int index) {\n"
+    "$deprecation$public $type$ ${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, $type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$($type$ value) {\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$($type$ value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<? extends $boxed_type$> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
@@ -829,7 +851,7 @@
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::
 GenerateSerializationCode(io::Printer* printer) const {
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     // We invoke getSerializedSize in writeTo for messages that have packed
     // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods.
     // That makes it safe to rely on the memoized size here.
@@ -870,7 +892,7 @@
   printer->Print(
       "size += dataSize;\n");
 
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "if (!get$capitalized_name$List().isEmpty()) {\n"
       "  size += $tag_size$;\n"
@@ -883,7 +905,7 @@
   }
 
   // cache the data size for packed fields.
-  if (descriptor_->options().packed()) {
+  if (descriptor_->is_packed()) {
     printer->Print(variables_,
       "$name$MemoizedSerializedSize = dataSize;\n");
   }
diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
index 7bd5ad7..f73bfb0 100644
--- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -182,10 +182,16 @@
   std::vector<std::pair<string, string> > dependencies;
   for (int i = 0; i < file_->dependency_count(); i++) {
     string filename = file_->dependency(i)->name();
-    string classname = FileJavaPackage(file_->dependency(i)) + "." +
-                       name_resolver_->GetDescriptorClassName(
-                           file_->dependency(i));
-    dependencies.push_back(std::make_pair(filename, classname));
+    string package = FileJavaPackage(file_->dependency(i));
+    string classname = name_resolver_->GetDescriptorClassName(
+        file_->dependency(i));
+    string full_name;
+    if (package.empty()) {
+      full_name = classname;
+    } else {
+      full_name = package + "." + classname;
+    }
+    dependencies.push_back(std::make_pair(filename, full_name));
   }
 
   // -----------------------------------------------------------------
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 5c2900c..2b6e938 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -217,14 +217,15 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof java.lang.String) {\n"
     "    return (java.lang.String) ref;\n"
@@ -232,6 +233,7 @@
     "    com.google.protobuf.ByteString bs = \n"
     "        (com.google.protobuf.ByteString) ref;\n"
       "    java.lang.String s = bs.toStringUtf8();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "    $name$_ = s;\n");
@@ -248,7 +250,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof java.lang.String) {\n"
     "    com.google.protobuf.ByteString b = \n"
@@ -260,6 +262,7 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringFieldGenerator::
@@ -269,19 +272,21 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_builder$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (!(ref instanceof java.lang.String)) {\n"
     "    com.google.protobuf.ByteString bs =\n"
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "    $name$_ = s;\n");
@@ -301,7 +306,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref = $name$_;\n"
     "  if (ref instanceof String) {\n"
     "    com.google.protobuf.ByteString b = \n"
@@ -313,10 +318,11 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  $set_has_field_bit_builder$\n"
@@ -324,10 +330,12 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $clear_has_field_bit_builder$\n");
+  printer->Annotate("{", "}", descriptor_);
   // The default value is not a simple literal so we want to avoid executing
   // it multiple times.  Instead, get the default out of the default instance.
   printer->Print(variables_,
@@ -339,9 +347,10 @@
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -482,14 +491,15 @@
   if (SupportFieldPresence(descriptor_->file())) {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
     "  return $has_oneof_case_message$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -500,6 +510,7 @@
     "    com.google.protobuf.ByteString bs = \n"
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
     "    if ($has_oneof_case_message$) {\n"
@@ -519,7 +530,7 @@
 
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -536,6 +547,7 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringOneofFieldGenerator::
@@ -543,14 +555,15 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $has_oneof_case_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -560,6 +573,7 @@
     "        (com.google.protobuf.ByteString) ref;\n"
     "    java.lang.String s = bs.toStringUtf8();\n"
     "    if ($has_oneof_case_message$) {\n");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "      $oneof_name$_ = s;\n");
@@ -580,7 +594,7 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.Object ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = $oneof_name$_;\n"
@@ -597,10 +611,11 @@
     "    return (com.google.protobuf.ByteString) ref;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  $set_oneof_case_message$;\n"
@@ -608,9 +623,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
@@ -618,12 +634,14 @@
     "  }\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -744,25 +762,30 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ProtocolStringList\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_;\n"   // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return $name$_.getByteString(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableStringFieldGenerator::
@@ -794,28 +817,33 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ProtocolStringList\n"
-    "    get$capitalized_name$List() {\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return $name$_.getUnmodifiableView();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return $name$_.getByteString(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, java.lang.String value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
@@ -823,9 +851,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  ensure$capitalized_name$IsMutable();\n"
@@ -833,9 +862,10 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<java.lang.String> values) {\n"
     "  ensure$capitalized_name$IsMutable();\n"
     "  com.google.protobuf.AbstractMessageLite.Builder.addAll(\n"
@@ -843,20 +873,23 @@
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  $name$_ = $empty_list$;\n"
     "  $clear_mutable_bit_builder$;\n"
     "  $on_changed$\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index 7e3ad1d..adda307 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -71,7 +71,7 @@
   (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["default_init"] =
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
-  (*variables)["capitalized_type"] = "String";
+  (*variables)["capitalized_type"] = "java.lang.String";
   (*variables)["tag"] =
       SimpleItoa(static_cast<int32>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = SimpleItoa(
@@ -192,22 +192,25 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return $get_has_field_bit_message$;\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  return $name$_;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  return com.google.protobuf.ByteString.copyFromUtf8($name$_);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -246,48 +249,54 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  return instance.get$capitalized_name$Bytes();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$Bytes(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringFieldLiteGenerator::
@@ -324,7 +333,7 @@
 GenerateParsingCode(io::Printer* printer) const {
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
-      "String s = input.readStringRequireUtf8();\n"
+      "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_has_field_bit_message$\n"
       "$name$_ = s;\n");
   } else {
@@ -333,7 +342,7 @@
     // spurious intermediary ByteString allocations, cutting overall allocations
     // in half.
     printer->Print(variables_,
-      "String s = input.readString();\n"
+      "java.lang.String s = input.readString();\n"
       "$set_has_field_bit_message$\n"
       "$name$_ = s;\n");
   }
@@ -410,54 +419,60 @@
   if (SupportFieldPresence(descriptor_->file())) {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public boolean has$capitalized_name$() {\n"
+    "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
     "  return $has_oneof_case_message$;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  java.lang.String ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = (java.lang.String) $oneof_name$_;\n"
     "  }\n"
     "  return ref;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
 
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  java.lang.String ref $default_init$;\n"
     "  if ($has_oneof_case_message$) {\n"
     "    ref = (java.lang.String) $oneof_name$_;\n"
     "  }\n"
     "  return com.google.protobuf.ByteString.copyFromUtf8(ref);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private void set$capitalized_name$(\n"
+    "private void ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "$null_check$"
     "  $set_oneof_case_message$;\n"
     "  $oneof_name$_ = value;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private void clear$capitalized_name$() {\n"
+    "private void ${$clear$capitalized_name$$}$() {\n"
     "  if ($has_oneof_case_message$) {\n"
     "    $clear_oneof_case_message$;\n"
     "    $oneof_name$_ = null;\n"
     "  }\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "private void set$capitalized_name$Bytes(\n"
+    "private void ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "$null_check$");
+  printer->Annotate("{", "}", descriptor_);
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
       "  checkByteStringIsUtf8(value);\n");
@@ -474,48 +489,54 @@
   if (SupportFieldPresence(descriptor_->file())) {
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
-      "$deprecation$public boolean has$capitalized_name$() {\n"
+      "$deprecation$public boolean ${$has$capitalized_name$$}$() {\n"
       "  return instance.has$capitalized_name$();\n"
       "}\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$() {\n"
+    "$deprecation$public java.lang.String ${$get$capitalized_name$$}$() {\n"
     "  return instance.get$capitalized_name$();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes() {\n"
+    "    ${$get$capitalized_name$Bytes$}$() {\n"
     "  return instance.get$capitalized_name$Bytes();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$Bytes(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringOneofFieldLiteGenerator::
@@ -529,7 +550,7 @@
 GenerateParsingCode(io::Printer* printer) const {
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
-      "String s = input.readStringRequireUtf8();\n"
+      "java.lang.String s = input.readStringRequireUtf8();\n"
       "$set_oneof_case_message$;\n"
       "$oneof_name$_ = s;\n");
   } else {
@@ -538,7 +559,7 @@
     // spurious intermediary ByteString allocations, cutting overall allocations
     // in half.
     printer->Print(variables_,
-      "String s = input.readString();\n"
+      "java.lang.String s = input.readString();\n"
       "$set_oneof_case_message$;\n"
       "$oneof_name$_ = s;\n");
   }
@@ -597,7 +618,7 @@
 GenerateInterfaceMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$java.util.List<String>\n"
+    "$deprecation$java.util.List<java.lang.String>\n"
     "    get$capitalized_name$List();\n");
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
@@ -615,30 +636,37 @@
 void RepeatedImmutableStringFieldLiteGenerator::
 GenerateMembers(io::Printer* printer) const {
   printer->Print(variables_,
-    "private com.google.protobuf.Internal.ProtobufList<String> $name$_;\n");
+    "private com.google.protobuf.Internal.ProtobufList<java.lang.String> "
+    "$name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<String> get$capitalized_name$List() {\n"
-    "  return $name$_;\n"   // note:  unmodifiable list
+    "$deprecation$public java.util.List<java.lang.String> "
+    "${$get$capitalized_name$List$}$() {\n"
+    "  return $name$_;\n"  // note:  unmodifiable list
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return $name$_.size();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return $name$_.get(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return com.google.protobuf.ByteString.copyFromUtf8(\n"
     "      $name$_.get(index));\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   printer->Print(variables_,
     "private void ensure$capitalized_name$IsMutable() {\n"
@@ -697,67 +725,77 @@
 GenerateBuilderMembers(io::Printer* printer) const {
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.util.List<String>\n"
-    "    get$capitalized_name$List() {\n"
+    "$deprecation$public java.util.List<java.lang.String>\n"
+    "    ${$get$capitalized_name$List$}$() {\n"
     "  return java.util.Collections.unmodifiableList(\n"
     "      instance.get$capitalized_name$List());\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public int get$capitalized_name$Count() {\n"
+    "$deprecation$public int ${$get$capitalized_name$Count$}$() {\n"
     "  return instance.get$capitalized_name$Count();\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n"
+    "$deprecation$public java.lang.String "
+    "${$get$capitalized_name$$}$(int index) {\n"
     "  return instance.get$capitalized_name$(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
     "$deprecation$public com.google.protobuf.ByteString\n"
-    "    get$capitalized_name$Bytes(int index) {\n"
+    "    ${$get$capitalized_name$Bytes$}$(int index) {\n"
     "  return instance.get$capitalized_name$Bytes(index);\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder set$capitalized_name$(\n"
+    "$deprecation$public Builder ${$set$capitalized_name$$}$(\n"
     "    int index, java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.set$capitalized_name$(index, value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$$}$(\n"
     "    java.lang.String value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder addAll$capitalized_name$(\n"
+    "$deprecation$public Builder ${$addAll$capitalized_name$$}$(\n"
     "    java.lang.Iterable<java.lang.String> values) {\n"
     "  copyOnWrite();\n"
     "  instance.addAll$capitalized_name$(values);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder clear$capitalized_name$() {\n"
+    "$deprecation$public Builder ${$clear$capitalized_name$$}$() {\n"
     "  copyOnWrite();\n"
     "  instance.clear$capitalized_name$();\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-    "$deprecation$public Builder add$capitalized_name$Bytes(\n"
+    "$deprecation$public Builder ${$add$capitalized_name$Bytes$}$(\n"
     "    com.google.protobuf.ByteString value) {\n"
     "  copyOnWrite();\n"
     "  instance.add$capitalized_name$Bytes(value);\n"
     "  return this;\n"
     "}\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::
@@ -787,14 +825,14 @@
 GenerateParsingCode(io::Printer* printer) const {
   if (CheckUtf8(descriptor_)) {
     printer->Print(variables_,
-    "String s = input.readStringRequireUtf8();\n");
+      "java.lang.String s = input.readStringRequireUtf8();\n");
   } else {
     // Lite runtime should attempt to reduce allocations by attempting to
     // construct the string directly from the input stream buffer. This avoids
     // spurious intermediary ByteString allocations, cutting overall allocations
     // in half.
     printer->Print(variables_,
-    "String s = input.readString();\n");
+      "java.lang.String s = input.readString();\n");
   }
   printer->Print(variables_,
     "if (!$is_mutable$) {\n"
@@ -868,7 +906,7 @@
 }
 
 string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const {
-  return "String";
+  return "java.lang.String";
 }
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
index 7666db3..26bc7f8 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -52,7 +52,7 @@
 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
 //   repeat code between this and the other field types.
 void SetEnumVariables(const Params& params,
-    const FieldDescriptor* descriptor, map<string, string>* variables) {
+    const FieldDescriptor* descriptor, std::map<string, string>* variables) {
   (*variables)["name"] =
     RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
   (*variables)["capitalized_name"] =
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
index b94790d..1be25d1 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -62,7 +62,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   vector<string> canonical_values_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
@@ -85,7 +85,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   vector<string> canonical_values_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorEnumFieldGenerator);
@@ -112,7 +112,7 @@
   void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
 
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
   vector<string> canonical_values_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc
index 0b9d1d8..4c61f91 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc
@@ -78,7 +78,7 @@
 }  // namespace
 
 void SetVariables(const FieldDescriptor* descriptor, const Params params,
-                  map<string, string>* variables) {
+                  std::map<string, string>* variables) {
   (*variables)["extends"] = ClassName(params, descriptor->containing_type());
   (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
   bool repeated = descriptor->is_repeated();
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/javanano/javanano_extension.h
index 4843e29..f4e9eb2 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.h
+++ b/src/google/protobuf/compiler/javanano/javanano_extension.h
@@ -61,7 +61,7 @@
  private:
   const Params& params_;
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
 };
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
index 85257f3..e31d117 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_field.cc
@@ -151,7 +151,7 @@
 }
 
 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables) {
+                             std::map<string, string>* variables) {
   (*variables)["oneof_name"] =
       UnderscoresToCamelCase(descriptor->containing_oneof());
   (*variables)["oneof_capitalized_name"] =
@@ -169,7 +169,7 @@
 }
 
 void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
-                              const map<string, string>& variables,
+                              const std::map<string, string>& variables,
                               io::Printer* printer) {
   if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
     printer->Print(variables,
@@ -190,7 +190,7 @@
 }
 
 void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
-                                const map<string, string>& variables,
+                                const std::map<string, string>& variables,
                                 io::Printer* printer) {
   if (GetJavaType(descriptor) == JAVATYPE_BYTES) {
     printer->Print(variables,
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
index 57c221f..347c888 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -114,12 +114,12 @@
 };
 
 void SetCommonOneofVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables);
+                             std::map<string, string>* variables);
 void GenerateOneofFieldEquals(const FieldDescriptor* descriptor,
-                              const map<string, string>& variables,
+                              const std::map<string, string>& variables,
                               io::Printer* printer);
 void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor,
-                                const map<string, string>& variables,
+                                const std::map<string, string>& variables,
                                 io::Printer* printer);
 
 }  // namespace javanano
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
index 5018250..1927ba1 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -567,7 +567,7 @@
 }
 
 void SetBitOperationVariables(const string name,
-    int bitIndex, map<string, string>* variables) {
+    int bitIndex, std::map<string, string>* variables) {
   (*variables)["get_" + name] = GenerateGetBit(bitIndex);
   (*variables)["set_" + name] = GenerateSetBit(bitIndex);
   (*variables)["clear_" + name] = GenerateClearBit(bitIndex);
diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
index 014c85a..04b2d63 100644
--- a/src/google/protobuf/compiler/javanano/javanano_helpers.h
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h
@@ -181,7 +181,7 @@
 // the given name of the bit, to the appropriate Java expressions for the given
 // bit index.
 void SetBitOperationVariables(const string name,
-    int bitIndex, map<string, string>* variables);
+    int bitIndex, std::map<string, string>* variables);
 
 inline bool IsMapEntry(const Descriptor* descriptor) {
   // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well.
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
index 83b2b0c..a4ab885 100644
--- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
@@ -84,7 +84,7 @@
 }
 
 void SetMapVariables(const Params& params,
-    const FieldDescriptor* descriptor, map<string, string>* variables) {
+    const FieldDescriptor* descriptor, std::map<string, string>* variables) {
   const FieldDescriptor* key = KeyField(descriptor);
   const FieldDescriptor* value = ValueField(descriptor);
   (*variables)["name"] =
diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h
index c01bde3..81e5915 100644
--- a/src/google/protobuf/compiler/javanano/javanano_map_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h
@@ -58,7 +58,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index f81f7f9..7842188 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -182,7 +182,7 @@
   }
 
   // oneof
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["message_name"] = descriptor_->name();
   for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
     const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i);
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index d1d04b5..2ed8a3a 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -54,7 +54,7 @@
 // TODO(kenton):  Factor out a "SetCommonFieldVariables()" to get rid of
 //   repeat code between this and the other field types.
 void SetMessageVariables(const Params& params,
-    const FieldDescriptor* descriptor, map<string, string>* variables) {
+    const FieldDescriptor* descriptor, std::map<string, string>* variables) {
   (*variables)["name"] =
     RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
   (*variables)["capitalized_name"] =
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
index e074735..0ae8879 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -62,7 +62,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
 };
@@ -85,7 +85,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
 };
@@ -108,7 +108,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
index e3b4bb9..3594767 100644
--- a/src/google/protobuf/compiler/javanano/javanano_params.h
+++ b/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -47,8 +47,8 @@
 // Parameters for used by the generators
 class Params {
  public:
-  typedef map<string, string> NameMap;
-  typedef set<string> NameSet;
+  typedef std::map<string, string> NameMap;
+  typedef std::set<string> NameSet;
  private:
   string empty_;
   string base_name_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index 978abf2..66a0ff0 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -166,7 +166,7 @@
 
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   (*variables)["name"] =
     RenameJavaKeywords(UnderscoresToCamelCase(descriptor));
   (*variables)["capitalized_name"] =
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
index a01981d..d7d72d5 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -65,7 +65,7 @@
   void GenerateSerializationConditional(io::Printer* printer) const;
 
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
 };
@@ -89,7 +89,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator);
 };
@@ -111,7 +111,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator);
 };
@@ -137,7 +137,7 @@
   void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
 
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
 };
diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
index 7c63e58..73d3276 100755
--- a/src/google/protobuf/compiler/js/js_generator.cc
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -143,12 +143,16 @@
   return false;
 }
 
+bool StrEndsWith(StringPiece sp, StringPiece x) {
+  return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
+}
+
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // suffix stripped.
 // TODO(haberman): Unify with copy in compiler/cpp/internal/helpers.cc.
 string StripProto(const string& filename) {
-  const char* suffix = HasSuffixString(filename, ".protodevel")
-      ? ".protodevel" : ".proto";
+  const char* suffix =
+      StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
   return StripSuffixString(filename, suffix);
 }
 
@@ -193,6 +197,7 @@
   string basename = StripProto(filename);
   StripString(&basename, "-", '$');
   StripString(&basename, "/", '_');
+  StripString(&basename, ".", '_');
   return basename + "_pb";
 }
 
@@ -756,8 +761,22 @@
   return PostProcessFloat(result);
 }
 
+// Return true if this is an integral field that should be represented as string
+// in JS.
+bool IsIntegralFieldWithStringJSType(const FieldDescriptor* field) {
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT64:
+      // The default value of JSType is JS_NORMAL, which behaves the same as
+      // JS_NUMBER.
+      return field->options().jstype() == google::protobuf::FieldOptions::JS_STRING;
+    default:
+      return false;
+  }
+}
+
 string MaybeNumberString(const FieldDescriptor* field, const string& orig) {
-  return orig;
+  return IsIntegralFieldWithStringJSType(field) ? ("\"" + orig + "\"") : orig;
 }
 
 string JSFieldDefault(const FieldDescriptor* field) {
@@ -856,7 +875,7 @@
 }
 
 string JSIntegerTypeName(const FieldDescriptor* field) {
-  return "number";
+  return IsIntegralFieldWithStringJSType(field) ? "string" : "number";
 }
 
 string JSStringTypeName(const GeneratorOptions& options,
@@ -1033,8 +1052,7 @@
   if (name[0] >= 'a' && name[0] <= 'z') {
     name[0] = (name[0] - 'a') + 'A';
   }
-
-  return name;
+  return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name;
 }
 
 string JSBinaryReadWriteMethodName(const FieldDescriptor* field,
@@ -1244,13 +1262,6 @@
         " * You should avoid comparisons like {@code val === true/false} in "
         "those cases.\n";
   }
-  if (field->is_repeated()) {
-    comments +=
-        " * If you change this array by adding, removing or replacing "
-        "elements, or if you\n"
-        " * replace the array itself, then you must call the setter to "
-        "update it.\n";
-  }
   if (field->type() == FieldDescriptor::TYPE_BYTES && bytes_mode == BYTES_U8) {
     comments +=
         " * Note that Uint8Array is not supported on all browsers.\n"
@@ -1323,7 +1334,7 @@
 // Returns the max index in the underlying data storage array beyond which the
 // extension object is used.
 string GetPivot(const Descriptor* desc) {
-  static const int kDefaultPivot = (1 << 29);  // max field number (29 bits)
+  static const int kDefaultPivot = 500;
 
   // Find the max field number
   int max_field_number = 0;
@@ -1335,7 +1346,7 @@
   }
 
   int pivot = -1;
-  if (IsExtendable(desc)) {
+  if (IsExtendable(desc) || (max_field_number >= kDefaultPivot)) {
     pivot = ((max_field_number + 1) < kDefaultPivot) ?
         (max_field_number + 1) : kDefaultPivot;
   }
@@ -1507,6 +1518,10 @@
   printer->Print("/**\n"
                  " * @fileoverview\n"
                  " * @enhanceable\n"
+                 " * @suppress {messageConventions} JS Compiler reports an "
+                 "error if a variable or\n"
+                 " *     field starts with 'MSG_' and isn't a translatable "
+                 "message.\n"
                  " * @public\n"
                  " */\n"
                  "// GENERATED CODE -- DO NOT EDIT!\n"
@@ -1698,18 +1713,16 @@
                                      bool require_jspb, bool require_extension,
                                      bool require_map) const {
   if (require_jspb) {
-    printer->Print(
-        "goog.require('jspb.Message');\n"
-        "goog.require('jspb.BinaryReader');\n"
-        "goog.require('jspb.BinaryWriter');\n");
+    required->insert("jspb.Message");
+    required->insert("jspb.BinaryReader");
+    required->insert("jspb.BinaryWriter");
   }
   if (require_extension) {
-    printer->Print("goog.require('jspb.ExtensionFieldBinaryInfo');\n");
-    printer->Print(
-        "goog.require('jspb.ExtensionFieldInfo');\n");
+    required->insert("jspb.ExtensionFieldBinaryInfo");
+    required->insert("jspb.ExtensionFieldInfo");
   }
   if (require_map) {
-    printer->Print("goog.require('jspb.Map');\n");
+    required->insert("jspb.Map");
   }
 
   std::set<string>::iterator it;
@@ -2037,6 +2050,7 @@
       " *     http://goto/soy-param-migration\n"
       " * @param {!$classname$} msg The msg instance to transform.\n"
       " * @return {!Object}\n"
+      " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
       " */\n"
       "$classname$.toObject = function(includeInstance, msg) {\n"
       "  var f, obj = {",
@@ -2125,7 +2139,8 @@
             "obj", obj_reference);
       }
     } else {
-      printer->Print("jspb.Message.getField($obj$, $index$)",
+      printer->Print("jspb.Message.get$cardinality$Field($obj$, $index$)",
+                     "cardinality", field->is_repeated() ? "Repeated" : "",
                      "index", JSFieldIndex(field),
                      "obj", obj_reference);
     }
@@ -2333,7 +2348,6 @@
       "defname", JSGetterName(options, field, BYTES_DEFAULT));
 }
 
-
 void Generator::GenerateClassField(const GeneratorOptions& options,
                                    io::Printer* printer,
                                    const FieldDescriptor* field) const {
@@ -2463,7 +2477,7 @@
     // Simple (primitive) field, either singular or repeated.
 
     // TODO(b/26173701): Always use BYTES_DEFAULT for the getter return type;
-    // at this point we "lie" to non-binary users and tell the the return
+    // at this point we "lie" to non-binary users and tell the return
     // type is always base64 string, pending a LSC to migrate to typed getters.
     BytesMode bytes_mode =
         field->type() == FieldDescriptor::TYPE_BYTES && !options.binary ?
@@ -2910,6 +2924,7 @@
       " * format), writing to the given BinaryWriter.\n"
       " * @param {!$class$} message\n"
       " * @param {!jspb.BinaryWriter} writer\n"
+      " * @suppress {unusedLocalVariables} f is only used for nested messages\n"
       " */\n"
       "$class$.serializeBinaryToWriter = function(message, "
       "writer) {\n"
@@ -2982,7 +2997,13 @@
         case FieldDescriptor::CPPTYPE_INT64:
         case FieldDescriptor::CPPTYPE_UINT32:
         case FieldDescriptor::CPPTYPE_UINT64: {
-          {
+          if (IsIntegralFieldWithStringJSType(field)) {
+            // We can use `parseInt` here even though it will not be precise for
+            // 64-bit quantities because we are only testing for zero/nonzero,
+            // and JS numbers (64-bit floating point values, i.e., doubles) are
+            // integer-precise in the range that includes zero.
+            printer->Print("  if (parseInt(f, 10) !== 0) {\n");
+          } else {
             printer->Print("  if (f !== 0) {\n");
           }
           break;
@@ -3306,7 +3327,8 @@
       printer->Print(
           "var $alias$ = require('$file$');\n",
           "alias", ModuleAlias(name),
-          "file", GetRootPath(file->name(), name) + GetJSFilename(options, name));
+          "file",
+          GetRootPath(file->name(), name) + GetJSFilename(options, name));
     }
   }
 
diff --git a/src/google/protobuf/compiler/js/well_known_types/any.js b/src/google/protobuf/compiler/js/well_known_types/any.js
index 22f1891..d7ca6e3 100644
--- a/src/google/protobuf/compiler/js/well_known_types/any.js
+++ b/src/google/protobuf/compiler/js/well_known_types/any.js
@@ -69,7 +69,7 @@
  *     the binary data properly.
  * @param {string} name The expected type name of this message object.
  * @return {?T} If the name matched the expected name, returns the deserialized
- *     object, otherwise returns undefined.
+ *     object, otherwise returns null.
  */
 proto.google.protobuf.Any.prototype.unpack = function(deserialize, name) {
   if (this.getTypeName() == name) {
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 0ddb99e..cc660f4 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -40,6 +40,7 @@
 #endif
 #include <vector>
 
+
 #include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/stubs/logging.h>
@@ -52,9 +53,17 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/text_format.h>
 #include <google/protobuf/stubs/substitute.h>
 #include <gtest/gtest.h>
 
+#ifdef major		
+#undef major		
+#endif		
+#ifdef minor		
+#undef minor		
+#endif		
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -129,11 +138,48 @@
   }
 }
 
+namespace {
+void CheckSingleAnnotation(const string& expected_file,
+                           const string& expected_text,
+                           const string& file_content,
+                           const GeneratedCodeInfo::Annotation& annotation) {
+  EXPECT_EQ(expected_file, annotation.source_file());
+  ASSERT_GE(file_content.size(), annotation.begin());
+  ASSERT_GE(file_content.size(), annotation.end());
+  ASSERT_LE(annotation.begin(), annotation.end());
+  EXPECT_EQ(expected_text.size(), annotation.end() - annotation.begin());
+  EXPECT_EQ(expected_text,
+            file_content.substr(annotation.begin(), expected_text.size()));
+}
+}  // anonymous namespace
+
+void MockCodeGenerator::CheckGeneratedAnnotations(
+    const string& name, const string& file, const string& output_directory) {
+  string file_content;
+  GOOGLE_CHECK_OK(
+      File::GetContents(output_directory + "/" + GetOutputFileName(name, file),
+                        &file_content, true));
+  string meta_content;
+  GOOGLE_CHECK_OK(File::GetContents(
+      output_directory + "/" + GetOutputFileName(name, file) + ".meta",
+      &meta_content, true));
+  GeneratedCodeInfo annotations;
+  GOOGLE_CHECK(TextFormat::ParseFromString(meta_content, &annotations));
+  ASSERT_EQ(3, annotations.annotation_size());
+  CheckSingleAnnotation("first_annotation", "first", file_content,
+                        annotations.annotation(0));
+  CheckSingleAnnotation("second_annotation", "second", file_content,
+                        annotations.annotation(1));
+  CheckSingleAnnotation("third_annotation", "third", file_content,
+                        annotations.annotation(2));
+}
+
 bool MockCodeGenerator::Generate(
     const FileDescriptor* file,
     const string& parameter,
     GeneratorContext* context,
     string* error) const {
+  bool annotate = false;
   for (int i = 0; i < file->message_type_count(); i++) {
     if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
       string command = StripPrefixString(file->message_type(i)->name(),
@@ -162,6 +208,8 @@
         std::cerr << "Saw json_name: "
                   << field_descriptor_proto.has_json_name() << std::endl;
         abort();
+      } else if (command == "Annotate") {
+        annotate = true;
       } else if (command == "ShowVersionNumber") {
         Version compiler_version;
         context->GetCompilerVersion(&compiler_version);
@@ -212,16 +260,40 @@
     google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
         context->Open(GetOutputFileName(name_, file)));
 
-    io::Printer printer(output.get(), '$');
-    printer.PrintRaw(GetOutputFileContent(name_, parameter,
-                                          file, context));
+    GeneratedCodeInfo annotations;
+    io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+        &annotations);
+    io::Printer printer(output.get(), '$',
+                        annotate ? &annotation_collector : NULL);
+    printer.PrintRaw(GetOutputFileContent(name_, parameter, file, context));
+    string annotate_suffix = "_annotation";
+    if (annotate) {
+      printer.Print("$p$", "p", "first");
+      printer.Annotate("p", "first" + annotate_suffix);
+    }
     printer.PrintRaw(kFirstInsertionPoint);
+    if (annotate) {
+      printer.Print("$p$", "p", "second");
+      printer.Annotate("p", "second" + annotate_suffix);
+    }
     printer.PrintRaw(kSecondInsertionPoint);
+    if (annotate) {
+      printer.Print("$p$", "p", "third");
+      printer.Annotate("p", "third" + annotate_suffix);
+    }
 
     if (printer.failed()) {
       *error = "MockCodeGenerator detected write error.";
       return false;
     }
+    if (annotate) {
+      google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> meta_output(
+          context->Open(GetOutputFileName(name_, file) + ".meta"));
+      if (!TextFormat::Print(annotations, meta_output.get())) {
+        *error = "MockCodeGenerator couldn't write .meta";
+        return false;
+      }
+    }
   }
 
   return true;
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index e1665f8..cdd9138 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -68,6 +68,8 @@
 //     printing "Saw message type MockCodeGenerator_HasSourceCodeInfo: FOO." to
 //     stderr, where FOO is "1" if the supplied FileDescriptorProto has source
 //     code info, and "0" otherwise.
+//   MockCodeGenerator_Annotate:  Generate() will add annotations to its output
+//     that can later be verified with CheckGeneratedAnnotations.
 class MockCodeGenerator : public CodeGenerator {
  public:
   MockCodeGenerator(const string& name);
@@ -88,6 +90,12 @@
                               const string& parsed_file_list,
                               const string& output_directory);
 
+  // Checks that the correct text ranges were annotated by the
+  // MockCodeGenerator_Annotate directive.
+  static void CheckGeneratedAnnotations(const string& name,
+                                        const string& file,
+                                        const string& output_directory);
+
   // Get the name of the file which would be written by the given generator.
   static string GetOutputFileName(const string& generator_name,
                                   const FileDescriptor* file);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
index 7a774a0..8899a13 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -46,7 +46,7 @@
 namespace {
 
 void SetEnumVariables(const FieldDescriptor* descriptor,
-                      map<string, string>* variables) {
+                      std::map<string, string>* variables) {
   string type = EnumName(descriptor->enum_type());
   (*variables)["storage_type"] = type;
   // For non repeated fields, if it was defined in a different file, the
@@ -118,7 +118,7 @@
 }
 
 void EnumFieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
   SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // If it is an enum defined in a different file, then we'll need a forward
   // declaration for it.  When it is in our file, all the enums are output
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
index 946faa8..ae56c06 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -47,7 +47,7 @@
  public:
   virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
  protected:
   EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
index 73e4b86..b788d0a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -59,7 +59,7 @@
 ExtensionGenerator::~ExtensionGenerator() {}
 
 void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["method_name"] = method_name_;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
@@ -77,7 +77,7 @@
 
 void ExtensionGenerator::GenerateStaticVariablesInitialization(
     io::Printer* printer) {
-  map<string, string> vars;
+  std::map<string, string> vars;
   vars["root_class_and_method_name"] = root_class_and_method_name_;
   vars["extended_type"] = ClassName(descriptor_->containing_type());
   vars["number"] = SimpleItoa(descriptor_->number());
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
index 9f7e84f..b6123fa 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -49,7 +49,7 @@
 namespace {
 
 void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             map<string, string>* variables) {
+                             std::map<string, string>* variables) {
   string camel_case_name = FieldName(descriptor);
   string raw_field_name;
   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
@@ -178,7 +178,7 @@
 }
 
 void FieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
   // Nothing
 }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
index a3a4b1b..6bd5db2 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -67,7 +67,7 @@
   virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
 
   // Exposed for subclasses, should always call it on the parent class also.
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
   // Used during generation, not intended to be extended by subclasses.
   void GenerateFieldDescription(
@@ -100,7 +100,7 @@
   virtual bool WantsHasProperty(void) const = 0;
 
   const FieldDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
index 7ad127b..954b268 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -89,7 +89,7 @@
 void PruneFileAndDepsMarkingAsVisited(
     const FileDescriptor* file,
     vector<const FileDescriptor*>* files,
-    set<const FileDescriptor*>* files_visited) {
+    std::set<const FileDescriptor*>* files_visited) {
   vector<const FileDescriptor*>::iterator iter =
       std::find(files->begin(), files->end(), file);
   if (iter != files->end()) {
@@ -105,7 +105,7 @@
 void CollectMinimalFileDepsContainingExtensionsWorker(
     const FileDescriptor* file,
     vector<const FileDescriptor*>* files,
-    set<const FileDescriptor*>* files_visited) {
+    std::set<const FileDescriptor*>* files_visited) {
   if (files_visited->find(file) != files_visited->end()) {
     return;
   }
@@ -138,7 +138,7 @@
 void CollectMinimalFileDepsContainingExtensions(
     const FileDescriptor* file,
     vector<const FileDescriptor*>* files) {
-  set<const FileDescriptor*> files_visited;
+  std::set<const FileDescriptor*> files_visited;
   for (int i = 0; i < file->dependency_count(); i++) {
     const FileDescriptor* dep = file->dependency(i);
     CollectMinimalFileDepsContainingExtensionsWorker(dep, files,
@@ -229,12 +229,12 @@
       "CF_EXTERN_C_BEGIN\n"
       "\n");
 
-  set<string> fwd_decls;
+  std::set<string> fwd_decls;
   for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
        iter != message_generators_.end(); ++iter) {
     (*iter)->DetermineForwardDeclarations(&fwd_decls);
   }
-  for (set<string>::const_iterator i(fwd_decls.begin());
+  for (std::set<string>::const_iterator i(fwd_decls.begin());
        i != fwd_decls.end(); ++i) {
     printer->Print("$value$;\n", "value", *i);
   }
@@ -325,7 +325,7 @@
 
     // #import the headers for anything that a plain dependency of this proto
     // file (that means they were just an include, not a "public" include).
-    set<string> public_import_names;
+    std::set<string> public_import_names;
     for (int i = 0; i < file_->public_dependency_count(); i++) {
       public_import_names.insert(file_->public_dependency(i)->name());
     }
@@ -468,7 +468,7 @@
 
   // File descriptor only needed if there are messages to use it.
   if (message_generators_.size() > 0) {
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["root_class_name"] = root_class_name_;
     vars["package"] = file_->package();
     vars["objc_prefix"] = FileClassPrefix(file_);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 1ea2676..54dc745 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -28,9 +28,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <climits>
@@ -49,8 +47,15 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/strutil.h>
 
+#if defined(_MSC_VER)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::open;
+#endif
+
 // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
 // error cases, so it seems to be ok to use as a back door for errors.
 
@@ -196,7 +201,7 @@
     // method declared in protos. The main cases are methods
     // that take no arguments, or setFoo:/hasFoo: type methods.
     "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
-    "extensionsCurrentlySet", "isInitialized", "serializedSize",
+    "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
     "sortedExtensionsInUse", "unknownFields",
 
     // MacTypes.h names
@@ -980,13 +985,13 @@
 
 class ExpectedPrefixesCollector : public LineConsumer {
  public:
-  ExpectedPrefixesCollector(map<string, string>* inout_package_to_prefix_map)
+  ExpectedPrefixesCollector(std::map<string, string>* inout_package_to_prefix_map)
       : prefix_map_(inout_package_to_prefix_map) {}
 
   virtual bool ConsumeLine(const StringPiece& line, string* out_error);
 
  private:
-  map<string, string>* prefix_map_;
+  std::map<string, string>* prefix_map_;
 };
 
 bool ExpectedPrefixesCollector::ConsumeLine(
@@ -1009,7 +1014,7 @@
 }
 
 bool LoadExpectedPackagePrefixes(const Options &generation_options,
-                                 map<string, string>* prefix_map,
+                                 std::map<string, string>* prefix_map,
                                  string* out_error) {
   if (generation_options.expected_prefixes_path.empty()) {
     return true;
@@ -1023,7 +1028,7 @@
 bool ValidateObjCClassPrefix(
     const FileDescriptor* file,
     const string& expected_prefixes_path,
-    const map<string, string>& expected_package_prefixes,
+    const std::map<string, string>& expected_package_prefixes,
     string* out_error) {
   const string prefix = file->options().objc_class_prefix();
   const string package = file->package();
@@ -1033,7 +1038,7 @@
 
   // Check: Error - See if there was an expected prefix for the package and
   // report if it doesn't match (wrong or missing).
-  map<string, string>::const_iterator package_match =
+  std::map<string, string>::const_iterator package_match =
       expected_package_prefixes.find(package);
   if (package_match != expected_package_prefixes.end()) {
     // There was an entry, and...
@@ -1082,7 +1087,7 @@
 
   // Look for any other package that uses the same prefix.
   string other_package_for_prefix;
-  for (map<string, string>::const_iterator i = expected_package_prefixes.begin();
+  for (std::map<string, string>::const_iterator i = expected_package_prefixes.begin();
        i != expected_package_prefixes.end(); ++i) {
     if (i->second == prefix) {
       other_package_for_prefix = i->first;
@@ -1150,7 +1155,7 @@
                                const Options& generation_options,
                                string* out_error) {
   // Load the expected package prefixes, if available, to validate against.
-  map<string, string> expected_package_prefixes;
+  std::map<string, string> expected_package_prefixes;
   if (!LoadExpectedPackagePrefixes(generation_options,
                                    &expected_package_prefixes,
                                    out_error)) {
@@ -1519,7 +1524,7 @@
     ParseFrameworkMappings();
   }
 
-  map<string, string>::iterator proto_lookup =
+  std::map<string, string>::iterator proto_lookup =
       proto_file_to_framework_name_.find(file->name());
   if (proto_lookup != proto_file_to_framework_name_.end()) {
     other_framework_imports_.push_back(
@@ -1640,7 +1645,7 @@
     StringPiece proto_file(proto_file_list, start, offset - start);
     StringPieceTrimWhitespace(&proto_file);
     if (proto_file.size() != 0) {
-      map<string, string>::iterator existing_entry =
+      std::map<string, string>::iterator existing_entry =
           map_->find(proto_file.ToString());
       if (existing_entry != map_->end()) {
         std::cerr << "warning: duplicate proto file reference, replacing framework entry for '"
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index c99262a..daea760 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -262,20 +262,20 @@
  private:
   class ProtoFrameworkCollector : public LineConsumer {
    public:
-    ProtoFrameworkCollector(map<string, string>* inout_proto_file_to_framework_name)
+    ProtoFrameworkCollector(std::map<string, string>* inout_proto_file_to_framework_name)
         : map_(inout_proto_file_to_framework_name) {}
 
     virtual bool ConsumeLine(const StringPiece& line, string* out_error);
 
    private:
-    map<string, string>* map_;
+    std::map<string, string>* map_;
   };
 
   void ParseFrameworkMappings();
 
   const string generate_for_named_framework_;
   const string named_framework_to_proto_path_mappings_path_;
-  map<string, string> proto_file_to_framework_name_;
+  std::map<string, string> proto_file_to_framework_name_;
   bool need_to_parse_mapping_file_;
 
   vector<string> protobuf_framework_imports_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
index 0bc9dc1..bcaf570 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -162,7 +162,7 @@
 }
 
 void MapFieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
   RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->FindFieldByName("value");
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
index bc68a68..6664d84 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -51,7 +51,7 @@
   MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
   virtual ~MapFieldGenerator();
 
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
  private:
   scoped_ptr<FieldGenerator> value_field_generator_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
index 0a554a8..4f22e29 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -233,7 +233,7 @@
   }
 }
 
-void MessageGenerator::DetermineForwardDeclarations(set<string>* fwd_decls) {
+void MessageGenerator::DetermineForwardDeclarations(std::set<string>* fwd_decls) {
   if (!IsMapEntryMessage(descriptor_)) {
     for (int i = 0; i < descriptor_->field_count(); i++) {
       const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
@@ -514,7 +514,7 @@
           "    };\n");
     }
 
-    map<string, string> vars;
+    std::map<string, string> vars;
     vars["classname"] = class_name_;
     vars["rootclassname"] = root_classname_;
     vars["fields"] = has_fields ? "fields" : "NULL";
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
index 0fb78bc..8f317ac 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -64,7 +64,7 @@
   void GenerateMessageHeader(io::Printer* printer);
   void GenerateSource(io::Printer* printer);
   void GenerateExtensionRegistrationSource(io::Printer* printer);
-  void DetermineForwardDeclarations(set<string>* fwd_decls);
+  void DetermineForwardDeclarations(std::set<string>* fwd_decls);
 
   // Checks if the message or a nested message includes a oneof definition.
   bool IncludesOneOfDefinition() const;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
index d6ccd6d..699d25b 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -45,7 +45,7 @@
 namespace {
 
 void SetMessageVariables(const FieldDescriptor* descriptor,
-                         map<string, string>* variables) {
+                         std::map<string, string>* variables) {
   const string& message_type = ClassName(descriptor->message_type());
   (*variables)["type"] = message_type;
   (*variables)["containing_class"] = ClassName(descriptor->containing_type());
@@ -67,7 +67,7 @@
 MessageFieldGenerator::~MessageFieldGenerator() {}
 
 void MessageFieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
   ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // Class name is already in "storage_type".
   fwd_decls->insert("@class " + variable("storage_type"));
@@ -95,7 +95,7 @@
 RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
 
 void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
-    set<string>* fwd_decls) const {
+    std::set<string>* fwd_decls) const {
   RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls);
   // Class name is already in "storage_type".
   fwd_decls->insert("@class " + variable("storage_type"));
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
index d2dba15..50f4b6d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -51,7 +51,7 @@
   virtual bool WantsHasProperty(void) const;
 
  public:
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
@@ -67,7 +67,7 @@
   virtual ~RepeatedMessageFieldGenerator();
 
  public:
-  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+  virtual void DetermineForwardDeclarations(std::set<string>* fwd_decls) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
index 3d9df4d..ff353a6 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -67,7 +67,7 @@
 
  private:
   const OneofDescriptor* descriptor_;
-  map<string, string> variables_;
+  std::map<string, string> variables_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator);
 };
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
index d49350f..aa8ac32 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -118,7 +118,7 @@
 }
 
 void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           map<string, string>* variables) {
+                           std::map<string, string>* variables) {
   std::string primitive_name = PrimitiveTypeName(descriptor);
   (*variables)["type"] = primitive_name;
   (*variables)["storage_type"] = primitive_name;
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 1a40956..bb4a44c 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -664,7 +664,7 @@
 
 namespace {
 
-const int kMaxExtensionRangeSentinel = -1;
+const int kMaxRangeSentinel = -1;
 
 bool IsMessageSetWireFormatMessage(const DescriptorProto& message) {
   const MessageOptions& options = message.options();
@@ -688,12 +688,27 @@
       kint32max :
       FieldDescriptor::kMaxNumber + 1;
   for (int i = 0; i < message->extension_range_size(); ++i) {
-    if (message->extension_range(i).end() == kMaxExtensionRangeSentinel) {
+    if (message->extension_range(i).end() == kMaxRangeSentinel) {
       message->mutable_extension_range(i)->set_end(max_extension_number);
     }
   }
 }
 
+// Modifies any reserved ranges that specified 'max' as the end of the
+// reserved range, and sets them to the type-specific maximum. The actual max
+// tag number can only be determined after all options have been parsed.
+void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) {
+  const bool is_message_set = IsMessageSetWireFormatMessage(*message);
+  const int max_field_number = is_message_set ?
+      kint32max :
+      FieldDescriptor::kMaxNumber + 1;
+  for (int i = 0; i < message->reserved_range_size(); ++i) {
+    if (message->reserved_range(i).end() == kMaxRangeSentinel) {
+      message->mutable_reserved_range(i)->set_end(max_field_number);
+    }
+  }
+}
+
 }  // namespace
 
 bool Parser::ParseMessageBlock(DescriptorProto* message,
@@ -717,6 +732,9 @@
   if (message->extension_range_size() > 0) {
     AdjustExtensionRangesWithMaxEndNumber(message);
   }
+  if (message->reserved_range_size() > 0) {
+    AdjustReservedRangesWithMaxEndNumber(message);
+  }
   return true;
 }
 
@@ -1429,6 +1447,8 @@
   // Parse the declaration.
   DO(Consume("extensions"));
 
+  int old_range_size = message->extension_range_size();
+
   do {
     // Note that kExtensionRangeFieldNumber was already pushed by the parent.
     LocationRecorder location(extensions_location,
@@ -1455,7 +1475,7 @@
         // Set to the sentinel value - 1 since we increment the value below.
         // The actual value of the end of the range should be set with
         // AdjustExtensionRangesWithMaxEndNumber.
-        end = kMaxExtensionRangeSentinel - 1;
+        end = kMaxRangeSentinel - 1;
       } else {
         DO(ConsumeInteger(&end, "Expected integer."));
       }
@@ -1475,12 +1495,36 @@
     range->set_end(end);
   } while (TryConsume(","));
 
+  if (LookingAt("[")) {
+    LocationRecorder location(
+        extensions_location,
+        DescriptorProto::ExtensionRange::kOptionsFieldNumber);
+
+    DO(Consume("["));
+
+    // Parse extension range options in the first range.
+    ExtensionRangeOptions* options =
+        message->mutable_extension_range(old_range_size)->mutable_options();
+    do {
+      DO(ParseOption(options, location, containing_file, OPTION_ASSIGNMENT));
+    } while (TryConsume(","));
+
+    DO(Consume("]"));
+
+    // Then copy the extension range options to all of the other ranges we've
+    // parsed.
+    for (int i = old_range_size + 1; i < message->extension_range_size(); i++) {
+      message->mutable_extension_range(i)->mutable_options()
+          ->CopyFrom(*options);
+    }
+  }
+
   DO(ConsumeEndOfDeclaration(";", &extensions_location));
   return true;
 }
 
-// This is similar to extension range parsing, except that "max" is not
-// supported, and accepts field name literals.
+// This is similar to extension range parsing, except that it accepts field
+// name literals.
 bool Parser::ParseReserved(DescriptorProto* message,
                            const LocationRecorder& message_location) {
   // Parse the declaration.
@@ -1528,7 +1572,14 @@
     if (TryConsume("to")) {
       LocationRecorder end_location(
           location, DescriptorProto::ReservedRange::kEndFieldNumber);
-      DO(ConsumeInteger(&end, "Expected integer."));
+      if (TryConsume("max")) {
+        // Set to the sentinel value - 1 since we increment the value below.
+        // The actual value of the end of the range should be set with
+        // AdjustExtensionRangesWithMaxEndNumber.
+        end = kMaxRangeSentinel - 1;
+      } else {
+        DO(ConsumeInteger(&end, "Expected integer."));
+      }
     } else {
       LocationRecorder end_location(
           location, DescriptorProto::ReservedRange::kEndFieldNumber);
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index d5e3132..97831f7 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -663,7 +663,7 @@
   ExpectParsesTo(
     "message TestMessage {\n"
     "  required int32 foo = 1;\n"
-    "  reserved 2, 15, 9 to 11, 3;\n"
+    "  reserved 2, 15, 9 to 11, 3, 20 to max;\n"
     "}\n",
 
     "message_type {"
@@ -673,6 +673,29 @@
     "  reserved_range { start:15  end:16        }"
     "  reserved_range { start:9   end:12        }"
     "  reserved_range { start:3   end:4         }"
+    "  reserved_range { start:20  end:536870912 }"
+    "}");
+}
+
+TEST_F(ParseMessageTest, ReservedRangeOnMessageSet) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  option message_set_wire_format = true;\n"
+    "  reserved 20 to max;\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  options {"
+    "    uninterpreted_option {"
+    "      name {"
+    "        name_part: \"message_set_wire_format\""
+    "        is_extension: false"
+    "      }"
+    "      identifier_value: \"true\""
+    "    }"
+    "  }"
+    "  reserved_range { start:20  end:2147483647 }"
     "}");
 }
 
@@ -703,6 +726,30 @@
     "}");
 }
 
+TEST_F(ParseMessageTest, ExtensionRangeWithOptions) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 10 to 19 [(i) = 5];\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension_range {"
+    "    start:10"
+    "    end:20"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "}");
+}
+
 TEST_F(ParseMessageTest, CompoundExtensionRange) {
   ExpectParsesTo(
     "message TestMessage {\n"
@@ -719,6 +766,82 @@
     "}");
 }
 
+TEST_F(ParseMessageTest, CompoundExtensionRangeWithOptions) {
+  ExpectParsesTo(
+    "message TestMessage {\n"
+    "  extensions 2, 15, 9 to 11, 100 to max, 3 [(i) = 5];\n"
+    "}\n",
+
+    "message_type {"
+    "  name: \"TestMessage\""
+    "  extension_range {"
+    "    start:2"
+    "    end:3"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:15"
+    "    end:16"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:9"
+    "    end:12"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:100"
+    "    end:536870912"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "  extension_range {"
+    "    start:3"
+    "    end:4"
+    "    options {"
+    "      uninterpreted_option {"
+    "        name {"
+    "          name_part: \"i\""
+    "          is_extension: true"
+    "        }"
+    "        positive_int_value: 5"
+    "      }"
+    "    }"
+    "  }"
+    "}");
+}
+
 TEST_F(ParseMessageTest, LargerMaxForMessageSetWireFormatMessages) {
   // Messages using the message_set_wire_format option can accept larger
   // extension numbers, as the numbers are not encoded as int32 field values
@@ -1368,12 +1491,12 @@
 // -------------------------------------------------------------------
 // Reserved field number errors
 
-TEST_F(ParseErrorTest, ReservedMaxNotAllowed) {
+TEST_F(ParseErrorTest, ReservedStandaloneMaxNotAllowed) {
   ExpectHasErrors(
     "message Foo {\n"
-    "  reserved 10 to max;\n"
+    "  reserved max;\n"
     "}\n",
-    "1:17: Expected integer.\n");
+    "1:11: Expected field name or number range.\n");
 }
 
 TEST_F(ParseErrorTest, ReservedMixNameAndNumber) {
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
index cbddee9..60e6fce 100644
--- a/src/google/protobuf/compiler/php/php_generator.cc
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -51,6 +51,9 @@
 const std::string kDescriptorPackageName = "Google\\Protobuf\\Internal";
 const char* const kReservedNames[] = {"ARRAY", "Empty", "ECHO"};
 const int kReservedNamesSize = 3;
+const int kFieldSetter = 1;
+const int kFieldGetter = 2;
+const int kFieldProperty = 3;
 
 namespace google {
 namespace protobuf {
@@ -71,12 +74,18 @@
 std::string BinaryToHex(const string& binary);
 void Indent(io::Printer* printer);
 void Outdent(io::Printer* printer);
-void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message);
-void GenerateFieldDocComment(io::Printer* printer,
-                             const FieldDescriptor* field);
-void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
+void GenerateMessageDocComment(io::Printer* printer, const Descriptor* message,
+                               int is_descriptor);
+void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+                             int is_descriptor, int function_type);
+void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+                            int is_descriptor);
 void GenerateEnumValueDocComment(io::Printer* printer,
                                  const EnumValueDescriptor* value);
+void GenerateServiceDocComment(io::Printer* printer,
+                               const ServiceDescriptor* service);
+void GenerateServiceMethodDocComment(io::Printer* printer,
+                              const MethodDescriptor* method);
 
 std::string RenameEmpty(const std::string& name) {
   if (name == "Empty") {
@@ -134,6 +143,25 @@
   return "";
 }
 
+template <typename DescriptorType>
+std::string NamespacedName(const string& classname,
+                            const DescriptorType* desc, bool is_descriptor) {
+  if (desc->file()->options().has_php_namespace()) {
+    const string& php_namespace = desc->file()->options().php_namespace();
+    if (php_namespace != "") {
+      return php_namespace + '\\' + classname;
+    } else {
+      return classname;
+    }
+  }
+
+  if (desc->file()->package() == "") {
+    return classname;
+  } else {
+    return PhpName(desc->file()->package(), is_descriptor) + '\\' +
+           classname;
+  }
+}
 
 template <typename DescriptorType>
 std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
@@ -144,13 +172,13 @@
     containing = containing->containing_type();
   }
   classname = ClassNamePrefix(classname, desc) + classname;
+  return NamespacedName(classname, desc, is_descriptor);
+}
 
-  if (desc->file()->package() == "") {
-    return classname;
-  } else {
-    return PhpName(desc->file()->package(), is_descriptor) + '\\' +
-           classname;
-  }
+std::string FullClassName(const ServiceDescriptor* desc, bool is_descriptor) {
+  string classname = desc->name();
+  classname = ClassNamePrefix(classname, desc) + classname;
+  return NamespacedName(classname, desc, is_descriptor);
 }
 
 std::string PhpName(const std::string& full_name, bool is_descriptor) {
@@ -258,6 +286,17 @@
   return result + ".php";
 }
 
+std::string GeneratedServiceFileName(const ServiceDescriptor* service,
+                                    bool is_descriptor) {
+  std::string result = FullClassName(service, is_descriptor) + "Interface";
+  for (int i = 0; i < result.size(); i++) {
+    if (result[i] == '\\') {
+      result[i] = '/';
+    }
+  }
+  return result + ".php";
+}
+
 std::string IntToString(int32 value) {
   std::ostringstream os;
   os << value;
@@ -297,6 +336,87 @@
   }
 }
 
+std::string PhpSetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+  if (field->is_map()) {
+    return "array|\\Google\\Protobuf\\Internal\\MapField";
+  }
+  string type;
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_ENUM:
+      type = "int";
+      break;
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      type = "int|string";
+      break;
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT:
+      type = "float";
+      break;
+    case FieldDescriptor::TYPE_BOOL:
+      type = "bool";
+      break;
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      type = "string";
+      break;
+    case FieldDescriptor::TYPE_MESSAGE:
+      type = "\\" + FullClassName(field->message_type(), is_descriptor);
+      break;
+    case FieldDescriptor::TYPE_GROUP:
+      return "null";
+    default: assert(false); return "";
+  }
+  if (field->is_repeated()) {
+    // accommodate for edge case with multiple types.
+    size_t start_pos = type.find("|");
+    if (start_pos != std::string::npos) {
+      type.replace(start_pos, 1, "[]|");
+    }
+    type += "[]|\\Google\\Protobuf\\Internal\\RepeatedField";
+  }
+  return type;
+}
+
+std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor) {
+  if (field->is_map()) {
+    return "\\Google\\Protobuf\\Internal\\MapField";
+  }
+  if (field->is_repeated()) {
+    return "\\Google\\Protobuf\\Internal\\RepeatedField";
+  }
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_ENUM: return "int";
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64: return "int|string";
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_FLOAT: return "float";
+    case FieldDescriptor::TYPE_BOOL: return "bool";
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES: return "string";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return "\\" + FullClassName(field->message_type(), is_descriptor);
+    case FieldDescriptor::TYPE_GROUP: return "null";
+    default: assert(false); return "";
+  }
+}
+
 std::string EnumOrMessageSuffix(
     const FieldDescriptor* field, bool is_descriptor) {
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
@@ -381,7 +501,7 @@
 void GenerateField(const FieldDescriptor* field, io::Printer* printer,
                    bool is_descriptor) {
   if (field->is_repeated()) {
-    GenerateFieldDocComment(printer, field);
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
     printer->Print(
         "private $^name^;\n",
         "name", field->name());
@@ -389,7 +509,7 @@
     // Oneof fields are handled by GenerateOneofField.
     return;
   } else {
-    GenerateFieldDocComment(printer, field);
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldProperty);
     printer->Print(
         "private $^name^ = ^default^;\n",
         "name", field->name(),
@@ -417,7 +537,7 @@
 
   // Generate getter.
   if (oneof != NULL) {
-    GenerateFieldDocComment(printer, field);
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
     printer->Print(
         "public function get^camel_name^()\n"
         "{\n"
@@ -426,7 +546,7 @@
         "camel_name", UnderscoresToCamelCase(field->name(), true),
         "number", IntToString(field->number()));
   } else {
-    GenerateFieldDocComment(printer, field);
+    GenerateFieldDocComment(printer, field, is_descriptor, kFieldGetter);
     printer->Print(
         "public function get^camel_name^()\n"
         "{\n"
@@ -437,14 +557,11 @@
   }
 
   // Generate setter.
-  GenerateFieldDocComment(printer, field);
+  GenerateFieldDocComment(printer, field, is_descriptor, kFieldSetter);
   printer->Print(
-      "public function set^camel_name^(^var^)\n"
+      "public function set^camel_name^($var)\n"
       "{\n",
-      "camel_name", UnderscoresToCamelCase(field->name(), true),
-      "var", (field->is_repeated() ||
-              field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
-             "&$var": "$var");
+      "camel_name", UnderscoresToCamelCase(field->name(), true));
 
   Indent(printer);
 
@@ -568,6 +685,16 @@
   Outdent(printer);
 }
 
+void GenerateServiceMethod(const MethodDescriptor* method,
+                           io::Printer* printer) {
+  printer->Print(
+        "public function ^camel_name^(\\^request_name^ $request);\n\n",
+        "camel_name", UnderscoresToCamelCase(method->name(), false),
+        "request_name", FullClassName(
+          method->input_type(), false)
+  );
+}
+
 void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
                            io::Printer* printer) {
   // Don't generate MapEntry messages -- we use the PHP extension's native
@@ -749,7 +876,7 @@
         "use Google\\Protobuf\\Internal\\GPBType;\n"
         "use Google\\Protobuf\\Internal\\GPBWire;\n"
         "use Google\\Protobuf\\Internal\\RepeatedField;\n"
-        "use Google\\Protobuf\\Internal\\InputStream;\n\n"
+        "use Google\\Protobuf\\Internal\\InputStream;\n"
         "use Google\\Protobuf\\Internal\\GPBUtil;\n\n");
   }
 }
@@ -822,13 +949,20 @@
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (!file->package().empty()) {
+  if (file->options().has_php_namespace()) {
+    const string& php_namespace = file->options().php_namespace();
+    if (!php_namespace.empty()) {
+      printer.Print(
+          "namespace ^name^;\n\n",
+          "name", php_namespace);
+    }
+  } else if (!file->package().empty()) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
   }
 
-  GenerateEnumDocComment(&printer, en);
+  GenerateEnumDocComment(&printer, en, is_descriptor);
 
   if (lastindex != string::npos) {
     printer.Print(
@@ -874,7 +1008,14 @@
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (!file->package().empty()) {
+  if (file->options().has_php_namespace()) {
+    const string& php_namespace = file->options().php_namespace();
+    if (!php_namespace.empty()) {
+      printer.Print(
+          "namespace ^name^;\n\n",
+          "name", php_namespace);
+    }
+  } else if (!file->package().empty()) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
@@ -882,7 +1023,7 @@
 
   GenerateUseDeclaration(is_descriptor, &printer);
 
-  GenerateMessageDocComment(&printer, message);
+  GenerateMessageDocComment(&printer, message, is_descriptor);
   if (lastindex != string::npos) {
     printer.Print(
         "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
@@ -930,6 +1071,9 @@
   for (int i = 0; i < message->oneof_decl_count(); i++) {
     const OneofDescriptor* oneof = message->oneof_decl(i);
     printer.Print(
+      "/**\n"
+      " * @return string\n"
+      " */\n"
       "public function get^camel_name^()\n"
       "{\n"
       "    return $this->whichOneof(\"^name^\");\n"
@@ -952,6 +1096,58 @@
   }
 }
 
+void GenerateServiceFile(const FileDescriptor* file,
+  const ServiceDescriptor* service, bool is_descriptor,
+  GeneratorContext* generator_context) {
+  std::string filename = GeneratedServiceFileName(service, is_descriptor);
+  scoped_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string fullname = FilenameToClassname(filename);
+  int lastindex = fullname.find_last_of("\\");
+
+  if (file->options().has_php_namespace()) {
+    const string& php_namespace = file->options().php_namespace();
+    if (!php_namespace.empty()) {
+      printer.Print(
+          "namespace ^name^;\n\n",
+          "name", php_namespace);
+    }
+  } else if (!file->package().empty()) {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", fullname.substr(0, lastindex));
+  }
+
+  GenerateServiceDocComment(&printer, service);
+
+  if (lastindex != string::npos) {
+      printer.Print(
+        "interface ^name^\n"
+        "{\n",
+        "name", fullname.substr(lastindex + 1));
+  } else {
+      printer.Print(
+        "interface ^name^\n"
+        "{\n",
+        "name", fullname);
+  }
+
+  Indent(&printer);
+
+  for (int i = 0; i < service->method_count(); i++) {
+    const MethodDescriptor* method = service->method(i);
+    GenerateServiceMethodDocComment(&printer, method);
+    GenerateServiceMethod(method, &printer);
+  }
+
+  Outdent(&printer);
+  printer.Print("}\n\n");
+}
+
 void GenerateFile(const FileDescriptor* file, bool is_descriptor,
                   GeneratorContext* generator_context) {
   GenerateMetadataFile(file, is_descriptor, generator_context);
@@ -963,6 +1159,12 @@
     GenerateEnumFile(file, file->enum_type(i), is_descriptor,
                      generator_context);
   }
+  if (file->options().php_generic_services()) {
+    for (int i = 0; i < file->service_count(); i++) {
+      GenerateServiceFile(file, file->service(i), is_descriptor,
+                       generator_context);
+    }
+  }
 }
 
 static string EscapePhpdoc(const string& input) {
@@ -996,22 +1198,6 @@
         // does not have a corresponding @Deprecated annotation.
         result.append("&#64;");
         break;
-      case '<':
-        // Avoid interpretation as HTML.
-        result.append("&lt;");
-        break;
-      case '>':
-        // Avoid interpretation as HTML.
-        result.append("&gt;");
-        break;
-      case '&':
-        // Avoid interpretation as HTML.
-        result.append("&amp;");
-        break;
-      case '\\':
-        // Java interprets Unicode escape sequences anywhere!
-        result.append("&#92;");
-        break;
       default:
         result.push_back(c);
         break;
@@ -1030,7 +1216,7 @@
   if (!comments.empty()) {
     // TODO(teboring):  Ideally we should parse the comment text as Markdown and
     //   write it back as HTML, but this requires a Markdown parser.  For now
-    //   we just use <pre> to get fixed-width text formatting.
+    //   we just use the proto comments unchanged.
 
     // If the comment itself contains block comment start or end markers,
     // HTML-escape them so that they don't accidentally close the doc comment.
@@ -1041,7 +1227,6 @@
       lines.pop_back();
     }
 
-    printer->Print(" * <pre>\n");
     for (int i = 0; i < lines.size(); i++) {
       // Most lines should start with a space.  Watch out for lines that start
       // with a /, since putting that right after the leading asterisk will
@@ -1053,7 +1238,6 @@
       }
     }
     printer->Print(
-        " * </pre>\n"
         " *\n");
   }
 }
@@ -1079,17 +1263,28 @@
 }
 
 void GenerateMessageDocComment(io::Printer* printer,
-                               const Descriptor* message) {
+                               const Descriptor* message, int is_descriptor) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, message);
   printer->Print(
-    " * Protobuf type <code>^fullname^</code>\n"
+    " * Generated from protobuf message <code>^messagename^</code>\n"
     " */\n",
-    "fullname", EscapePhpdoc(message->full_name()));
+    "fullname", EscapePhpdoc(PhpName(message->full_name(), is_descriptor)),
+    "messagename", EscapePhpdoc(message->full_name()));
 }
 
-void GenerateFieldDocComment(io::Printer* printer,
-                             const FieldDescriptor* field) {
+void GenerateServiceDocComment(io::Printer* printer,
+                               const ServiceDescriptor* service) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, service);
+  printer->Print(
+    " * Protobuf type <code>^fullname^</code>\n"
+    " */\n",
+    "fullname", EscapePhpdoc(service->full_name()));
+}
+
+void GenerateFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+                             int is_descriptor, int function_type) {
   // In theory we should have slightly different comments for setters, getters,
   // etc., but in practice everyone already knows the difference between these
   // so it's redundant information.
@@ -1101,18 +1296,27 @@
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, field);
   printer->Print(
-    " * <code>^def^</code>\n",
+    " * Generated from protobuf field <code>^def^</code>\n",
     "def", EscapePhpdoc(FirstLineOf(field->DebugString())));
+  if (function_type == kFieldSetter) {
+    printer->Print(" * @param ^php_type^ $var\n",
+      "php_type", PhpSetterTypeName(field, is_descriptor));
+    printer->Print(" * @return $this\n");
+  } else if (function_type == kFieldGetter) {
+    printer->Print(" * @return ^php_type^\n",
+      "php_type", PhpGetterTypeName(field, is_descriptor));
+  }
   printer->Print(" */\n");
 }
 
-void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+                            int is_descriptor) {
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, enum_);
   printer->Print(
     " * Protobuf enum <code>^fullname^</code>\n"
     " */\n",
-    "fullname", EscapePhpdoc(enum_->full_name()));
+    "fullname", EscapePhpdoc(PhpName(enum_->full_name(), is_descriptor)));
 }
 
 void GenerateEnumValueDocComment(io::Printer* printer,
@@ -1120,11 +1324,28 @@
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, value);
   printer->Print(
-    " * <code>^def^</code>\n"
+    " * Generated from protobuf enum <code>^def^</code>\n"
     " */\n",
     "def", EscapePhpdoc(FirstLineOf(value->DebugString())));
 }
 
+void GenerateServiceMethodDocComment(io::Printer* printer,
+                              const MethodDescriptor* method) {
+  printer->Print("/**\n");
+  GenerateDocCommentBody(printer, method);
+  printer->Print(
+    " * Method <code>^method_name^</code>\n"
+    " *\n",
+    "method_name", EscapePhpdoc(UnderscoresToCamelCase(method->name(), false)));
+  printer->Print(
+    " * @param \\^input_type^ $request\n",
+    "input_type", EscapePhpdoc(FullClassName(method->input_type(), false)));
+  printer->Print(
+    " * @return \\^return_type^\n"
+    " */\n",
+    "return_type", EscapePhpdoc(FullClassName(method->output_type(), false)));
+}
+
 bool Generator::Generate(const FileDescriptor* file, const string& parameter,
                          GeneratorContext* generator_context,
                          string* error) const {
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 3848101..cb5e37b 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -36,18 +36,12 @@
 #include <set>
 
 #ifdef _WIN32
-#include <io.h>
 #include <fcntl.h>
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
 #else
 #include <unistd.h>
 #endif
 
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/plugin.pb.h>
@@ -55,6 +49,11 @@
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 
+#if defined(_MSC_VER)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::setmode;
+#endif
 
 namespace google {
 namespace protobuf {
@@ -127,6 +126,7 @@
   GeneratorResponseContext context(
       request.compiler_version(), response, parsed_files);
 
+
   string error;
   bool succeeded = generator.GenerateAll(
       parsed_files, request.parameter(), &context, &error);
@@ -150,8 +150,8 @@
   }
 
 #ifdef _WIN32
-  _setmode(STDIN_FILENO, _O_BINARY);
-  _setmode(STDOUT_FILENO, _O_BINARY);
+  setmode(STDIN_FILENO, _O_BINARY);
+  setmode(STDOUT_FILENO, _O_BINARY);
 #endif
 
   CodeGeneratorRequest request;
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index f7dc1b7..07883a3 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -20,13 +20,25 @@
 namespace google {
 namespace protobuf {
 namespace compiler {
-class VersionDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Version> {
+class VersionDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Version>
+     _instance;
 } _Version_default_instance_;
-class CodeGeneratorRequestDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest> {
+class CodeGeneratorRequestDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorRequest>
+     _instance;
 } _CodeGeneratorRequest_default_instance_;
-class CodeGeneratorResponse_FileDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File> {
+class CodeGeneratorResponse_FileDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse_File>
+     _instance;
 } _CodeGeneratorResponse_File_default_instance_;
-class CodeGeneratorResponseDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse> {
+class CodeGeneratorResponseDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<CodeGeneratorResponse>
+     _instance;
 } _CodeGeneratorResponse_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
@@ -39,23 +51,23 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, _has_bits_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Version, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -103,8 +115,7 @@
   0,
   ~0u,
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, 9, sizeof(Version)},
   { 13, 22, sizeof(CodeGeneratorRequest)},
   { 26, 34, sizeof(CodeGeneratorResponse_File)},
@@ -140,28 +151,20 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Version_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-  _CodeGeneratorRequest_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _CodeGeneratorResponse_File_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-  _CodeGeneratorResponse_default_instance_.Shutdown();
-  delete file_level_metadata[3].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
   ::google::protobuf::protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults();
-  _Version_default_instance_.DefaultConstruct();
-  _CodeGeneratorRequest_default_instance_.DefaultConstruct();
-  _CodeGeneratorResponse_File_default_instance_.DefaultConstruct();
-  _CodeGeneratorResponse_default_instance_.DefaultConstruct();
-  _CodeGeneratorRequest_default_instance_.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>(
+  _Version_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Version_default_instance_);_CodeGeneratorRequest_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_CodeGeneratorRequest_default_instance_);_CodeGeneratorResponse_File_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_CodeGeneratorResponse_File_default_instance_);_CodeGeneratorResponse_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_CodeGeneratorResponse_default_instance_);_CodeGeneratorRequest_default_instance_._instance.get_mutable()->compiler_version_ = const_cast< ::google::protobuf::compiler::Version*>(
       ::google::protobuf::compiler::Version::internal_default_instance());
 }
 
@@ -169,9 +172,10 @@
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n%google/protobuf/compiler/plugin.proto\022"
       "\030google.protobuf.compiler\032 google/protob"
       "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030"
@@ -194,14 +198,14 @@
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
   ::google::protobuf::protobuf_google_2fprotobuf_2fdescriptor_2eproto::AddDescriptors();
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -239,16 +243,17 @@
     suffix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.suffix_);
   }
   ::memcpy(&major_, &from.major_,
-    reinterpret_cast<char*>(&patch_) -
-    reinterpret_cast<char*>(&major_) + sizeof(patch_));
+    static_cast<size_t>(reinterpret_cast<char*>(&patch_) -
+    reinterpret_cast<char*>(&major_)) + sizeof(patch_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version)
 }
 
 void Version::SharedCtor() {
   _cached_size_ = 0;
   suffix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&major_, 0, reinterpret_cast<char*>(&patch_) -
-    reinterpret_cast<char*>(&major_) + sizeof(patch_));
+  ::memset(&major_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&patch_) -
+      reinterpret_cast<char*>(&major_)) + sizeof(patch_));
 }
 
 Version::~Version() {
@@ -285,13 +290,19 @@
 
 void Version::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   if (has_suffix()) {
     GOOGLE_DCHECK(!suffix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
     (*suffix_.UnsafeRawStringPointer())->clear();
   }
-  if (_has_bits_[0 / 32] & 14u) {
-    ::memset(&major_, 0, reinterpret_cast<char*>(&patch_) -
-      reinterpret_cast<char*>(&major_) + sizeof(patch_));
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 14u) {
+    ::memset(&major_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&patch_) -
+        reinterpret_cast<char*>(&major_)) + sizeof(patch_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -310,7 +321,7 @@
       // optional int32 major = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           set_has_major();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -324,7 +335,7 @@
       // optional int32 minor = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_minor();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -338,7 +349,7 @@
       // optional int32 patch = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
           set_has_patch();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -352,11 +363,11 @@
       // optional string suffix = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_suffix()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->suffix().data(), this->suffix().length(),
+            this->suffix().data(), static_cast<int>(this->suffix().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.Version.suffix");
         } else {
@@ -367,13 +378,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -412,7 +421,7 @@
   // optional string suffix = 4;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->suffix().data(), this->suffix().length(),
+      this->suffix().data(), static_cast<int>(this->suffix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.Version.suffix");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -421,13 +430,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.Version)
 }
 
 ::google::protobuf::uint8* Version::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -451,7 +461,7 @@
   // optional string suffix = 4;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->suffix().data(), this->suffix().length(),
+      this->suffix().data(), static_cast<int>(this->suffix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.Version.suffix");
     target =
@@ -461,7 +471,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.Version)
   return target;
@@ -474,7 +484,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 15u) {
     // optional string suffix = 4;
@@ -577,13 +587,14 @@
   InternalSwap(other);
 }
 void Version::InternalSwap(Version* other) {
+  using std::swap;
   suffix_.Swap(&other->suffix_);
-  std::swap(major_, other->major_);
-  std::swap(minor_, other->minor_);
-  std::swap(patch_, other->patch_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(major_, other->major_);
+  swap(minor_, other->minor_);
+  swap(patch_, other->patch_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Version::GetMetadata() const {
@@ -781,9 +792,7 @@
 
 void CodeGeneratorRequest::SharedDtor() {
   parameter_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete compiler_version_;
-  }
+  if (this != internal_default_instance()) delete compiler_version_;
 }
 
 void CodeGeneratorRequest::SetCachedSize(int size) const {
@@ -811,14 +820,19 @@
 
 void CodeGeneratorRequest::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   file_to_generate_.Clear();
   proto_file_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_parameter()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!parameter_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*parameter_.UnsafeRawStringPointer())->clear();
     }
-    if (has_compiler_version()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(compiler_version_ != NULL);
       compiler_version_->::google::protobuf::compiler::Version::Clear();
     }
@@ -840,12 +854,12 @@
       // repeated string file_to_generate = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_file_to_generate()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
             this->file_to_generate(this->file_to_generate_size() - 1).data(),
-            this->file_to_generate(this->file_to_generate_size() - 1).length(),
+            static_cast<int>(this->file_to_generate(this->file_to_generate_size() - 1).length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
         } else {
@@ -857,11 +871,11 @@
       // optional string parameter = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_parameter()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->parameter().data(), this->parameter().length(),
+            this->parameter().data(), static_cast<int>(this->parameter().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorRequest.parameter");
         } else {
@@ -873,7 +887,7 @@
       // optional .google.protobuf.compiler.Version compiler_version = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_compiler_version()));
         } else {
@@ -885,7 +899,7 @@
       // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
       case 15: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(122u)) {
+            static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_proto_file()));
         } else {
@@ -896,13 +910,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -925,7 +937,7 @@
   // repeated string file_to_generate = 1;
   for (int i = 0, n = this->file_to_generate_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      this->file_to_generate(i).data(), static_cast<int>(this->file_to_generate(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
     ::google::protobuf::internal::WireFormatLite::WriteString(
@@ -936,7 +948,7 @@
   // optional string parameter = 2;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->parameter().data(), this->parameter().length(),
+      this->parameter().data(), static_cast<int>(this->parameter().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.parameter");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -950,20 +962,22 @@
   }
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->proto_file_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      15, this->proto_file(i), output);
+      15, this->proto_file(static_cast<int>(i)), output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest)
 }
 
 ::google::protobuf::uint8* CodeGeneratorRequest::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -971,7 +985,7 @@
   // repeated string file_to_generate = 1;
   for (int i = 0, n = this->file_to_generate_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      this->file_to_generate(i).data(), static_cast<int>(this->file_to_generate(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.file_to_generate");
     target = ::google::protobuf::internal::WireFormatLite::
@@ -982,7 +996,7 @@
   // optional string parameter = 2;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->parameter().data(), this->parameter().length(),
+      this->parameter().data(), static_cast<int>(this->parameter().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorRequest.parameter");
     target =
@@ -998,15 +1012,16 @@
   }
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
-  for (unsigned int i = 0, n = this->proto_file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->proto_file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        15, this->proto_file(i), deterministic, target);
+        15, this->proto_file(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest)
   return target;
@@ -1019,7 +1034,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated string file_to_generate = 1;
   total_size += 1 *
@@ -1031,12 +1046,12 @@
 
   // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
   {
-    unsigned int count = this->proto_file_size();
+    unsigned int count = static_cast<unsigned int>(this->proto_file_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->proto_file(i));
+          this->proto_file(static_cast<int>(i)));
     }
   }
 
@@ -1123,13 +1138,14 @@
   InternalSwap(other);
 }
 void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) {
+  using std::swap;
   file_to_generate_.InternalSwap(&other->file_to_generate_);
   proto_file_.InternalSwap(&other->proto_file_);
   parameter_.Swap(&other->parameter_);
-  std::swap(compiler_version_, other->compiler_version_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(compiler_version_, other->compiler_version_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
@@ -1317,9 +1333,10 @@
   clear_has_compiler_version();
 }
 const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const {
+  const ::google::protobuf::compiler::Version* p = compiler_version_;
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
-  return compiler_version_ != NULL ? *compiler_version_
-                         : *::google::protobuf::compiler::Version::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::compiler::Version*>(
+      &::google::protobuf::compiler::_Version_default_instance_);
 }
 ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
   set_has_compiler_version();
@@ -1429,16 +1446,21 @@
 
 void CodeGeneratorResponse_File::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  if (_has_bits_[0 / 32] & 7u) {
-    if (has_name()) {
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 7u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_insertion_point()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!insertion_point_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*insertion_point_.UnsafeRawStringPointer())->clear();
     }
-    if (has_content()) {
+    if (cached_has_bits & 0x00000004u) {
       GOOGLE_DCHECK(!content_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*content_.UnsafeRawStringPointer())->clear();
     }
@@ -1460,11 +1482,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.File.name");
         } else {
@@ -1476,11 +1498,11 @@
       // optional string insertion_point = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_insertion_point()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->insertion_point().data(), this->insertion_point().length(),
+            this->insertion_point().data(), static_cast<int>(this->insertion_point().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
         } else {
@@ -1492,11 +1514,11 @@
       // optional string content = 15;
       case 15: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(122u)) {
+            static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_content()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->content().data(), this->content().length(),
+            this->content().data(), static_cast<int>(this->content().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.File.content");
         } else {
@@ -1507,13 +1529,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1537,7 +1557,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1547,7 +1567,7 @@
   // optional string insertion_point = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->insertion_point().data(), this->insertion_point().length(),
+      this->insertion_point().data(), static_cast<int>(this->insertion_point().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1557,7 +1577,7 @@
   // optional string content = 15;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->content().data(), this->content().length(),
+      this->content().data(), static_cast<int>(this->content().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.content");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1566,13 +1586,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File)
 }
 
 ::google::protobuf::uint8* CodeGeneratorResponse_File::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1581,7 +1602,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.name");
     target =
@@ -1592,7 +1613,7 @@
   // optional string insertion_point = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->insertion_point().data(), this->insertion_point().length(),
+      this->insertion_point().data(), static_cast<int>(this->insertion_point().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
     target =
@@ -1603,7 +1624,7 @@
   // optional string content = 15;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->content().data(), this->content().length(),
+      this->content().data(), static_cast<int>(this->content().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.File.content");
     target =
@@ -1613,7 +1634,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File)
   return target;
@@ -1626,7 +1647,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 7u) {
     // optional string name = 1;
@@ -1720,12 +1741,13 @@
   InternalSwap(other);
 }
 void CodeGeneratorResponse_File::InternalSwap(CodeGeneratorResponse_File* other) {
+  using std::swap;
   name_.Swap(&other->name_);
   insertion_point_.Swap(&other->insertion_point_);
   content_.Swap(&other->content_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
@@ -1995,6 +2017,10 @@
 
 void CodeGeneratorResponse::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   file_.Clear();
   if (has_error()) {
     GOOGLE_DCHECK(!error_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
@@ -2017,11 +2043,11 @@
       // optional string error = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_error()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->error().data(), this->error().length(),
+            this->error().data(), static_cast<int>(this->error().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.compiler.CodeGeneratorResponse.error");
         } else {
@@ -2033,7 +2059,7 @@
       // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
       case 15: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(122u)) {
+            static_cast< ::google::protobuf::uint8>(122u /* 122 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_file()));
         } else {
@@ -2044,13 +2070,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -2074,7 +2098,7 @@
   // optional string error = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->error().data(), this->error().length(),
+      this->error().data(), static_cast<int>(this->error().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.error");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -2082,20 +2106,22 @@
   }
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      15, this->file(i), output);
+      15, this->file(static_cast<int>(i)), output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse)
 }
 
 ::google::protobuf::uint8* CodeGeneratorResponse::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2104,7 +2130,7 @@
   // optional string error = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->error().data(), this->error().length(),
+      this->error().data(), static_cast<int>(this->error().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.compiler.CodeGeneratorResponse.error");
     target =
@@ -2113,15 +2139,16 @@
   }
 
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
-  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        15, this->file(i), deterministic, target);
+        15, this->file(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse)
   return target;
@@ -2134,16 +2161,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
   {
-    unsigned int count = this->file_size();
+    unsigned int count = static_cast<unsigned int>(this->file_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->file(i));
+          this->file(static_cast<int>(i)));
     }
   }
 
@@ -2213,11 +2240,12 @@
   InternalSwap(other);
 }
 void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) {
+  using std::swap;
   file_.InternalSwap(&other->file_);
   error_.Swap(&other->error_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 4f8befb..2d66f03 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -39,81 +39,6 @@
 #endif
 namespace google {
 namespace protobuf {
-class DescriptorProto;
-class DescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
-class DescriptorProto_ExtensionRange;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal;
-LIBPROTOC_EXPORT extern DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
-class DescriptorProto_ReservedRange;
-class DescriptorProto_ReservedRangeDefaultTypeInternal;
-LIBPROTOC_EXPORT extern DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
-class EnumDescriptorProto;
-class EnumDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
-class EnumOptions;
-class EnumOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
-class EnumValueDescriptorProto;
-class EnumValueDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
-class EnumValueOptions;
-class EnumValueOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
-class FieldDescriptorProto;
-class FieldDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
-class FieldOptions;
-class FieldOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
-class FileDescriptorProto;
-class FileDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
-class FileDescriptorSet;
-class FileDescriptorSetDefaultTypeInternal;
-LIBPROTOC_EXPORT extern FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
-class FileOptions;
-class FileOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
-class GeneratedCodeInfo;
-class GeneratedCodeInfoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
-class GeneratedCodeInfo_Annotation;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal;
-LIBPROTOC_EXPORT extern GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
-class MessageOptions;
-class MessageOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
-class MethodDescriptorProto;
-class MethodDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
-class MethodOptions;
-class MethodOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
-class OneofDescriptorProto;
-class OneofDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
-class OneofOptions;
-class OneofOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
-class ServiceDescriptorProto;
-class ServiceDescriptorProtoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
-class ServiceOptions;
-class ServiceOptionsDefaultTypeInternal;
-LIBPROTOC_EXPORT extern ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
-class SourceCodeInfo;
-class SourceCodeInfoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
-class SourceCodeInfo_Location;
-class SourceCodeInfo_LocationDefaultTypeInternal;
-LIBPROTOC_EXPORT extern SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
-class UninterpretedOption;
-class UninterpretedOptionDefaultTypeInternal;
-LIBPROTOC_EXPORT extern UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
-class UninterpretedOption_NamePart;
-class UninterpretedOption_NamePartDefaultTypeInternal;
-LIBPROTOC_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
 namespace compiler {
 class CodeGeneratorRequest;
 class CodeGeneratorRequestDefaultTypeInternal;
@@ -142,8 +67,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOC_EXPORT AddDescriptors();
 void LIBPROTOC_EXPORT InitDefaults();
@@ -162,11 +88,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Version(Version&& from) noexcept
+    : Version() {
+    *this = ::std::move(from);
+  }
 
+  inline Version& operator=(Version&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -182,6 +121,9 @@
     0;
 
   void Swap(Version* other);
+  friend void swap(Version& a, Version& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -292,11 +234,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  CodeGeneratorRequest(CodeGeneratorRequest&& from) noexcept
+    : CodeGeneratorRequest() {
+    *this = ::std::move(from);
+  }
 
+  inline CodeGeneratorRequest& operator=(CodeGeneratorRequest&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -312,6 +267,9 @@
     1;
 
   void Swap(CodeGeneratorRequest* other);
+  friend void swap(CodeGeneratorRequest& a, CodeGeneratorRequest& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -440,11 +398,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  CodeGeneratorResponse_File(CodeGeneratorResponse_File&& from) noexcept
+    : CodeGeneratorResponse_File() {
+    *this = ::std::move(from);
+  }
 
+  inline CodeGeneratorResponse_File& operator=(CodeGeneratorResponse_File&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -460,6 +431,9 @@
     2;
 
   void Swap(CodeGeneratorResponse_File* other);
+  friend void swap(CodeGeneratorResponse_File& a, CodeGeneratorResponse_File& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -576,11 +550,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  CodeGeneratorResponse(CodeGeneratorResponse&& from) noexcept
+    : CodeGeneratorResponse() {
+    *this = ::std::move(from);
+  }
 
+  inline CodeGeneratorResponse& operator=(CodeGeneratorResponse&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -596,6 +583,9 @@
     3;
 
   void Swap(CodeGeneratorResponse* other);
+  friend void swap(CodeGeneratorResponse& a, CodeGeneratorResponse& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -684,6 +674,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Version
 
 // optional int32 major = 1;
@@ -1002,9 +996,10 @@
   clear_has_compiler_version();
 }
 inline const ::google::protobuf::compiler::Version& CodeGeneratorRequest::compiler_version() const {
+  const ::google::protobuf::compiler::Version* p = compiler_version_;
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.compiler_version)
-  return compiler_version_ != NULL ? *compiler_version_
-                         : *::google::protobuf::compiler::Version::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::compiler::Version*>(
+      &::google::protobuf::compiler::_Version_default_instance_);
 }
 inline ::google::protobuf::compiler::Version* CodeGeneratorRequest::mutable_compiler_version() {
   set_has_compiler_version();
@@ -1322,6 +1317,9 @@
   return file_;
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 // -------------------------------------------------------------------
 
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index f04dc73..5b55745 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -91,6 +91,7 @@
 
   // The version number of protocol compiler.
   optional Version compiler_version = 3;
+
 }
 
 // The plugin writes an encoded CodeGeneratorResponse to stdout.
diff --git a/src/google/protobuf/compiler/profile.pb.cc b/src/google/protobuf/compiler/profile.pb.cc
deleted file mode 100644
index c185e4f..0000000
--- a/src/google/protobuf/compiler/profile.pb.cc
+++ /dev/null
@@ -1,1442 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/compiler/profile.proto
-
-#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
-#include <google/protobuf/compiler/profile.pb.h>
-
-#include <algorithm>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/port.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/wire_format_lite_inl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
-// @@protoc_insertion_point(includes)
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-class FieldAccessInfoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FieldAccessInfo> {
-} _FieldAccessInfo_default_instance_;
-class MessageAccessInfoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<MessageAccessInfo> {
-} _MessageAccessInfo_default_instance_;
-class AccessInfoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<AccessInfo> {
-} _AccessInfo_default_instance_;
-
-namespace protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto {
-
-
-namespace {
-
-::google::protobuf::Metadata file_level_metadata[3];
-
-}  // namespace
-
-PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
-  {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
-};
-
-PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
-  ::google::protobuf::internal::AuxillaryParseTableField(),
-};
-PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-};
-
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldAccessInfo, _has_bits_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldAccessInfo, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldAccessInfo, name_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldAccessInfo, getters_count_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldAccessInfo, setters_count_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldAccessInfo, configs_count_),
-  0,
-  1,
-  2,
-  3,
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageAccessInfo, _has_bits_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageAccessInfo, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageAccessInfo, name_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageAccessInfo, count_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageAccessInfo, field_),
-  0,
-  1,
-  ~0u,
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AccessInfo, _has_bits_),
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AccessInfo, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(AccessInfo, message_),
-  ~0u,
-};
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
-  { 0, 9, sizeof(FieldAccessInfo)},
-  { 13, 21, sizeof(MessageAccessInfo)},
-  { 24, 30, sizeof(AccessInfo)},
-};
-
-static ::google::protobuf::Message const * const file_default_instances[] = {
-  reinterpret_cast<const ::google::protobuf::Message*>(&_FieldAccessInfo_default_instance_),
-  reinterpret_cast<const ::google::protobuf::Message*>(&_MessageAccessInfo_default_instance_),
-  reinterpret_cast<const ::google::protobuf::Message*>(&_AccessInfo_default_instance_),
-};
-
-namespace {
-
-void protobuf_AssignDescriptors() {
-  AddDescriptors();
-  ::google::protobuf::MessageFactory* factory = NULL;
-  AssignDescriptors(
-      "google/protobuf/compiler/profile.proto", schemas, file_default_instances, TableStruct::offsets, factory,
-      file_level_metadata, NULL, NULL);
-}
-
-void protobuf_AssignDescriptorsOnce() {
-  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
-  ::google::protobuf::GoogleOnceInit(&once, &protobuf_AssignDescriptors);
-}
-
-void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
-void protobuf_RegisterTypes(const ::std::string&) {
-  protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 3);
-}
-
-}  // namespace
-
-void TableStruct::Shutdown() {
-  _FieldAccessInfo_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-  _MessageAccessInfo_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _AccessInfo_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-}
-
-void TableStruct::InitDefaultsImpl() {
-  GOOGLE_PROTOBUF_VERIFY_VERSION;
-
-  ::google::protobuf::internal::InitProtobufDefaults();
-  _FieldAccessInfo_default_instance_.DefaultConstruct();
-  _MessageAccessInfo_default_instance_.DefaultConstruct();
-  _AccessInfo_default_instance_.DefaultConstruct();
-}
-
-void InitDefaults() {
-  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
-  ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
-}
-void AddDescriptorsImpl() {
-  InitDefaults();
-  static const char descriptor[] = {
-      "\n&google/protobuf/compiler/profile.proto"
-      "\022\030google.protobuf.compiler\"d\n\017FieldAcces"
-      "sInfo\022\014\n\004name\030\001 \001(\t\022\025\n\rgetters_count\030\002 \001"
-      "(\004\022\025\n\rsetters_count\030\003 \001(\004\022\025\n\rconfigs_cou"
-      "nt\030\004 \001(\004\"j\n\021MessageAccessInfo\022\014\n\004name\030\001 "
-      "\001(\t\022\r\n\005count\030\002 \001(\004\0228\n\005field\030\003 \003(\0132).goog"
-      "le.protobuf.compiler.FieldAccessInfo\"J\n\n"
-      "AccessInfo\022<\n\007message\030\001 \003(\0132+.google.pro"
-      "tobuf.compiler.MessageAccessInfo"
-  };
-  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
-      descriptor, 352);
-  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
-    "google/protobuf/compiler/profile.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
-}
-
-void AddDescriptors() {
-  static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
-  ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
-}
-// Force AddDescriptors() to be called at static initialization time.
-struct StaticDescriptorInitializer {
-  StaticDescriptorInitializer() {
-    AddDescriptors();
-  }
-} static_descriptor_initializer;
-
-}  // namespace protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto
-
-
-// ===================================================================
-
-#if !defined(_MSC_VER) || _MSC_VER >= 1900
-const int FieldAccessInfo::kNameFieldNumber;
-const int FieldAccessInfo::kGettersCountFieldNumber;
-const int FieldAccessInfo::kSettersCountFieldNumber;
-const int FieldAccessInfo::kConfigsCountFieldNumber;
-#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
-
-FieldAccessInfo::FieldAccessInfo()
-  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
-  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
-    protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::InitDefaults();
-  }
-  SharedCtor();
-  // @@protoc_insertion_point(constructor:google.protobuf.compiler.FieldAccessInfo)
-}
-FieldAccessInfo::FieldAccessInfo(const FieldAccessInfo& from)
-  : ::google::protobuf::Message(),
-      _internal_metadata_(NULL),
-      _has_bits_(from._has_bits_),
-      _cached_size_(0) {
-  _internal_metadata_.MergeFrom(from._internal_metadata_);
-  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (from.has_name()) {
-    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
-  }
-  ::memcpy(&getters_count_, &from.getters_count_,
-    reinterpret_cast<char*>(&configs_count_) -
-    reinterpret_cast<char*>(&getters_count_) + sizeof(configs_count_));
-  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.FieldAccessInfo)
-}
-
-void FieldAccessInfo::SharedCtor() {
-  _cached_size_ = 0;
-  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&getters_count_, 0, reinterpret_cast<char*>(&configs_count_) -
-    reinterpret_cast<char*>(&getters_count_) + sizeof(configs_count_));
-}
-
-FieldAccessInfo::~FieldAccessInfo() {
-  // @@protoc_insertion_point(destructor:google.protobuf.compiler.FieldAccessInfo)
-  SharedDtor();
-}
-
-void FieldAccessInfo::SharedDtor() {
-  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-
-void FieldAccessInfo::SetCachedSize(int size) const {
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
-}
-const ::google::protobuf::Descriptor* FieldAccessInfo::descriptor() {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::protobuf_AssignDescriptorsOnce();
-  return protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
-}
-
-const FieldAccessInfo& FieldAccessInfo::default_instance() {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::InitDefaults();
-  return *internal_default_instance();
-}
-
-FieldAccessInfo* FieldAccessInfo::New(::google::protobuf::Arena* arena) const {
-  FieldAccessInfo* n = new FieldAccessInfo;
-  if (arena != NULL) {
-    arena->Own(n);
-  }
-  return n;
-}
-
-void FieldAccessInfo::Clear() {
-// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.FieldAccessInfo)
-  if (has_name()) {
-    GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
-    (*name_.UnsafeRawStringPointer())->clear();
-  }
-  if (_has_bits_[0 / 32] & 14u) {
-    ::memset(&getters_count_, 0, reinterpret_cast<char*>(&configs_count_) -
-      reinterpret_cast<char*>(&getters_count_) + sizeof(configs_count_));
-  }
-  _has_bits_.Clear();
-  _internal_metadata_.Clear();
-}
-
-bool FieldAccessInfo::MergePartialFromCodedStream(
-    ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::google::protobuf::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.FieldAccessInfo)
-  for (;;) {
-    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // optional string name = 1;
-      case 1: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
-          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
-                input, this->mutable_name()));
-          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
-            ::google::protobuf::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.FieldAccessInfo.name");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional uint64 getters_count = 2;
-      case 2: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
-          set_has_getters_count();
-          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
-                 input, &getters_count_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional uint64 setters_count = 3;
-      case 3: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
-          set_has_setters_count();
-          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
-                 input, &setters_count_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional uint64 configs_count = 4;
-      case 4: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(32u)) {
-          set_has_configs_count();
-          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
-                 input, &configs_count_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
-          goto success;
-        }
-        DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.FieldAccessInfo)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.FieldAccessInfo)
-  return false;
-#undef DO_
-}
-
-void FieldAccessInfo::SerializeWithCachedSizes(
-    ::google::protobuf::io::CodedOutputStream* output) const {
-  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.FieldAccessInfo)
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  cached_has_bits = _has_bits_[0];
-  // optional string name = 1;
-  if (cached_has_bits & 0x00000001u) {
-    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
-      ::google::protobuf::internal::WireFormat::SERIALIZE,
-      "google.protobuf.compiler.FieldAccessInfo.name");
-    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
-      1, this->name(), output);
-  }
-
-  // optional uint64 getters_count = 2;
-  if (cached_has_bits & 0x00000002u) {
-    ::google::protobuf::internal::WireFormatLite::WriteUInt64(2, this->getters_count(), output);
-  }
-
-  // optional uint64 setters_count = 3;
-  if (cached_has_bits & 0x00000004u) {
-    ::google::protobuf::internal::WireFormatLite::WriteUInt64(3, this->setters_count(), output);
-  }
-
-  // optional uint64 configs_count = 4;
-  if (cached_has_bits & 0x00000008u) {
-    ::google::protobuf::internal::WireFormatLite::WriteUInt64(4, this->configs_count(), output);
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
-  }
-  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.FieldAccessInfo)
-}
-
-::google::protobuf::uint8* FieldAccessInfo::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.FieldAccessInfo)
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  cached_has_bits = _has_bits_[0];
-  // optional string name = 1;
-  if (cached_has_bits & 0x00000001u) {
-    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
-      ::google::protobuf::internal::WireFormat::SERIALIZE,
-      "google.protobuf.compiler.FieldAccessInfo.name");
-    target =
-      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
-        1, this->name(), target);
-  }
-
-  // optional uint64 getters_count = 2;
-  if (cached_has_bits & 0x00000002u) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(2, this->getters_count(), target);
-  }
-
-  // optional uint64 setters_count = 3;
-  if (cached_has_bits & 0x00000004u) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(3, this->setters_count(), target);
-  }
-
-  // optional uint64 configs_count = 4;
-  if (cached_has_bits & 0x00000008u) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(4, this->configs_count(), target);
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
-  }
-  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.FieldAccessInfo)
-  return target;
-}
-
-size_t FieldAccessInfo::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.FieldAccessInfo)
-  size_t total_size = 0;
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    total_size +=
-      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
-  }
-  if (_has_bits_[0 / 32] & 15u) {
-    // optional string name = 1;
-    if (has_name()) {
-      total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::StringSize(
-          this->name());
-    }
-
-    // optional uint64 getters_count = 2;
-    if (has_getters_count()) {
-      total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::UInt64Size(
-          this->getters_count());
-    }
-
-    // optional uint64 setters_count = 3;
-    if (has_setters_count()) {
-      total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::UInt64Size(
-          this->setters_count());
-    }
-
-    // optional uint64 configs_count = 4;
-    if (has_configs_count()) {
-      total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::UInt64Size(
-          this->configs_count());
-    }
-
-  }
-  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = cached_size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
-  return total_size;
-}
-
-void FieldAccessInfo::MergeFrom(const ::google::protobuf::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.FieldAccessInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  const FieldAccessInfo* source =
-      ::google::protobuf::internal::DynamicCastToGenerated<const FieldAccessInfo>(
-          &from);
-  if (source == NULL) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.FieldAccessInfo)
-    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.FieldAccessInfo)
-    MergeFrom(*source);
-  }
-}
-
-void FieldAccessInfo::MergeFrom(const FieldAccessInfo& from) {
-// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.FieldAccessInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom(from._internal_metadata_);
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  cached_has_bits = from._has_bits_[0];
-  if (cached_has_bits & 15u) {
-    if (cached_has_bits & 0x00000001u) {
-      set_has_name();
-      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
-    }
-    if (cached_has_bits & 0x00000002u) {
-      getters_count_ = from.getters_count_;
-    }
-    if (cached_has_bits & 0x00000004u) {
-      setters_count_ = from.setters_count_;
-    }
-    if (cached_has_bits & 0x00000008u) {
-      configs_count_ = from.configs_count_;
-    }
-    _has_bits_[0] |= cached_has_bits;
-  }
-}
-
-void FieldAccessInfo::CopyFrom(const ::google::protobuf::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.FieldAccessInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
-}
-
-void FieldAccessInfo::CopyFrom(const FieldAccessInfo& from) {
-// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.FieldAccessInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
-}
-
-bool FieldAccessInfo::IsInitialized() const {
-  return true;
-}
-
-void FieldAccessInfo::Swap(FieldAccessInfo* other) {
-  if (other == this) return;
-  InternalSwap(other);
-}
-void FieldAccessInfo::InternalSwap(FieldAccessInfo* other) {
-  name_.Swap(&other->name_);
-  std::swap(getters_count_, other->getters_count_);
-  std::swap(setters_count_, other->setters_count_);
-  std::swap(configs_count_, other->configs_count_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
-  _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
-}
-
-::google::protobuf::Metadata FieldAccessInfo::GetMetadata() const {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::protobuf_AssignDescriptorsOnce();
-  return protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::file_level_metadata[kIndexInFileMessages];
-}
-
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// FieldAccessInfo
-
-// optional string name = 1;
-bool FieldAccessInfo::has_name() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void FieldAccessInfo::set_has_name() {
-  _has_bits_[0] |= 0x00000001u;
-}
-void FieldAccessInfo::clear_has_name() {
-  _has_bits_[0] &= ~0x00000001u;
-}
-void FieldAccessInfo::clear_name() {
-  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_name();
-}
-const ::std::string& FieldAccessInfo::name() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.name)
-  return name_.GetNoArena();
-}
-void FieldAccessInfo::set_name(const ::std::string& value) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.name)
-}
-#if LANG_CXX11
-void FieldAccessInfo::set_name(::std::string&& value) {
-  set_has_name();
-  name_.SetNoArena(
-    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.FieldAccessInfo.name)
-}
-#endif
-void FieldAccessInfo::set_name(const char* value) {
-  GOOGLE_DCHECK(value != NULL);
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.FieldAccessInfo.name)
-}
-void FieldAccessInfo::set_name(const char* value, size_t size) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.FieldAccessInfo.name)
-}
-::std::string* FieldAccessInfo::mutable_name() {
-  set_has_name();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.FieldAccessInfo.name)
-  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* FieldAccessInfo::release_name() {
-  // @@protoc_insertion_point(field_release:google.protobuf.compiler.FieldAccessInfo.name)
-  clear_has_name();
-  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void FieldAccessInfo::set_allocated_name(::std::string* name) {
-  if (name != NULL) {
-    set_has_name();
-  } else {
-    clear_has_name();
-  }
-  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.FieldAccessInfo.name)
-}
-
-// optional uint64 getters_count = 2;
-bool FieldAccessInfo::has_getters_count() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void FieldAccessInfo::set_has_getters_count() {
-  _has_bits_[0] |= 0x00000002u;
-}
-void FieldAccessInfo::clear_has_getters_count() {
-  _has_bits_[0] &= ~0x00000002u;
-}
-void FieldAccessInfo::clear_getters_count() {
-  getters_count_ = GOOGLE_ULONGLONG(0);
-  clear_has_getters_count();
-}
-::google::protobuf::uint64 FieldAccessInfo::getters_count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.getters_count)
-  return getters_count_;
-}
-void FieldAccessInfo::set_getters_count(::google::protobuf::uint64 value) {
-  set_has_getters_count();
-  getters_count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.getters_count)
-}
-
-// optional uint64 setters_count = 3;
-bool FieldAccessInfo::has_setters_count() const {
-  return (_has_bits_[0] & 0x00000004u) != 0;
-}
-void FieldAccessInfo::set_has_setters_count() {
-  _has_bits_[0] |= 0x00000004u;
-}
-void FieldAccessInfo::clear_has_setters_count() {
-  _has_bits_[0] &= ~0x00000004u;
-}
-void FieldAccessInfo::clear_setters_count() {
-  setters_count_ = GOOGLE_ULONGLONG(0);
-  clear_has_setters_count();
-}
-::google::protobuf::uint64 FieldAccessInfo::setters_count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.setters_count)
-  return setters_count_;
-}
-void FieldAccessInfo::set_setters_count(::google::protobuf::uint64 value) {
-  set_has_setters_count();
-  setters_count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.setters_count)
-}
-
-// optional uint64 configs_count = 4;
-bool FieldAccessInfo::has_configs_count() const {
-  return (_has_bits_[0] & 0x00000008u) != 0;
-}
-void FieldAccessInfo::set_has_configs_count() {
-  _has_bits_[0] |= 0x00000008u;
-}
-void FieldAccessInfo::clear_has_configs_count() {
-  _has_bits_[0] &= ~0x00000008u;
-}
-void FieldAccessInfo::clear_configs_count() {
-  configs_count_ = GOOGLE_ULONGLONG(0);
-  clear_has_configs_count();
-}
-::google::protobuf::uint64 FieldAccessInfo::configs_count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.configs_count)
-  return configs_count_;
-}
-void FieldAccessInfo::set_configs_count(::google::protobuf::uint64 value) {
-  set_has_configs_count();
-  configs_count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.configs_count)
-}
-
-#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
-
-// ===================================================================
-
-#if !defined(_MSC_VER) || _MSC_VER >= 1900
-const int MessageAccessInfo::kNameFieldNumber;
-const int MessageAccessInfo::kCountFieldNumber;
-const int MessageAccessInfo::kFieldFieldNumber;
-#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
-
-MessageAccessInfo::MessageAccessInfo()
-  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
-  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
-    protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::InitDefaults();
-  }
-  SharedCtor();
-  // @@protoc_insertion_point(constructor:google.protobuf.compiler.MessageAccessInfo)
-}
-MessageAccessInfo::MessageAccessInfo(const MessageAccessInfo& from)
-  : ::google::protobuf::Message(),
-      _internal_metadata_(NULL),
-      _has_bits_(from._has_bits_),
-      _cached_size_(0),
-      field_(from.field_) {
-  _internal_metadata_.MergeFrom(from._internal_metadata_);
-  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (from.has_name()) {
-    name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
-  }
-  count_ = from.count_;
-  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.MessageAccessInfo)
-}
-
-void MessageAccessInfo::SharedCtor() {
-  _cached_size_ = 0;
-  name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  count_ = GOOGLE_ULONGLONG(0);
-}
-
-MessageAccessInfo::~MessageAccessInfo() {
-  // @@protoc_insertion_point(destructor:google.protobuf.compiler.MessageAccessInfo)
-  SharedDtor();
-}
-
-void MessageAccessInfo::SharedDtor() {
-  name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-
-void MessageAccessInfo::SetCachedSize(int size) const {
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
-}
-const ::google::protobuf::Descriptor* MessageAccessInfo::descriptor() {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::protobuf_AssignDescriptorsOnce();
-  return protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
-}
-
-const MessageAccessInfo& MessageAccessInfo::default_instance() {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::InitDefaults();
-  return *internal_default_instance();
-}
-
-MessageAccessInfo* MessageAccessInfo::New(::google::protobuf::Arena* arena) const {
-  MessageAccessInfo* n = new MessageAccessInfo;
-  if (arena != NULL) {
-    arena->Own(n);
-  }
-  return n;
-}
-
-void MessageAccessInfo::Clear() {
-// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.MessageAccessInfo)
-  field_.Clear();
-  if (has_name()) {
-    GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
-    (*name_.UnsafeRawStringPointer())->clear();
-  }
-  count_ = GOOGLE_ULONGLONG(0);
-  _has_bits_.Clear();
-  _internal_metadata_.Clear();
-}
-
-bool MessageAccessInfo::MergePartialFromCodedStream(
-    ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::google::protobuf::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.MessageAccessInfo)
-  for (;;) {
-    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // optional string name = 1;
-      case 1: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
-          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
-                input, this->mutable_name()));
-          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
-            ::google::protobuf::internal::WireFormat::PARSE,
-            "google.protobuf.compiler.MessageAccessInfo.name");
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // optional uint64 count = 2;
-      case 2: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
-          set_has_count();
-          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                   ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
-                 input, &count_)));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      // repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-      case 3: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
-          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
-                input, add_field()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
-          goto success;
-        }
-        DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.MessageAccessInfo)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.MessageAccessInfo)
-  return false;
-#undef DO_
-}
-
-void MessageAccessInfo::SerializeWithCachedSizes(
-    ::google::protobuf::io::CodedOutputStream* output) const {
-  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.MessageAccessInfo)
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  cached_has_bits = _has_bits_[0];
-  // optional string name = 1;
-  if (cached_has_bits & 0x00000001u) {
-    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
-      ::google::protobuf::internal::WireFormat::SERIALIZE,
-      "google.protobuf.compiler.MessageAccessInfo.name");
-    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
-      1, this->name(), output);
-  }
-
-  // optional uint64 count = 2;
-  if (cached_has_bits & 0x00000002u) {
-    ::google::protobuf::internal::WireFormatLite::WriteUInt64(2, this->count(), output);
-  }
-
-  // repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-  for (unsigned int i = 0, n = this->field_size(); i < n; i++) {
-    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      3, this->field(i), output);
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
-  }
-  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.MessageAccessInfo)
-}
-
-::google::protobuf::uint8* MessageAccessInfo::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.MessageAccessInfo)
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  cached_has_bits = _has_bits_[0];
-  // optional string name = 1;
-  if (cached_has_bits & 0x00000001u) {
-    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
-      ::google::protobuf::internal::WireFormat::SERIALIZE,
-      "google.protobuf.compiler.MessageAccessInfo.name");
-    target =
-      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
-        1, this->name(), target);
-  }
-
-  // optional uint64 count = 2;
-  if (cached_has_bits & 0x00000002u) {
-    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(2, this->count(), target);
-  }
-
-  // repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-  for (unsigned int i = 0, n = this->field_size(); i < n; i++) {
-    target = ::google::protobuf::internal::WireFormatLite::
-      InternalWriteMessageNoVirtualToArray(
-        3, this->field(i), deterministic, target);
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
-  }
-  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.MessageAccessInfo)
-  return target;
-}
-
-size_t MessageAccessInfo::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.MessageAccessInfo)
-  size_t total_size = 0;
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    total_size +=
-      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
-  }
-  // repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-  {
-    unsigned int count = this->field_size();
-    total_size += 1UL * count;
-    for (unsigned int i = 0; i < count; i++) {
-      total_size +=
-        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->field(i));
-    }
-  }
-
-  if (_has_bits_[0 / 32] & 3u) {
-    // optional string name = 1;
-    if (has_name()) {
-      total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::StringSize(
-          this->name());
-    }
-
-    // optional uint64 count = 2;
-    if (has_count()) {
-      total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::UInt64Size(
-          this->count());
-    }
-
-  }
-  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = cached_size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
-  return total_size;
-}
-
-void MessageAccessInfo::MergeFrom(const ::google::protobuf::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.MessageAccessInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  const MessageAccessInfo* source =
-      ::google::protobuf::internal::DynamicCastToGenerated<const MessageAccessInfo>(
-          &from);
-  if (source == NULL) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.MessageAccessInfo)
-    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.MessageAccessInfo)
-    MergeFrom(*source);
-  }
-}
-
-void MessageAccessInfo::MergeFrom(const MessageAccessInfo& from) {
-// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.MessageAccessInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom(from._internal_metadata_);
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  field_.MergeFrom(from.field_);
-  cached_has_bits = from._has_bits_[0];
-  if (cached_has_bits & 3u) {
-    if (cached_has_bits & 0x00000001u) {
-      set_has_name();
-      name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_);
-    }
-    if (cached_has_bits & 0x00000002u) {
-      count_ = from.count_;
-    }
-    _has_bits_[0] |= cached_has_bits;
-  }
-}
-
-void MessageAccessInfo::CopyFrom(const ::google::protobuf::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.MessageAccessInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
-}
-
-void MessageAccessInfo::CopyFrom(const MessageAccessInfo& from) {
-// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.MessageAccessInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
-}
-
-bool MessageAccessInfo::IsInitialized() const {
-  return true;
-}
-
-void MessageAccessInfo::Swap(MessageAccessInfo* other) {
-  if (other == this) return;
-  InternalSwap(other);
-}
-void MessageAccessInfo::InternalSwap(MessageAccessInfo* other) {
-  field_.InternalSwap(&other->field_);
-  name_.Swap(&other->name_);
-  std::swap(count_, other->count_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
-  _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
-}
-
-::google::protobuf::Metadata MessageAccessInfo::GetMetadata() const {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::protobuf_AssignDescriptorsOnce();
-  return protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::file_level_metadata[kIndexInFileMessages];
-}
-
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// MessageAccessInfo
-
-// optional string name = 1;
-bool MessageAccessInfo::has_name() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
-}
-void MessageAccessInfo::set_has_name() {
-  _has_bits_[0] |= 0x00000001u;
-}
-void MessageAccessInfo::clear_has_name() {
-  _has_bits_[0] &= ~0x00000001u;
-}
-void MessageAccessInfo::clear_name() {
-  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_name();
-}
-const ::std::string& MessageAccessInfo::name() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.MessageAccessInfo.name)
-  return name_.GetNoArena();
-}
-void MessageAccessInfo::set_name(const ::std::string& value) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.MessageAccessInfo.name)
-}
-#if LANG_CXX11
-void MessageAccessInfo::set_name(::std::string&& value) {
-  set_has_name();
-  name_.SetNoArena(
-    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.MessageAccessInfo.name)
-}
-#endif
-void MessageAccessInfo::set_name(const char* value) {
-  GOOGLE_DCHECK(value != NULL);
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.MessageAccessInfo.name)
-}
-void MessageAccessInfo::set_name(const char* value, size_t size) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.MessageAccessInfo.name)
-}
-::std::string* MessageAccessInfo::mutable_name() {
-  set_has_name();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.MessageAccessInfo.name)
-  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-::std::string* MessageAccessInfo::release_name() {
-  // @@protoc_insertion_point(field_release:google.protobuf.compiler.MessageAccessInfo.name)
-  clear_has_name();
-  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-void MessageAccessInfo::set_allocated_name(::std::string* name) {
-  if (name != NULL) {
-    set_has_name();
-  } else {
-    clear_has_name();
-  }
-  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.MessageAccessInfo.name)
-}
-
-// optional uint64 count = 2;
-bool MessageAccessInfo::has_count() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
-}
-void MessageAccessInfo::set_has_count() {
-  _has_bits_[0] |= 0x00000002u;
-}
-void MessageAccessInfo::clear_has_count() {
-  _has_bits_[0] &= ~0x00000002u;
-}
-void MessageAccessInfo::clear_count() {
-  count_ = GOOGLE_ULONGLONG(0);
-  clear_has_count();
-}
-::google::protobuf::uint64 MessageAccessInfo::count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.MessageAccessInfo.count)
-  return count_;
-}
-void MessageAccessInfo::set_count(::google::protobuf::uint64 value) {
-  set_has_count();
-  count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.MessageAccessInfo.count)
-}
-
-// repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-int MessageAccessInfo::field_size() const {
-  return field_.size();
-}
-void MessageAccessInfo::clear_field() {
-  field_.Clear();
-}
-const ::google::protobuf::compiler::FieldAccessInfo& MessageAccessInfo::field(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_.Get(index);
-}
-::google::protobuf::compiler::FieldAccessInfo* MessageAccessInfo::mutable_field(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_.Mutable(index);
-}
-::google::protobuf::compiler::FieldAccessInfo* MessageAccessInfo::add_field() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_.Add();
-}
-::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo >*
-MessageAccessInfo::mutable_field() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.MessageAccessInfo.field)
-  return &field_;
-}
-const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo >&
-MessageAccessInfo::field() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_;
-}
-
-#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
-
-// ===================================================================
-
-#if !defined(_MSC_VER) || _MSC_VER >= 1900
-const int AccessInfo::kMessageFieldNumber;
-#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
-
-AccessInfo::AccessInfo()
-  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
-  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
-    protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::InitDefaults();
-  }
-  SharedCtor();
-  // @@protoc_insertion_point(constructor:google.protobuf.compiler.AccessInfo)
-}
-AccessInfo::AccessInfo(const AccessInfo& from)
-  : ::google::protobuf::Message(),
-      _internal_metadata_(NULL),
-      _has_bits_(from._has_bits_),
-      _cached_size_(0),
-      message_(from.message_) {
-  _internal_metadata_.MergeFrom(from._internal_metadata_);
-  // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.AccessInfo)
-}
-
-void AccessInfo::SharedCtor() {
-  _cached_size_ = 0;
-}
-
-AccessInfo::~AccessInfo() {
-  // @@protoc_insertion_point(destructor:google.protobuf.compiler.AccessInfo)
-  SharedDtor();
-}
-
-void AccessInfo::SharedDtor() {
-}
-
-void AccessInfo::SetCachedSize(int size) const {
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
-}
-const ::google::protobuf::Descriptor* AccessInfo::descriptor() {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::protobuf_AssignDescriptorsOnce();
-  return protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
-}
-
-const AccessInfo& AccessInfo::default_instance() {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::InitDefaults();
-  return *internal_default_instance();
-}
-
-AccessInfo* AccessInfo::New(::google::protobuf::Arena* arena) const {
-  AccessInfo* n = new AccessInfo;
-  if (arena != NULL) {
-    arena->Own(n);
-  }
-  return n;
-}
-
-void AccessInfo::Clear() {
-// @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.AccessInfo)
-  message_.Clear();
-  _has_bits_.Clear();
-  _internal_metadata_.Clear();
-}
-
-bool AccessInfo::MergePartialFromCodedStream(
-    ::google::protobuf::io::CodedInputStream* input) {
-#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
-  ::google::protobuf::uint32 tag;
-  // @@protoc_insertion_point(parse_start:google.protobuf.compiler.AccessInfo)
-  for (;;) {
-    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
-    tag = p.first;
-    if (!p.second) goto handle_unusual;
-    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
-      // repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-      case 1: {
-        if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
-          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
-                input, add_message()));
-        } else {
-          goto handle_unusual;
-        }
-        break;
-      }
-
-      default: {
-      handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
-          goto success;
-        }
-        DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
-        break;
-      }
-    }
-  }
-success:
-  // @@protoc_insertion_point(parse_success:google.protobuf.compiler.AccessInfo)
-  return true;
-failure:
-  // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.AccessInfo)
-  return false;
-#undef DO_
-}
-
-void AccessInfo::SerializeWithCachedSizes(
-    ::google::protobuf::io::CodedOutputStream* output) const {
-  // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.AccessInfo)
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  // repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-  for (unsigned int i = 0, n = this->message_size(); i < n; i++) {
-    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      1, this->message(i), output);
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
-  }
-  // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.AccessInfo)
-}
-
-::google::protobuf::uint8* AccessInfo::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, ::google::protobuf::uint8* target) const {
-  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.AccessInfo)
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  // repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-  for (unsigned int i = 0, n = this->message_size(); i < n; i++) {
-    target = ::google::protobuf::internal::WireFormatLite::
-      InternalWriteMessageNoVirtualToArray(
-        1, this->message(i), deterministic, target);
-  }
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
-  }
-  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.AccessInfo)
-  return target;
-}
-
-size_t AccessInfo::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.AccessInfo)
-  size_t total_size = 0;
-
-  if (_internal_metadata_.have_unknown_fields()) {
-    total_size +=
-      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
-  }
-  // repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-  {
-    unsigned int count = this->message_size();
-    total_size += 1UL * count;
-    for (unsigned int i = 0; i < count; i++) {
-      total_size +=
-        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->message(i));
-    }
-  }
-
-  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
-  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
-  _cached_size_ = cached_size;
-  GOOGLE_SAFE_CONCURRENT_WRITES_END();
-  return total_size;
-}
-
-void AccessInfo::MergeFrom(const ::google::protobuf::Message& from) {
-// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.AccessInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  const AccessInfo* source =
-      ::google::protobuf::internal::DynamicCastToGenerated<const AccessInfo>(
-          &from);
-  if (source == NULL) {
-  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.compiler.AccessInfo)
-    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
-  } else {
-  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.compiler.AccessInfo)
-    MergeFrom(*source);
-  }
-}
-
-void AccessInfo::MergeFrom(const AccessInfo& from) {
-// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.AccessInfo)
-  GOOGLE_DCHECK_NE(&from, this);
-  _internal_metadata_.MergeFrom(from._internal_metadata_);
-  ::google::protobuf::uint32 cached_has_bits = 0;
-  (void) cached_has_bits;
-
-  message_.MergeFrom(from.message_);
-}
-
-void AccessInfo::CopyFrom(const ::google::protobuf::Message& from) {
-// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.compiler.AccessInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
-}
-
-void AccessInfo::CopyFrom(const AccessInfo& from) {
-// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.compiler.AccessInfo)
-  if (&from == this) return;
-  Clear();
-  MergeFrom(from);
-}
-
-bool AccessInfo::IsInitialized() const {
-  return true;
-}
-
-void AccessInfo::Swap(AccessInfo* other) {
-  if (other == this) return;
-  InternalSwap(other);
-}
-void AccessInfo::InternalSwap(AccessInfo* other) {
-  message_.InternalSwap(&other->message_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
-  _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
-}
-
-::google::protobuf::Metadata AccessInfo::GetMetadata() const {
-  protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::protobuf_AssignDescriptorsOnce();
-  return protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::file_level_metadata[kIndexInFileMessages];
-}
-
-#if PROTOBUF_INLINE_NOT_IN_HEADERS
-// AccessInfo
-
-// repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-int AccessInfo::message_size() const {
-  return message_.size();
-}
-void AccessInfo::clear_message() {
-  message_.Clear();
-}
-const ::google::protobuf::compiler::MessageAccessInfo& AccessInfo::message(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.AccessInfo.message)
-  return message_.Get(index);
-}
-::google::protobuf::compiler::MessageAccessInfo* AccessInfo::mutable_message(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.AccessInfo.message)
-  return message_.Mutable(index);
-}
-::google::protobuf::compiler::MessageAccessInfo* AccessInfo::add_message() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.AccessInfo.message)
-  return message_.Add();
-}
-::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo >*
-AccessInfo::mutable_message() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.AccessInfo.message)
-  return &message_;
-}
-const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo >&
-AccessInfo::message() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.AccessInfo.message)
-  return message_;
-}
-
-#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
-
-// @@protoc_insertion_point(namespace_scope)
-
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-// @@protoc_insertion_point(global_scope)
diff --git a/src/google/protobuf/compiler/profile.pb.h b/src/google/protobuf/compiler/profile.pb.h
deleted file mode 100644
index d20b87e..0000000
--- a/src/google/protobuf/compiler/profile.pb.h
+++ /dev/null
@@ -1,728 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: google/protobuf/compiler/profile.proto
-
-#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fprofile_2eproto__INCLUDED
-#define PROTOBUF_google_2fprotobuf_2fcompiler_2fprofile_2eproto__INCLUDED
-
-#include <string>
-
-#include <google/protobuf/stubs/common.h>
-
-#if GOOGLE_PROTOBUF_VERSION < 3003000
-#error This file was generated by a newer version of protoc which is
-#error incompatible with your Protocol Buffer headers.  Please update
-#error your headers.
-#endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
-#error This file was generated by an older version of protoc which is
-#error incompatible with your Protocol Buffer headers.  Please
-#error regenerate this file with a newer version of protoc.
-#endif
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_table_driven.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
-// @@protoc_insertion_point(includes)
-namespace google {
-namespace protobuf {
-namespace compiler {
-class AccessInfo;
-class AccessInfoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern AccessInfoDefaultTypeInternal _AccessInfo_default_instance_;
-class FieldAccessInfo;
-class FieldAccessInfoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern FieldAccessInfoDefaultTypeInternal _FieldAccessInfo_default_instance_;
-class MessageAccessInfo;
-class MessageAccessInfoDefaultTypeInternal;
-LIBPROTOC_EXPORT extern MessageAccessInfoDefaultTypeInternal _MessageAccessInfo_default_instance_;
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-
-namespace protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto {
-// Internal implementation detail -- do not call these.
-struct LIBPROTOC_EXPORT TableStruct {
-  static const ::google::protobuf::internal::ParseTableField entries[];
-  static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
-  static const ::google::protobuf::internal::ParseTable schema[];
-  static const ::google::protobuf::uint32 offsets[];
-  static void InitDefaultsImpl();
-  static void Shutdown();
-};
-void LIBPROTOC_EXPORT AddDescriptors();
-void LIBPROTOC_EXPORT InitDefaults();
-}  // namespace protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto
-
-// ===================================================================
-
-class LIBPROTOC_EXPORT FieldAccessInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.FieldAccessInfo) */ {
- public:
-  FieldAccessInfo();
-  virtual ~FieldAccessInfo();
-
-  FieldAccessInfo(const FieldAccessInfo& from);
-
-  inline FieldAccessInfo& operator=(const FieldAccessInfo& from) {
-    CopyFrom(from);
-    return *this;
-  }
-
-  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
-    return _internal_metadata_.unknown_fields();
-  }
-
-  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
-    return _internal_metadata_.mutable_unknown_fields();
-  }
-
-  static const ::google::protobuf::Descriptor* descriptor();
-  static const FieldAccessInfo& default_instance();
-
-  static inline const FieldAccessInfo* internal_default_instance() {
-    return reinterpret_cast<const FieldAccessInfo*>(
-               &_FieldAccessInfo_default_instance_);
-  }
-  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    0;
-
-  void Swap(FieldAccessInfo* other);
-
-  // implements Message ----------------------------------------------
-
-  inline FieldAccessInfo* New() const PROTOBUF_FINAL { return New(NULL); }
-
-  FieldAccessInfo* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
-  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
-  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
-  void CopyFrom(const FieldAccessInfo& from);
-  void MergeFrom(const FieldAccessInfo& from);
-  void Clear() PROTOBUF_FINAL;
-  bool IsInitialized() const PROTOBUF_FINAL;
-
-  size_t ByteSizeLong() const PROTOBUF_FINAL;
-  bool MergePartialFromCodedStream(
-      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
-  void SerializeWithCachedSizes(
-      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
-  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
-  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
-  private:
-  void SharedCtor();
-  void SharedDtor();
-  void SetCachedSize(int size) const PROTOBUF_FINAL;
-  void InternalSwap(FieldAccessInfo* other);
-  private:
-  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
-    return NULL;
-  }
-  inline void* MaybeArenaPtr() const {
-    return NULL;
-  }
-  public:
-
-  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
-
-  // nested types ----------------------------------------------------
-
-  // accessors -------------------------------------------------------
-
-  // optional string name = 1;
-  bool has_name() const;
-  void clear_name();
-  static const int kNameFieldNumber = 1;
-  const ::std::string& name() const;
-  void set_name(const ::std::string& value);
-  #if LANG_CXX11
-  void set_name(::std::string&& value);
-  #endif
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
-  ::std::string* mutable_name();
-  ::std::string* release_name();
-  void set_allocated_name(::std::string* name);
-
-  // optional uint64 getters_count = 2;
-  bool has_getters_count() const;
-  void clear_getters_count();
-  static const int kGettersCountFieldNumber = 2;
-  ::google::protobuf::uint64 getters_count() const;
-  void set_getters_count(::google::protobuf::uint64 value);
-
-  // optional uint64 setters_count = 3;
-  bool has_setters_count() const;
-  void clear_setters_count();
-  static const int kSettersCountFieldNumber = 3;
-  ::google::protobuf::uint64 setters_count() const;
-  void set_setters_count(::google::protobuf::uint64 value);
-
-  // optional uint64 configs_count = 4;
-  bool has_configs_count() const;
-  void clear_configs_count();
-  static const int kConfigsCountFieldNumber = 4;
-  ::google::protobuf::uint64 configs_count() const;
-  void set_configs_count(::google::protobuf::uint64 value);
-
-  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.FieldAccessInfo)
- private:
-  void set_has_name();
-  void clear_has_name();
-  void set_has_getters_count();
-  void clear_has_getters_count();
-  void set_has_setters_count();
-  void clear_has_setters_count();
-  void set_has_configs_count();
-  void clear_has_configs_count();
-
-  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::internal::HasBits<1> _has_bits_;
-  mutable int _cached_size_;
-  ::google::protobuf::internal::ArenaStringPtr name_;
-  ::google::protobuf::uint64 getters_count_;
-  ::google::protobuf::uint64 setters_count_;
-  ::google::protobuf::uint64 configs_count_;
-  friend struct protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::TableStruct;
-};
-// -------------------------------------------------------------------
-
-class LIBPROTOC_EXPORT MessageAccessInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.MessageAccessInfo) */ {
- public:
-  MessageAccessInfo();
-  virtual ~MessageAccessInfo();
-
-  MessageAccessInfo(const MessageAccessInfo& from);
-
-  inline MessageAccessInfo& operator=(const MessageAccessInfo& from) {
-    CopyFrom(from);
-    return *this;
-  }
-
-  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
-    return _internal_metadata_.unknown_fields();
-  }
-
-  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
-    return _internal_metadata_.mutable_unknown_fields();
-  }
-
-  static const ::google::protobuf::Descriptor* descriptor();
-  static const MessageAccessInfo& default_instance();
-
-  static inline const MessageAccessInfo* internal_default_instance() {
-    return reinterpret_cast<const MessageAccessInfo*>(
-               &_MessageAccessInfo_default_instance_);
-  }
-  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    1;
-
-  void Swap(MessageAccessInfo* other);
-
-  // implements Message ----------------------------------------------
-
-  inline MessageAccessInfo* New() const PROTOBUF_FINAL { return New(NULL); }
-
-  MessageAccessInfo* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
-  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
-  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
-  void CopyFrom(const MessageAccessInfo& from);
-  void MergeFrom(const MessageAccessInfo& from);
-  void Clear() PROTOBUF_FINAL;
-  bool IsInitialized() const PROTOBUF_FINAL;
-
-  size_t ByteSizeLong() const PROTOBUF_FINAL;
-  bool MergePartialFromCodedStream(
-      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
-  void SerializeWithCachedSizes(
-      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
-  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
-  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
-  private:
-  void SharedCtor();
-  void SharedDtor();
-  void SetCachedSize(int size) const PROTOBUF_FINAL;
-  void InternalSwap(MessageAccessInfo* other);
-  private:
-  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
-    return NULL;
-  }
-  inline void* MaybeArenaPtr() const {
-    return NULL;
-  }
-  public:
-
-  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
-
-  // nested types ----------------------------------------------------
-
-  // accessors -------------------------------------------------------
-
-  // repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-  int field_size() const;
-  void clear_field();
-  static const int kFieldFieldNumber = 3;
-  const ::google::protobuf::compiler::FieldAccessInfo& field(int index) const;
-  ::google::protobuf::compiler::FieldAccessInfo* mutable_field(int index);
-  ::google::protobuf::compiler::FieldAccessInfo* add_field();
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo >*
-      mutable_field();
-  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo >&
-      field() const;
-
-  // optional string name = 1;
-  bool has_name() const;
-  void clear_name();
-  static const int kNameFieldNumber = 1;
-  const ::std::string& name() const;
-  void set_name(const ::std::string& value);
-  #if LANG_CXX11
-  void set_name(::std::string&& value);
-  #endif
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
-  ::std::string* mutable_name();
-  ::std::string* release_name();
-  void set_allocated_name(::std::string* name);
-
-  // optional uint64 count = 2;
-  bool has_count() const;
-  void clear_count();
-  static const int kCountFieldNumber = 2;
-  ::google::protobuf::uint64 count() const;
-  void set_count(::google::protobuf::uint64 value);
-
-  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.MessageAccessInfo)
- private:
-  void set_has_name();
-  void clear_has_name();
-  void set_has_count();
-  void clear_has_count();
-
-  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::internal::HasBits<1> _has_bits_;
-  mutable int _cached_size_;
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo > field_;
-  ::google::protobuf::internal::ArenaStringPtr name_;
-  ::google::protobuf::uint64 count_;
-  friend struct protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::TableStruct;
-};
-// -------------------------------------------------------------------
-
-class LIBPROTOC_EXPORT AccessInfo : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.AccessInfo) */ {
- public:
-  AccessInfo();
-  virtual ~AccessInfo();
-
-  AccessInfo(const AccessInfo& from);
-
-  inline AccessInfo& operator=(const AccessInfo& from) {
-    CopyFrom(from);
-    return *this;
-  }
-
-  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
-    return _internal_metadata_.unknown_fields();
-  }
-
-  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
-    return _internal_metadata_.mutable_unknown_fields();
-  }
-
-  static const ::google::protobuf::Descriptor* descriptor();
-  static const AccessInfo& default_instance();
-
-  static inline const AccessInfo* internal_default_instance() {
-    return reinterpret_cast<const AccessInfo*>(
-               &_AccessInfo_default_instance_);
-  }
-  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    2;
-
-  void Swap(AccessInfo* other);
-
-  // implements Message ----------------------------------------------
-
-  inline AccessInfo* New() const PROTOBUF_FINAL { return New(NULL); }
-
-  AccessInfo* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
-  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
-  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
-  void CopyFrom(const AccessInfo& from);
-  void MergeFrom(const AccessInfo& from);
-  void Clear() PROTOBUF_FINAL;
-  bool IsInitialized() const PROTOBUF_FINAL;
-
-  size_t ByteSizeLong() const PROTOBUF_FINAL;
-  bool MergePartialFromCodedStream(
-      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
-  void SerializeWithCachedSizes(
-      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
-  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
-      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
-  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
-  private:
-  void SharedCtor();
-  void SharedDtor();
-  void SetCachedSize(int size) const PROTOBUF_FINAL;
-  void InternalSwap(AccessInfo* other);
-  private:
-  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
-    return NULL;
-  }
-  inline void* MaybeArenaPtr() const {
-    return NULL;
-  }
-  public:
-
-  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
-
-  // nested types ----------------------------------------------------
-
-  // accessors -------------------------------------------------------
-
-  // repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-  int message_size() const;
-  void clear_message();
-  static const int kMessageFieldNumber = 1;
-  const ::google::protobuf::compiler::MessageAccessInfo& message(int index) const;
-  ::google::protobuf::compiler::MessageAccessInfo* mutable_message(int index);
-  ::google::protobuf::compiler::MessageAccessInfo* add_message();
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo >*
-      mutable_message();
-  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo >&
-      message() const;
-
-  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.AccessInfo)
- private:
-
-  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  ::google::protobuf::internal::HasBits<1> _has_bits_;
-  mutable int _cached_size_;
-  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo > message_;
-  friend struct protobuf_google_2fprotobuf_2fcompiler_2fprofile_2eproto::TableStruct;
-};
-// ===================================================================
-
-
-// ===================================================================
-
-#if !PROTOBUF_INLINE_NOT_IN_HEADERS
-// FieldAccessInfo
-
-// optional string name = 1;
-inline bool FieldAccessInfo::has_name() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
-}
-inline void FieldAccessInfo::set_has_name() {
-  _has_bits_[0] |= 0x00000001u;
-}
-inline void FieldAccessInfo::clear_has_name() {
-  _has_bits_[0] &= ~0x00000001u;
-}
-inline void FieldAccessInfo::clear_name() {
-  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_name();
-}
-inline const ::std::string& FieldAccessInfo::name() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.name)
-  return name_.GetNoArena();
-}
-inline void FieldAccessInfo::set_name(const ::std::string& value) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.name)
-}
-#if LANG_CXX11
-inline void FieldAccessInfo::set_name(::std::string&& value) {
-  set_has_name();
-  name_.SetNoArena(
-    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.FieldAccessInfo.name)
-}
-#endif
-inline void FieldAccessInfo::set_name(const char* value) {
-  GOOGLE_DCHECK(value != NULL);
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.FieldAccessInfo.name)
-}
-inline void FieldAccessInfo::set_name(const char* value, size_t size) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.FieldAccessInfo.name)
-}
-inline ::std::string* FieldAccessInfo::mutable_name() {
-  set_has_name();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.FieldAccessInfo.name)
-  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-inline ::std::string* FieldAccessInfo::release_name() {
-  // @@protoc_insertion_point(field_release:google.protobuf.compiler.FieldAccessInfo.name)
-  clear_has_name();
-  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-inline void FieldAccessInfo::set_allocated_name(::std::string* name) {
-  if (name != NULL) {
-    set_has_name();
-  } else {
-    clear_has_name();
-  }
-  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.FieldAccessInfo.name)
-}
-
-// optional uint64 getters_count = 2;
-inline bool FieldAccessInfo::has_getters_count() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
-}
-inline void FieldAccessInfo::set_has_getters_count() {
-  _has_bits_[0] |= 0x00000002u;
-}
-inline void FieldAccessInfo::clear_has_getters_count() {
-  _has_bits_[0] &= ~0x00000002u;
-}
-inline void FieldAccessInfo::clear_getters_count() {
-  getters_count_ = GOOGLE_ULONGLONG(0);
-  clear_has_getters_count();
-}
-inline ::google::protobuf::uint64 FieldAccessInfo::getters_count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.getters_count)
-  return getters_count_;
-}
-inline void FieldAccessInfo::set_getters_count(::google::protobuf::uint64 value) {
-  set_has_getters_count();
-  getters_count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.getters_count)
-}
-
-// optional uint64 setters_count = 3;
-inline bool FieldAccessInfo::has_setters_count() const {
-  return (_has_bits_[0] & 0x00000004u) != 0;
-}
-inline void FieldAccessInfo::set_has_setters_count() {
-  _has_bits_[0] |= 0x00000004u;
-}
-inline void FieldAccessInfo::clear_has_setters_count() {
-  _has_bits_[0] &= ~0x00000004u;
-}
-inline void FieldAccessInfo::clear_setters_count() {
-  setters_count_ = GOOGLE_ULONGLONG(0);
-  clear_has_setters_count();
-}
-inline ::google::protobuf::uint64 FieldAccessInfo::setters_count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.setters_count)
-  return setters_count_;
-}
-inline void FieldAccessInfo::set_setters_count(::google::protobuf::uint64 value) {
-  set_has_setters_count();
-  setters_count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.setters_count)
-}
-
-// optional uint64 configs_count = 4;
-inline bool FieldAccessInfo::has_configs_count() const {
-  return (_has_bits_[0] & 0x00000008u) != 0;
-}
-inline void FieldAccessInfo::set_has_configs_count() {
-  _has_bits_[0] |= 0x00000008u;
-}
-inline void FieldAccessInfo::clear_has_configs_count() {
-  _has_bits_[0] &= ~0x00000008u;
-}
-inline void FieldAccessInfo::clear_configs_count() {
-  configs_count_ = GOOGLE_ULONGLONG(0);
-  clear_has_configs_count();
-}
-inline ::google::protobuf::uint64 FieldAccessInfo::configs_count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.FieldAccessInfo.configs_count)
-  return configs_count_;
-}
-inline void FieldAccessInfo::set_configs_count(::google::protobuf::uint64 value) {
-  set_has_configs_count();
-  configs_count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.FieldAccessInfo.configs_count)
-}
-
-// -------------------------------------------------------------------
-
-// MessageAccessInfo
-
-// optional string name = 1;
-inline bool MessageAccessInfo::has_name() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
-}
-inline void MessageAccessInfo::set_has_name() {
-  _has_bits_[0] |= 0x00000001u;
-}
-inline void MessageAccessInfo::clear_has_name() {
-  _has_bits_[0] &= ~0x00000001u;
-}
-inline void MessageAccessInfo::clear_name() {
-  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  clear_has_name();
-}
-inline const ::std::string& MessageAccessInfo::name() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.MessageAccessInfo.name)
-  return name_.GetNoArena();
-}
-inline void MessageAccessInfo::set_name(const ::std::string& value) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.MessageAccessInfo.name)
-}
-#if LANG_CXX11
-inline void MessageAccessInfo::set_name(::std::string&& value) {
-  set_has_name();
-  name_.SetNoArena(
-    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.MessageAccessInfo.name)
-}
-#endif
-inline void MessageAccessInfo::set_name(const char* value) {
-  GOOGLE_DCHECK(value != NULL);
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.MessageAccessInfo.name)
-}
-inline void MessageAccessInfo::set_name(const char* value, size_t size) {
-  set_has_name();
-  name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
-      ::std::string(reinterpret_cast<const char*>(value), size));
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.MessageAccessInfo.name)
-}
-inline ::std::string* MessageAccessInfo::mutable_name() {
-  set_has_name();
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.MessageAccessInfo.name)
-  return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-inline ::std::string* MessageAccessInfo::release_name() {
-  // @@protoc_insertion_point(field_release:google.protobuf.compiler.MessageAccessInfo.name)
-  clear_has_name();
-  return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-}
-inline void MessageAccessInfo::set_allocated_name(::std::string* name) {
-  if (name != NULL) {
-    set_has_name();
-  } else {
-    clear_has_name();
-  }
-  name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name);
-  // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.MessageAccessInfo.name)
-}
-
-// optional uint64 count = 2;
-inline bool MessageAccessInfo::has_count() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
-}
-inline void MessageAccessInfo::set_has_count() {
-  _has_bits_[0] |= 0x00000002u;
-}
-inline void MessageAccessInfo::clear_has_count() {
-  _has_bits_[0] &= ~0x00000002u;
-}
-inline void MessageAccessInfo::clear_count() {
-  count_ = GOOGLE_ULONGLONG(0);
-  clear_has_count();
-}
-inline ::google::protobuf::uint64 MessageAccessInfo::count() const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.MessageAccessInfo.count)
-  return count_;
-}
-inline void MessageAccessInfo::set_count(::google::protobuf::uint64 value) {
-  set_has_count();
-  count_ = value;
-  // @@protoc_insertion_point(field_set:google.protobuf.compiler.MessageAccessInfo.count)
-}
-
-// repeated .google.protobuf.compiler.FieldAccessInfo field = 3;
-inline int MessageAccessInfo::field_size() const {
-  return field_.size();
-}
-inline void MessageAccessInfo::clear_field() {
-  field_.Clear();
-}
-inline const ::google::protobuf::compiler::FieldAccessInfo& MessageAccessInfo::field(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_.Get(index);
-}
-inline ::google::protobuf::compiler::FieldAccessInfo* MessageAccessInfo::mutable_field(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_.Mutable(index);
-}
-inline ::google::protobuf::compiler::FieldAccessInfo* MessageAccessInfo::add_field() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_.Add();
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo >*
-MessageAccessInfo::mutable_field() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.MessageAccessInfo.field)
-  return &field_;
-}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::FieldAccessInfo >&
-MessageAccessInfo::field() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.MessageAccessInfo.field)
-  return field_;
-}
-
-// -------------------------------------------------------------------
-
-// AccessInfo
-
-// repeated .google.protobuf.compiler.MessageAccessInfo message = 1;
-inline int AccessInfo::message_size() const {
-  return message_.size();
-}
-inline void AccessInfo::clear_message() {
-  message_.Clear();
-}
-inline const ::google::protobuf::compiler::MessageAccessInfo& AccessInfo::message(int index) const {
-  // @@protoc_insertion_point(field_get:google.protobuf.compiler.AccessInfo.message)
-  return message_.Get(index);
-}
-inline ::google::protobuf::compiler::MessageAccessInfo* AccessInfo::mutable_message(int index) {
-  // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.AccessInfo.message)
-  return message_.Mutable(index);
-}
-inline ::google::protobuf::compiler::MessageAccessInfo* AccessInfo::add_message() {
-  // @@protoc_insertion_point(field_add:google.protobuf.compiler.AccessInfo.message)
-  return message_.Add();
-}
-inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo >*
-AccessInfo::mutable_message() {
-  // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.AccessInfo.message)
-  return &message_;
-}
-inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::MessageAccessInfo >&
-AccessInfo::message() const {
-  // @@protoc_insertion_point(field_list:google.protobuf.compiler.AccessInfo.message)
-  return message_;
-}
-
-#endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-
-// @@protoc_insertion_point(namespace_scope)
-
-
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-// @@protoc_insertion_point(global_scope)
-
-#endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fprofile_2eproto__INCLUDED
diff --git a/src/google/protobuf/compiler/profile.proto b/src/google/protobuf/compiler/profile.proto
deleted file mode 100644
index 09ebe09..0000000
--- a/src/google/protobuf/compiler/profile.proto
+++ /dev/null
@@ -1,68 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: [email protected] (Seong Beom Kim)
-//
-// protoc (Protocol Compiler) can generate more efficient code
-// if it knows how a workload accesses fields of a message;
-// e.g. some much more frequently than others.
-//
-// Protos defined here describe the access information per message
-// and per field. Note that one can use any methods to collect
-// the access patterns like CPU profiling, instrumented build, etc.
-
-syntax = "proto2";
-
-package google.protobuf.compiler;
-
-// To convey the access pattern of a field, it classifies
-// the type of the accessor methods into getters, setters and
-// configs. Getters and setters read and write the field
-// respectively and other operations like checking if the field
-// exists are considered as configs.
-message FieldAccessInfo {
-  optional string name = 1;
-  optional uint64 getters_count = 2;
-  optional uint64 setters_count = 3;
-  optional uint64 configs_count = 4;
-}
-
-// "count" correlates with how many samples an access info has
-// for a message. High "count" means more confident optimization
-// based on the info.
-message MessageAccessInfo {
-  optional string name = 1;
-  optional uint64 count = 2;
-  repeated FieldAccessInfo field = 3;
-}
-
-message AccessInfo {
-  repeated MessageAccessInfo message = 1;
-}
diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
index 21a7e15..9776983 100644
--- a/src/google/protobuf/compiler/python/python_generator.cc
+++ b/src/google/protobuf/compiler/python/python_generator.cc
@@ -63,11 +63,12 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
 #include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/substitute.h>
 
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -75,12 +76,21 @@
 
 namespace {
 
+// Reimplemented here because we can't bring in
+// absl/strings/string_view_utils.h because it needs C++11.
+bool StrStartsWith(StringPiece sp, StringPiece x) {
+  return sp.size() >= x.size() && sp.substr(0, x.size()) == x;
+}
+bool StrEndsWith(StringPiece sp, StringPiece x) {
+  return sp.size() >= x.size() && sp.substr(sp.size() - x.size()) == x;
+}
+
 // Returns a copy of |filename| with any trailing ".protodevel" or ".proto
 // suffix stripped.
 // TODO(robinson): Unify with copy in compiler/cpp/internal/helpers.cc.
 string StripProto(const string& filename) {
-  const char* suffix = HasSuffixString(filename, ".protodevel")
-      ? ".protodevel" : ".proto";
+  const char* suffix =
+      StrEndsWith(filename, ".protodevel") ? ".protodevel" : ".proto";
   return StripSuffixString(filename, suffix);
 }
 
@@ -350,7 +360,9 @@
   // can only be successfully parsed after we register corresponding
   // extensions. Therefore we parse all options again here to recognize
   // custom options that may be unknown when we define the descriptors.
+  // This does not apply to services because they are not used by extensions.
   FixAllDescriptorOptions();
+  PrintServiceDescriptors();
   if (HasGenericServices(file)) {
     PrintServices();
   }
@@ -562,9 +574,16 @@
   }
 }
 
-void Generator::PrintServices() const {
+void Generator::PrintServiceDescriptors() const {
   for (int i = 0; i < file_->service_count(); ++i) {
     PrintServiceDescriptor(*file_->service(i));
+    AddServiceToFileDescriptor(*file_->service(i));
+    printer_->Print("\n");
+  }
+}
+
+void Generator::PrintServices() const {
+  for (int i = 0; i < file_->service_count(); ++i) {
     PrintServiceClass(*file_->service(i));
     PrintServiceStub(*file_->service(i));
     printer_->Print("\n");
@@ -628,7 +647,10 @@
   }
 
   printer_->Outdent();
-  printer_->Print("])\n\n");
+  printer_->Print("])\n");
+  printer_->Print("_sym_db.RegisterServiceDescriptor($name$)\n", "name",
+                  service_name);
+  printer_->Print("\n");
 }
 
 
@@ -887,6 +909,18 @@
   printer_->Print(m, file_descriptor_template);
 }
 
+void Generator::AddServiceToFileDescriptor(
+    const ServiceDescriptor& descriptor) const {
+  std::map<string, string> m;
+  m["descriptor_name"] = kDescriptorKey;
+  m["service_name"] = descriptor.name();
+  m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor);
+  const char file_descriptor_template[] =
+      "$descriptor_name$.services_by_name['$service_name$'] = "
+      "$service_descriptor_name$\n";
+  printer_->Print(m, file_descriptor_template);
+}
+
 void Generator::AddEnumToFileDescriptor(
     const EnumDescriptor& descriptor) const {
   std::map<string, string> m;
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 594260a..2b5a028 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -112,6 +112,7 @@
   void AddMessageToFileDescriptor(const Descriptor& descriptor) const;
   void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const;
   void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const;
+  void AddServiceToFileDescriptor(const ServiceDescriptor& descriptor) const;
   string FieldReferencingExpression(const Descriptor* containing_type,
                                     const FieldDescriptor& field,
                                     const string& python_dict_name) const;
@@ -126,11 +127,12 @@
   void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const;
 
   void PrintServices() const;
+  void PrintServiceDescriptors() const;
   void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
   void PrintServiceClass(const ServiceDescriptor& descriptor) const;
   void PrintServiceStub(const ServiceDescriptor& descriptor) const;
   void PrintDescriptorKeyAndModuleName(
-      const ServiceDescriptor& descriptor) const ;
+      const ServiceDescriptor& descriptor) const;
 
   void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const;
   string OptionsValue(const string& class_name,
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index 933450f..2e5a89a 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -33,6 +33,7 @@
 #include <google/protobuf/compiler/subprocess.h>
 
 #include <algorithm>
+#include <cstring>
 #include <iostream>
 
 #ifndef _WIN32
@@ -47,11 +48,20 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/stubs/substitute.h>
 
-
 namespace google {
 namespace protobuf {
 namespace compiler {
 
+namespace {
+char* portable_strdup(const char* s) {
+  char* ns = (char*) malloc(strlen(s) + 1);
+  if (ns != NULL) {
+    strcpy(ns, s);
+  }
+  return ns;
+}
+}  // namespace
+
 #ifdef _WIN32
 
 static void CloseHandleOrDie(HANDLE handle) {
@@ -115,7 +125,7 @@
   }
 
   // CreateProcess() mutates its second parameter.  WTF?
-  char* name_copy = strdup(program.c_str());
+  char* name_copy = portable_strdup(program.c_str());
 
   // Create the process.
   PROCESS_INFORMATION process_info;
@@ -299,7 +309,7 @@
   GOOGLE_CHECK(pipe(stdin_pipe) != -1);
   GOOGLE_CHECK(pipe(stdout_pipe) != -1);
 
-  char* argv[2] = { strdup(program.c_str()), NULL };
+  char* argv[2] = { portable_strdup(program.c_str()), NULL };
 
   child_pid_ = fork();
   if (child_pid_ == -1) {
@@ -347,7 +357,6 @@
 
 bool Subprocess::Communicate(const Message& input, Message* output,
                              string* error) {
-
   GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
 
   // The "sighandler_t" typedef is GNU-specific, so define our own.
diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h
index 2513863..9d980b0 100644
--- a/src/google/protobuf/compiler/subprocess.h
+++ b/src/google/protobuf/compiler/subprocess.h
@@ -44,7 +44,6 @@
 
 #include <string>
 
-
 namespace google {
 namespace protobuf {
 
diff --git a/src/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh
index 6fc7136..f859791 100755
--- a/src/google/protobuf/compiler/zip_output_unittest.sh
+++ b/src/google/protobuf/compiler/zip_output_unittest.sh
@@ -41,6 +41,8 @@
 
 TEST_TMPDIR=.
 PROTOC=./protoc
+JAR=jar
+UNZIP=unzip
 
 echo '
   syntax = "proto2";
@@ -57,8 +59,9 @@
     || fail 'protoc failed.'
 
 echo "Testing output to zip..."
-if unzip -h > /dev/null; then
-  unzip -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list || fail 'unzip failed.'
+if $UNZIP -h > /dev/null; then
+  $UNZIP -t $TEST_TMPDIR/testzip.zip > $TEST_TMPDIR/testzip.list \
+    || fail 'unzip failed.'
 
   grep 'testing: testzip\.pb\.cc *OK$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'testzip.pb.cc not found in output zip.'
@@ -73,8 +76,14 @@
 fi
 
 echo "Testing output to jar..."
-if jar c $TEST_TMPDIR/testzip.proto > /dev/null; then
-  jar tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list || fail 'jar failed.'
+if $JAR c $TEST_TMPDIR/testzip.proto > /dev/null; then
+  $JAR tf $TEST_TMPDIR/testzip.jar > $TEST_TMPDIR/testzip.list \
+    || fail 'jar failed.'
+
+  # Check that -interface.jar timestamps are normalized:
+  if [[ "$(TZ=UTC $JAR tvf $TEST_TMPDIR/testzip.jar)" != *'Tue Jan 01 00:00:00 UTC 1980'* ]]; then
+    fail 'Zip did not contain normalized timestamps'
+  fi
 
   grep '^test/jar/Foo\.java$' $TEST_TMPDIR/testzip.list > /dev/null \
     || fail 'Foo.java not found in output jar.'
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 458cced..1799af6 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -70,6 +70,10 @@
 namespace protobuf {
 namespace compiler {
 
+// January 1, 1980 as a DOS date.
+// see https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
+static const uint16 kDosEpoch = 1 << 5 | 1;
+
 static const uint32 kCRC32Table[256] = {
   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
   0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
@@ -154,7 +158,7 @@
   WriteShort(&output, 0);  // flags
   WriteShort(&output, 0);  // compression method: stored
   WriteShort(&output, 0);  // last modified time
-  WriteShort(&output, 0);  // last modified date
+  WriteShort(&output, kDosEpoch);  // last modified date
   output.WriteLittleEndian32(info.crc32);  // crc-32
   output.WriteLittleEndian32(info.size);  // compressed size
   output.WriteLittleEndian32(info.size);  // uncompressed size
@@ -185,7 +189,7 @@
     WriteShort(&output, 0);  // flags
     WriteShort(&output, 0);  // compression method: stored
     WriteShort(&output, 0);  // last modified time
-    WriteShort(&output, 0);  // last modified date
+    WriteShort(&output, kDosEpoch);  // last modified date
     output.WriteLittleEndian32(crc32);  // crc-32
     output.WriteLittleEndian32(size);  // compressed size
     output.WriteLittleEndian32(size);  // uncompressed size
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 6a80792..89b37ee 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -44,25 +44,26 @@
 #include <algorithm>
 #include <limits>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/io/strtod.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/common.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/mutex.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/strtod.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/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor_database.h>
+#include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/text_format.h>
+#include <google/protobuf/unknown_field_set.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/substitute.h>
+
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
 
@@ -1953,6 +1954,10 @@
     DescriptorProto::ExtensionRange* range = proto->add_extension_range();
     range->set_start(extension_range(i)->start);
     range->set_end(extension_range(i)->end);
+    const ExtensionRangeOptions* options = extension_range(i)->options_;
+    if (options != &ExtensionRangeOptions::default_instance()) {
+      range->mutable_options()->CopyFrom(*options);
+    }
   }
   for (int i = 0; i < extension_count(); i++) {
     extension(i)->CopyTo(proto->add_extension());
@@ -3203,6 +3208,8 @@
   void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
   void CrossLinkField(FieldDescriptor* field,
                       const FieldDescriptorProto& proto);
+  void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
+                               const DescriptorProto::ExtensionRange& proto);
   void CrossLinkEnum(EnumDescriptor* enum_type,
                      const EnumDescriptorProto& proto);
   void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
@@ -3382,6 +3389,8 @@
   void DetectMapConflicts(const Descriptor* message,
                           const DescriptorProto& proto);
 
+  void ValidateJSType(FieldDescriptor* field,
+                      const FieldDescriptorProto& proto);
 };
 
 const FileDescriptor* DescriptorPool::BuildFile(
@@ -3509,8 +3518,8 @@
 bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
                                     const string& package_name) {
   return HasPrefixString(file->package(), package_name) &&
-           (file->package().size() == package_name.size() ||
-            file->package()[package_name.size()] == '.');
+         (file->package().size() == package_name.size() ||
+          file->package()[package_name.size()] == '.');
 }
 
 void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
@@ -4776,6 +4785,13 @@
              DescriptorPool::ErrorCollector::NUMBER,
              "Extension range end number must be greater than start number.");
   }
+
+  if (!proto.has_options()) {
+    result->options_ = NULL;  // Will set to default_instance later.
+  } else {
+    AllocateOptionsImpl(parent->full_name(), parent->full_name(),
+                        proto.options(), result);
+  }
 }
 
 void DescriptorBuilder::BuildReservedRange(
@@ -5100,6 +5116,11 @@
     CrossLinkField(&message->extensions_[i], proto.extension(i));
   }
 
+  for (int i = 0; i < message->extension_range_count(); i++) {
+    CrossLinkExtensionRange(&message->extension_ranges_[i],
+                            proto.extension_range(i));
+  }
+
   // Set up field array for each oneof.
 
   // First count the number of fields per oneof.
@@ -5162,6 +5183,14 @@
   }
 }
 
+void DescriptorBuilder::CrossLinkExtensionRange(
+    Descriptor::ExtensionRange* range,
+    const DescriptorProto::ExtensionRange& proto) {
+  if (range->options_ == NULL) {
+    range->options_ = &ExtensionRangeOptions::default_instance();
+  }
+}
+
 void DescriptorBuilder::CrossLinkField(
     FieldDescriptor* field, const FieldDescriptorProto& proto) {
   if (field->options_ == NULL) {
@@ -5734,6 +5763,8 @@
     }
   }
 
+  ValidateJSType(field, proto);
+
 }
 
 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
@@ -5922,6 +5953,40 @@
   }
 }
 
+void DescriptorBuilder::ValidateJSType(FieldDescriptor* field,
+                                       const FieldDescriptorProto& proto) {
+  FieldOptions::JSType jstype = field->options().jstype();
+  // The default is always acceptable.
+  if (jstype == FieldOptions::JS_NORMAL) {
+    return;
+  }
+
+  switch (field->type()) {
+    // Integral 64-bit types may be represented as JavaScript numbers or
+    // strings.
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      if (jstype == FieldOptions::JS_STRING ||
+          jstype == FieldOptions::JS_NUMBER) {
+        return;
+      }
+      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+               "Illegal jstype for int64, uint64, sint64, fixed64 "
+               "or sfixed64 field: " +
+               FieldOptions_JSType_descriptor()->value(jstype)->name());
+      break;
+
+    // No other types permit a jstype option.
+    default:
+      AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
+               "jstype is only allowed on int64, uint64, sint64, fixed64 "
+               "or sfixed64 fields.");
+      break;
+  }
+}
 
 #undef VALIDATE_OPTIONS_FROM_ARRAY
 
@@ -6663,6 +6728,7 @@
     annotation_extensions.insert("google.protobuf.FieldOptions");
     annotation_extensions.insert("google.protobuf.EnumOptions");
     annotation_extensions.insert("google.protobuf.EnumValueOptions");
+    annotation_extensions.insert("google.protobuf.EnumValueOptions");
     annotation_extensions.insert("google.protobuf.ServiceOptions");
     annotation_extensions.insert("google.protobuf.MethodOptions");
     annotation_extensions.insert("google.protobuf.StreamOptions");
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 7aea734..57128e6 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -99,6 +99,7 @@
 class OneofOptions;
 class EnumOptions;
 class EnumValueOptions;
+class ExtensionRangeOptions;
 class ServiceOptions;
 class MethodOptions;
 class FileOptions;
@@ -337,8 +338,12 @@
   // A range of field numbers which are designated for third-party
   // extensions.
   struct ExtensionRange {
+    typedef ExtensionRangeOptions OptionsType;
+
     int start;  // inclusive
     int end;    // exclusive
+
+    const ExtensionRangeOptions* options_;
   };
 
   // The number of extension ranges in this message type.
@@ -440,27 +445,30 @@
   const Descriptor* containing_type_;
   const MessageOptions* options_;
 
+  // These arrays are separated from their sizes to minimize padding on 64-bit.
+  FieldDescriptor* fields_;
+  OneofDescriptor* oneof_decls_;
+  Descriptor* nested_types_;
+  EnumDescriptor* enum_types_;
+  ExtensionRange* extension_ranges_;
+  FieldDescriptor* extensions_;
+  ReservedRange* reserved_ranges_;
+  const string** reserved_names_;
+
+  int field_count_;
+  int oneof_decl_count_;
+  int nested_type_count_;
+  int enum_type_count_;
+  int extension_range_count_;
+  int extension_count_;
+  int reserved_range_count_;
+  int reserved_name_count_;
+
   // True if this is a placeholder for an unknown type.
   bool is_placeholder_;
   // True if this is a placeholder and the type name wasn't fully-qualified.
   bool is_unqualified_placeholder_;
 
-  int field_count_;
-  FieldDescriptor* fields_;
-  int oneof_decl_count_;
-  OneofDescriptor* oneof_decls_;
-  int nested_type_count_;
-  Descriptor* nested_types_;
-  int enum_type_count_;
-  EnumDescriptor* enum_types_;
-  int extension_range_count_;
-  ExtensionRange* extension_ranges_;
-  int extension_count_;
-  FieldDescriptor* extensions_;
-  int reserved_range_count_;
-  ReservedRange* reserved_ranges_;
-  int reserved_name_count_;
-  const string** reserved_names_;
   // IMPORTANT:  If you add a new field, make sure to search for all instances
   // of Allocate<Descriptor>() and AllocateArray<Descriptor>() in descriptor.cc
   // and update them to initialize the field.
@@ -477,6 +485,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor);
 };
 
+
 // Describes a single field of a message.  To get the descriptor for a given
 // field, first get the Descriptor for the message in which it is defined,
 // then call Descriptor::FindFieldByName().  To get a FieldDescriptor for
@@ -736,20 +745,21 @@
   const string* full_name_;
   const string* lowercase_name_;
   const string* camelcase_name_;
-  // Whether the user has specified the json_name field option in the .proto
-  // file.
-  bool has_json_name_;
   // If has_json_name_ is true, it's the value specified by the user.
   // Otherwise, it has the same value as camelcase_name_.
   const string* json_name_;
   const FileDescriptor* file_;
-  int number_;
   GoogleOnceDynamic* type_once_;
   static void TypeOnceInit(const FieldDescriptor* to_init);
   void InternalTypeOnceInit() const;
   mutable Type type_;
   Label label_;
+  bool has_default_value_;
+  // Whether the user has specified the json_name field option in the .proto
+  // file.
+  bool has_json_name_;
   bool is_extension_;
+  int number_;
   int index_in_oneof_;
   const Descriptor* containing_type_;
   const OneofDescriptor* containing_oneof_;
@@ -763,7 +773,6 @@
   // of Allocate<FieldDescriptor>() and AllocateArray<FieldDescriptor>() in
   // descriptor.cc and update them to initialize the field.
 
-  bool has_default_value_;
   union {
     int32  default_value_int32_;
     int64  default_value_int64_;
@@ -794,6 +803,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor);
 };
 
+
 // Describes a oneof defined in a message type.
 class LIBPROTOBUF_EXPORT OneofDescriptor {
  public:
@@ -803,6 +813,8 @@
   // Index of this oneof within the message's oneof array.
   int index() const;
 
+  // The .proto file in which this oneof was defined.  Never NULL.
+  const FileDescriptor* file() const;
   // The Descriptor for the message containing this oneof.
   const Descriptor* containing_type() const;
 
@@ -998,6 +1010,8 @@
   // with C++ scoping rules for enums.
   const string& full_name() const;
 
+  // The .proto file in which this value was defined.  Never NULL.
+  const FileDescriptor* file() const;
   // The type of this value.  Never NULL.
   const EnumDescriptor* type() const;
 
@@ -1122,8 +1136,8 @@
   const string* full_name_;
   const FileDescriptor* file_;
   const ServiceOptions* options_;
-  int method_count_;
   MethodDescriptor* methods_;
+  int method_count_;
   // IMPORTANT:  If you add a new field, make sure to search for all instances
   // of Allocate<ServiceDescriptor>() and AllocateArray<ServiceDescriptor>() in
   // descriptor.cc and update them to initialize the field.
@@ -1136,6 +1150,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceDescriptor);
 };
 
+
 // Describes an individual service method.  To obtain a MethodDescriptor given
 // a service, first get its ServiceDescriptor, then call
 // ServiceDescriptor::FindMethodByName().  Use DescriptorPool to construct your
@@ -1149,6 +1164,8 @@
   // Index within the service's Descriptor.
   int index() const;
 
+  // The .proto file in which this method was defined.  Never NULL.
+  const FileDescriptor* file() const;
   // Gets the service to which this method belongs.  Never NULL.
   const ServiceDescriptor* service() const;
 
@@ -1360,36 +1377,39 @@
   const string* name_;
   const string* package_;
   const DescriptorPool* pool_;
-  int dependency_count_;
-  mutable const FileDescriptor** dependencies_;
-  const string** dependencies_names_;
   GoogleOnceDynamic* dependencies_once_;
   static void DependenciesOnceInit(const FileDescriptor* to_init);
   void InternalDependenciesOnceInit() const;
+
+  // These are arranged to minimze padding on 64-bit.
+  int dependency_count_;
   int public_dependency_count_;
-  int* public_dependencies_;
   int weak_dependency_count_;
-  int* weak_dependencies_;
   int message_type_count_;
-  Descriptor* message_types_;
   int enum_type_count_;
-  EnumDescriptor* enum_types_;
   int service_count_;
-  ServiceDescriptor* services_;
   int extension_count_;
   Syntax syntax_;
   bool is_placeholder_;
-  FieldDescriptor* extensions_;
-  const FileOptions* options_;
-
-  const FileDescriptorTables* tables_;
-  const SourceCodeInfo* source_code_info_;
 
   // Indicates the FileDescriptor is completed building. Used to verify
   // that type accessor functions that can possibly build a dependent file
   // aren't called during the process of building the file.
   bool finished_building_;
 
+  mutable const FileDescriptor** dependencies_;
+  const string** dependencies_names_;
+  int* public_dependencies_;
+  int* weak_dependencies_;
+  Descriptor* message_types_;
+  EnumDescriptor* enum_types_;
+  ServiceDescriptor* services_;
+  FieldDescriptor* extensions_;
+  const FileOptions* options_;
+
+  const FileDescriptorTables* tables_;
+  const SourceCodeInfo* source_code_info_;
+
   // IMPORTANT:  If you add a new field, make sure to search for all instances
   // of Allocate<FileDescriptor>() and AllocateArray<FileDescriptor>() in
   // descriptor.cc and update them to initialize the field.
@@ -1408,6 +1428,7 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
 };
 
+
 // ===================================================================
 
 // Used to construct descriptors.
@@ -1748,12 +1769,13 @@
   bool lazily_build_dependencies_;
   bool allow_unknown_;
   bool enforce_weak_;
-  std::set<string> unused_import_track_files_;
   bool disallow_enforce_utf8_;
+  std::set<string> unused_import_track_files_;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool);
 };
 
+
 // inline methods ====================================================
 
 // These macros makes this repetitive code more readable.
@@ -1949,6 +1971,10 @@
   }
 }
 
+inline const FileDescriptor* OneofDescriptor::file() const {
+  return containing_type()->file();
+}
+
 inline int OneofDescriptor::index() const {
   return static_cast<int>(this - containing_type_->oneof_decls_);
 }
@@ -1961,6 +1987,10 @@
   }
 }
 
+inline const FileDescriptor* EnumValueDescriptor::file() const {
+  return type()->file();
+}
+
 inline int EnumValueDescriptor::index() const {
   return static_cast<int>(this - type_->values_);
 }
@@ -1969,6 +1999,10 @@
   return static_cast<int>(this - file_->services_);
 }
 
+inline const FileDescriptor* MethodDescriptor::file() const {
+  return service()->file();
+}
+
 inline int MethodDescriptor::index() const {
   return static_cast<int>(this - service_->methods_);
 }
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 56c395e..69c0ab0 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -19,55 +19,135 @@
 
 namespace google {
 namespace protobuf {
-class FileDescriptorSetDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FileDescriptorSet> {
+class FileDescriptorSetDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FileDescriptorSet>
+     _instance;
 } _FileDescriptorSet_default_instance_;
-class FileDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FileDescriptorProto> {
+class FileDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FileDescriptorProto>
+     _instance;
 } _FileDescriptorProto_default_instance_;
-class DescriptorProto_ExtensionRangeDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<DescriptorProto_ExtensionRange> {
+class DescriptorProto_ExtensionRangeDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<DescriptorProto_ExtensionRange>
+     _instance;
 } _DescriptorProto_ExtensionRange_default_instance_;
-class DescriptorProto_ReservedRangeDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<DescriptorProto_ReservedRange> {
+class DescriptorProto_ReservedRangeDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<DescriptorProto_ReservedRange>
+     _instance;
 } _DescriptorProto_ReservedRange_default_instance_;
-class DescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<DescriptorProto> {
+class DescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<DescriptorProto>
+     _instance;
 } _DescriptorProto_default_instance_;
-class FieldDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FieldDescriptorProto> {
+class ExtensionRangeOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<ExtensionRangeOptions>
+     _instance;
+} _ExtensionRangeOptions_default_instance_;
+class FieldDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FieldDescriptorProto>
+     _instance;
 } _FieldDescriptorProto_default_instance_;
-class OneofDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<OneofDescriptorProto> {
+class OneofDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<OneofDescriptorProto>
+     _instance;
 } _OneofDescriptorProto_default_instance_;
-class EnumDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<EnumDescriptorProto> {
+class EnumDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<EnumDescriptorProto>
+     _instance;
 } _EnumDescriptorProto_default_instance_;
-class EnumValueDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<EnumValueDescriptorProto> {
+class EnumValueDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<EnumValueDescriptorProto>
+     _instance;
 } _EnumValueDescriptorProto_default_instance_;
-class ServiceDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<ServiceDescriptorProto> {
+class ServiceDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<ServiceDescriptorProto>
+     _instance;
 } _ServiceDescriptorProto_default_instance_;
-class MethodDescriptorProtoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<MethodDescriptorProto> {
+class MethodDescriptorProtoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<MethodDescriptorProto>
+     _instance;
 } _MethodDescriptorProto_default_instance_;
-class FileOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FileOptions> {
+class FileOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FileOptions>
+     _instance;
 } _FileOptions_default_instance_;
-class MessageOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<MessageOptions> {
+class MessageOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<MessageOptions>
+     _instance;
 } _MessageOptions_default_instance_;
-class FieldOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FieldOptions> {
+class FieldOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FieldOptions>
+     _instance;
 } _FieldOptions_default_instance_;
-class OneofOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<OneofOptions> {
+class OneofOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<OneofOptions>
+     _instance;
 } _OneofOptions_default_instance_;
-class EnumOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<EnumOptions> {
+class EnumOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<EnumOptions>
+     _instance;
 } _EnumOptions_default_instance_;
-class EnumValueOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<EnumValueOptions> {
+class EnumValueOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<EnumValueOptions>
+     _instance;
 } _EnumValueOptions_default_instance_;
-class ServiceOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<ServiceOptions> {
+class ServiceOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<ServiceOptions>
+     _instance;
 } _ServiceOptions_default_instance_;
-class MethodOptionsDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<MethodOptions> {
+class MethodOptionsDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<MethodOptions>
+     _instance;
 } _MethodOptions_default_instance_;
-class UninterpretedOption_NamePartDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<UninterpretedOption_NamePart> {
+class UninterpretedOption_NamePartDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<UninterpretedOption_NamePart>
+     _instance;
 } _UninterpretedOption_NamePart_default_instance_;
-class UninterpretedOptionDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<UninterpretedOption> {
+class UninterpretedOptionDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<UninterpretedOption>
+     _instance;
 } _UninterpretedOption_default_instance_;
-class SourceCodeInfo_LocationDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<SourceCodeInfo_Location> {
+class SourceCodeInfo_LocationDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<SourceCodeInfo_Location>
+     _instance;
 } _SourceCodeInfo_Location_default_instance_;
-class SourceCodeInfoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<SourceCodeInfo> {
+class SourceCodeInfoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<SourceCodeInfo>
+     _instance;
 } _SourceCodeInfo_default_instance_;
-class GeneratedCodeInfo_AnnotationDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<GeneratedCodeInfo_Annotation> {
+class GeneratedCodeInfo_AnnotationDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<GeneratedCodeInfo_Annotation>
+     _instance;
 } _GeneratedCodeInfo_Annotation_default_instance_;
-class GeneratedCodeInfoDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<GeneratedCodeInfo> {
+class GeneratedCodeInfoDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<GeneratedCodeInfo>
+     _instance;
 } _GeneratedCodeInfo_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fdescriptor_2eproto {
@@ -75,50 +155,51 @@
 
 namespace {
 
-::google::protobuf::Metadata file_level_metadata[25];
+::google::protobuf::Metadata file_level_metadata[26];
 const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors[6];
 
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _has_bits_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorSet, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -162,8 +243,10 @@
   ~0u,  // no _weak_field_map_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, start_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, end_),
-  0,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, options_),
   1,
+  2,
+  0,
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _has_bits_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -198,6 +281,13 @@
   1,
   ~0u,
   ~0u,
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, _has_bits_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, _internal_metadata_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, _extensions_),
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ExtensionRangeOptions, uninterpreted_option_),
+  ~0u,
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _has_bits_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -297,29 +387,33 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, php_generic_services_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, swift_prefix_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, php_class_prefix_),
+  GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, php_namespace_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_),
   0,
   1,
-  7,
   8,
   9,
-  15,
-  2,
   10,
+  17,
+  2,
   11,
   12,
   13,
   14,
+  15,
+  16,
   3,
   4,
   5,
   6,
+  7,
   ~0u,
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _has_bits_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_),
@@ -473,33 +567,33 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(GeneratedCodeInfo, annotation_),
   ~0u,
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, 6, sizeof(FileDescriptorSet)},
   { 7, 24, sizeof(FileDescriptorProto)},
-  { 36, 43, sizeof(DescriptorProto_ExtensionRange)},
-  { 45, 52, sizeof(DescriptorProto_ReservedRange)},
-  { 54, 69, sizeof(DescriptorProto)},
-  { 79, 94, sizeof(FieldDescriptorProto)},
-  { 104, 111, sizeof(OneofDescriptorProto)},
-  { 113, 121, sizeof(EnumDescriptorProto)},
-  { 124, 132, sizeof(EnumValueDescriptorProto)},
-  { 135, 143, sizeof(ServiceDescriptorProto)},
-  { 146, 157, sizeof(MethodDescriptorProto)},
-  { 163, 185, sizeof(FileOptions)},
-  { 202, 212, sizeof(MessageOptions)},
-  { 217, 229, sizeof(FieldOptions)},
-  { 236, 242, sizeof(OneofOptions)},
-  { 243, 251, sizeof(EnumOptions)},
-  { 254, 261, sizeof(EnumValueOptions)},
-  { 263, 270, sizeof(ServiceOptions)},
-  { 272, 280, sizeof(MethodOptions)},
-  { 283, 290, sizeof(UninterpretedOption_NamePart)},
-  { 292, 304, sizeof(UninterpretedOption)},
-  { 311, 321, sizeof(SourceCodeInfo_Location)},
-  { 326, 332, sizeof(SourceCodeInfo)},
-  { 333, 342, sizeof(GeneratedCodeInfo_Annotation)},
-  { 346, 352, sizeof(GeneratedCodeInfo)},
+  { 36, 44, sizeof(DescriptorProto_ExtensionRange)},
+  { 47, 54, sizeof(DescriptorProto_ReservedRange)},
+  { 56, 71, sizeof(DescriptorProto)},
+  { 81, 87, sizeof(ExtensionRangeOptions)},
+  { 88, 103, sizeof(FieldDescriptorProto)},
+  { 113, 120, sizeof(OneofDescriptorProto)},
+  { 122, 130, sizeof(EnumDescriptorProto)},
+  { 133, 141, sizeof(EnumValueDescriptorProto)},
+  { 144, 152, sizeof(ServiceDescriptorProto)},
+  { 155, 166, sizeof(MethodDescriptorProto)},
+  { 172, 196, sizeof(FileOptions)},
+  { 215, 225, sizeof(MessageOptions)},
+  { 230, 242, sizeof(FieldOptions)},
+  { 249, 255, sizeof(OneofOptions)},
+  { 256, 264, sizeof(EnumOptions)},
+  { 267, 274, sizeof(EnumValueOptions)},
+  { 276, 283, sizeof(ServiceOptions)},
+  { 285, 293, sizeof(MethodOptions)},
+  { 296, 303, sizeof(UninterpretedOption_NamePart)},
+  { 305, 317, sizeof(UninterpretedOption)},
+  { 324, 334, sizeof(SourceCodeInfo_Location)},
+  { 339, 345, sizeof(SourceCodeInfo)},
+  { 346, 355, sizeof(GeneratedCodeInfo_Annotation)},
+  { 359, 365, sizeof(GeneratedCodeInfo)},
 };
 
 static ::google::protobuf::Message const * const file_default_instances[] = {
@@ -508,6 +602,7 @@
   reinterpret_cast<const ::google::protobuf::Message*>(&_DescriptorProto_ExtensionRange_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&_DescriptorProto_ReservedRange_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&_DescriptorProto_default_instance_),
+  reinterpret_cast<const ::google::protobuf::Message*>(&_ExtensionRangeOptions_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&_FieldDescriptorProto_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&_OneofDescriptorProto_default_instance_),
   reinterpret_cast<const ::google::protobuf::Message*>(&_EnumDescriptorProto_default_instance_),
@@ -548,110 +643,85 @@
 void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;
 void protobuf_RegisterTypes(const ::std::string&) {
   protobuf_AssignDescriptorsOnce();
-  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 25);
+  ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 26);
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _FileDescriptorSet_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-  _FileDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _DescriptorProto_ExtensionRange_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-  _DescriptorProto_ReservedRange_default_instance_.Shutdown();
-  delete file_level_metadata[3].reflection;
-  _DescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[4].reflection;
-  _FieldDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[5].reflection;
-  _OneofDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[6].reflection;
-  _EnumDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[7].reflection;
-  _EnumValueDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[8].reflection;
-  _ServiceDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[9].reflection;
-  _MethodDescriptorProto_default_instance_.Shutdown();
-  delete file_level_metadata[10].reflection;
-  _FileOptions_default_instance_.Shutdown();
-  delete file_level_metadata[11].reflection;
-  _MessageOptions_default_instance_.Shutdown();
-  delete file_level_metadata[12].reflection;
-  _FieldOptions_default_instance_.Shutdown();
-  delete file_level_metadata[13].reflection;
-  _OneofOptions_default_instance_.Shutdown();
-  delete file_level_metadata[14].reflection;
-  _EnumOptions_default_instance_.Shutdown();
-  delete file_level_metadata[15].reflection;
-  _EnumValueOptions_default_instance_.Shutdown();
-  delete file_level_metadata[16].reflection;
-  _ServiceOptions_default_instance_.Shutdown();
-  delete file_level_metadata[17].reflection;
-  _MethodOptions_default_instance_.Shutdown();
-  delete file_level_metadata[18].reflection;
-  _UninterpretedOption_NamePart_default_instance_.Shutdown();
-  delete file_level_metadata[19].reflection;
-  _UninterpretedOption_default_instance_.Shutdown();
-  delete file_level_metadata[20].reflection;
-  _SourceCodeInfo_Location_default_instance_.Shutdown();
-  delete file_level_metadata[21].reflection;
-  _SourceCodeInfo_default_instance_.Shutdown();
-  delete file_level_metadata[22].reflection;
-  _GeneratedCodeInfo_Annotation_default_instance_.Shutdown();
-  delete file_level_metadata[23].reflection;
-  _GeneratedCodeInfo_default_instance_.Shutdown();
-  delete file_level_metadata[24].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _FileDescriptorSet_default_instance_.DefaultConstruct();
-  _FileDescriptorProto_default_instance_.DefaultConstruct();
-  _DescriptorProto_ExtensionRange_default_instance_.DefaultConstruct();
-  _DescriptorProto_ReservedRange_default_instance_.DefaultConstruct();
-  _DescriptorProto_default_instance_.DefaultConstruct();
-  _FieldDescriptorProto_default_instance_.DefaultConstruct();
-  _OneofDescriptorProto_default_instance_.DefaultConstruct();
-  _EnumDescriptorProto_default_instance_.DefaultConstruct();
-  _EnumValueDescriptorProto_default_instance_.DefaultConstruct();
-  _ServiceDescriptorProto_default_instance_.DefaultConstruct();
-  _MethodDescriptorProto_default_instance_.DefaultConstruct();
-  _FileOptions_default_instance_.DefaultConstruct();
-  _MessageOptions_default_instance_.DefaultConstruct();
-  _FieldOptions_default_instance_.DefaultConstruct();
-  _OneofOptions_default_instance_.DefaultConstruct();
-  _EnumOptions_default_instance_.DefaultConstruct();
-  _EnumValueOptions_default_instance_.DefaultConstruct();
-  _ServiceOptions_default_instance_.DefaultConstruct();
-  _MethodOptions_default_instance_.DefaultConstruct();
-  _UninterpretedOption_NamePart_default_instance_.DefaultConstruct();
-  _UninterpretedOption_default_instance_.DefaultConstruct();
-  _SourceCodeInfo_Location_default_instance_.DefaultConstruct();
-  _SourceCodeInfo_default_instance_.DefaultConstruct();
-  _GeneratedCodeInfo_Annotation_default_instance_.DefaultConstruct();
-  _GeneratedCodeInfo_default_instance_.DefaultConstruct();
-  _FileDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::FileOptions*>(
+  _FileDescriptorSet_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FileDescriptorSet_default_instance_);_FileDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FileDescriptorProto_default_instance_);_DescriptorProto_ExtensionRange_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_DescriptorProto_ExtensionRange_default_instance_);_DescriptorProto_ReservedRange_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_DescriptorProto_ReservedRange_default_instance_);_DescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_DescriptorProto_default_instance_);_ExtensionRangeOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_ExtensionRangeOptions_default_instance_);_FieldDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FieldDescriptorProto_default_instance_);_OneofDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_OneofDescriptorProto_default_instance_);_EnumDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_EnumDescriptorProto_default_instance_);_EnumValueDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_EnumValueDescriptorProto_default_instance_);_ServiceDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_ServiceDescriptorProto_default_instance_);_MethodDescriptorProto_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_MethodDescriptorProto_default_instance_);_FileOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FileOptions_default_instance_);_MessageOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_MessageOptions_default_instance_);_FieldOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FieldOptions_default_instance_);_OneofOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_OneofOptions_default_instance_);_EnumOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_EnumOptions_default_instance_);_EnumValueOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_EnumValueOptions_default_instance_);_ServiceOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_ServiceOptions_default_instance_);_MethodOptions_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_MethodOptions_default_instance_);_UninterpretedOption_NamePart_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_UninterpretedOption_NamePart_default_instance_);_UninterpretedOption_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_UninterpretedOption_default_instance_);_SourceCodeInfo_Location_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_SourceCodeInfo_Location_default_instance_);_SourceCodeInfo_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_SourceCodeInfo_default_instance_);_GeneratedCodeInfo_Annotation_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_GeneratedCodeInfo_Annotation_default_instance_);_GeneratedCodeInfo_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_GeneratedCodeInfo_default_instance_);_FileDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::FileOptions*>(
       ::google::protobuf::FileOptions::internal_default_instance());
-  _FileDescriptorProto_default_instance_.get_mutable()->source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(
+  _FileDescriptorProto_default_instance_._instance.get_mutable()->source_code_info_ = const_cast< ::google::protobuf::SourceCodeInfo*>(
       ::google::protobuf::SourceCodeInfo::internal_default_instance());
-  _DescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::MessageOptions*>(
+  _DescriptorProto_ExtensionRange_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::ExtensionRangeOptions*>(
+      ::google::protobuf::ExtensionRangeOptions::internal_default_instance());
+  _DescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::MessageOptions*>(
       ::google::protobuf::MessageOptions::internal_default_instance());
-  _FieldDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::FieldOptions*>(
+  _FieldDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::FieldOptions*>(
       ::google::protobuf::FieldOptions::internal_default_instance());
-  _OneofDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::OneofOptions*>(
+  _OneofDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::OneofOptions*>(
       ::google::protobuf::OneofOptions::internal_default_instance());
-  _EnumDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::EnumOptions*>(
+  _EnumDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::EnumOptions*>(
       ::google::protobuf::EnumOptions::internal_default_instance());
-  _EnumValueDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::EnumValueOptions*>(
+  _EnumValueDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::EnumValueOptions*>(
       ::google::protobuf::EnumValueOptions::internal_default_instance());
-  _ServiceDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::ServiceOptions*>(
+  _ServiceDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::ServiceOptions*>(
       ::google::protobuf::ServiceOptions::internal_default_instance());
-  _MethodDescriptorProto_default_instance_.get_mutable()->options_ = const_cast< ::google::protobuf::MethodOptions*>(
+  _MethodDescriptorProto_default_instance_._instance.get_mutable()->options_ = const_cast< ::google::protobuf::MethodOptions*>(
       ::google::protobuf::MethodOptions::internal_default_instance());
 }
 
@@ -659,9 +729,10 @@
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n google/protobuf/descriptor.proto\022\017goog"
       "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
       "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
@@ -677,7 +748,7 @@
       "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
       "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
       "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001"
-      "(\t\"\360\004\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
+      "(\t\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
       "field\030\002 \003(\0132%.google.protobuf.FieldDescr"
       "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p"
       "rotobuf.FieldDescriptorProto\0225\n\013nested_t"
@@ -690,131 +761,137 @@
       "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti"
       "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro"
       "tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
-      "eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005"
-      "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang"
-      "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\274\005\n\024FieldD"
-      "escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003"
-      " \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi"
-      "eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*"
-      ".google.protobuf.FieldDescriptorProto.Ty"
-      "pe\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022"
-      "\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030\t "
-      "\001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001(\0132"
-      "\035.google.protobuf.FieldOptions\"\266\002\n\004Type\022"
-      "\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE"
-      "_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020"
-      "\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n"
-      "\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GR"
-      "OUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022"
-      "\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_"
-      "SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SI"
-      "NT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LABE"
-      "L_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABE"
-      "L_REPEATED\020\003\"T\n\024OneofDescriptorProto\022\014\n\004"
-      "name\030\001 \001(\t\022.\n\007options\030\002 \001(\0132\035.google.pro"
-      "tobuf.OneofOptions\"\214\001\n\023EnumDescriptorPro"
-      "to\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google"
-      ".protobuf.EnumValueDescriptorProto\022-\n\007op"
-      "tions\030\003 \001(\0132\034.google.protobuf.EnumOption"
-      "s\"l\n\030EnumValueDescriptorProto\022\014\n\004name\030\001 "
-      "\001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.g"
-      "oogle.protobuf.EnumValueOptions\"\220\001\n\026Serv"
-      "iceDescriptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006meth"
-      "od\030\002 \003(\0132&.google.protobuf.MethodDescrip"
-      "torProto\0220\n\007options\030\003 \001(\0132\037.google.proto"
-      "buf.ServiceOptions\"\301\001\n\025MethodDescriptorP"
-      "roto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023"
-      "\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.g"
-      "oogle.protobuf.MethodOptions\022\037\n\020client_s"
-      "treaming\030\005 \001(\010:\005false\022\037\n\020server_streamin"
-      "g\030\006 \001(\010:\005false\"\264\005\n\013FileOptions\022\024\n\014java_p"
-      "ackage\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001"
-      "(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false\022)"
-      "\n\035java_generate_equals_and_hash\030\024 \001(\010B\002\030"
-      "\001\022%\n\026java_string_check_utf8\030\033 \001(\010:\005false"
-      "\022F\n\014optimize_for\030\t \001(\0162).google.protobuf"
-      ".FileOptions.OptimizeMode:\005SPEED\022\022\n\ngo_p"
-      "ackage\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001("
-      "\010:\005false\022$\n\025java_generic_services\030\021 \001(\010:"
-      "\005false\022\"\n\023py_generic_services\030\022 \001(\010:\005fal"
-      "se\022\031\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enab"
-      "le_arenas\030\037 \001(\010:\005false\022\031\n\021objc_class_pre"
-      "fix\030$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022\024\n\014s"
-      "wift_prefix\030\' \001(\t\022\030\n\020php_class_prefix\030( "
-      "\001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
-      "gle.protobuf.UninterpretedOption\":\n\014Opti"
-      "mizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LI"
-      "TE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002J\004\010&\020\'\"\362\001\n\016Messag"
-      "eOptions\022&\n\027message_set_wire_format\030\001 \001("
-      "\010:\005false\022.\n\037no_standard_descriptor_acces"
-      "sor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005fa"
-      "lse\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpreted_"
-      "option\030\347\007 \003(\0132$.google.protobuf.Uninterp"
-      "retedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\010\020\tJ\004\010\t\020\n\"\236\003\n\014F"
-      "ieldOptions\022:\n\005ctype\030\001 \001(\0162#.google.prot"
-      "obuf.FieldOptions.CType:\006STRING\022\016\n\006packe"
-      "d\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.google.protobu"
-      "f.FieldOptions.JSType:\tJS_NORMAL\022\023\n\004lazy"
-      "\030\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false"
-      "\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_o"
-      "ption\030\347\007 \003(\0132$.google.protobuf.Uninterpr"
-      "etedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020"
-      "\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORM"
-      "AL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020"
-      "\200\200\200\200\002J\004\010\004\020\005\"^\n\014OneofOptions\022C\n\024uninterpr"
-      "eted_option\030\347\007 \003(\0132$.google.protobuf.Uni"
-      "nterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOpti"
-      "ons\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003"
+      "eserved_name\030\n \003(\t\032e\n\016ExtensionRange\022\r\n\005"
+      "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003 \001("
+      "\0132&.google.protobuf.ExtensionRangeOption"
+      "s\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end"
+      "\030\002 \001(\005\"g\n\025ExtensionRangeOptions\022C\n\024unint"
+      "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
+      ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\274\005\n\024Fiel"
+      "dDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number"
+      "\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf."
+      "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016"
+      "2*.google.protobuf.FieldDescriptorProto."
+      "Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001("
+      "\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030"
+      "\t \001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001("
+      "\0132\035.google.protobuf.FieldOptions\"\266\002\n\004Typ"
+      "e\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTY"
+      "PE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT3"
+      "2\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022"
+      "\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_"
+      "GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020"
+      "\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYP"
+      "E_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_"
+      "SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LA"
+      "BEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LA"
+      "BEL_REPEATED\020\003\"T\n\024OneofDescriptorProto\022\014"
+      "\n\004name\030\001 \001(\t\022.\n\007options\030\002 \001(\0132\035.google.p"
+      "rotobuf.OneofOptions\"\214\001\n\023EnumDescriptorP"
+      "roto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).goog"
+      "le.protobuf.EnumValueDescriptorProto\022-\n\007"
+      "options\030\003 \001(\0132\034.google.protobuf.EnumOpti"
+      "ons\"l\n\030EnumValueDescriptorProto\022\014\n\004name\030"
+      "\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!"
+      ".google.protobuf.EnumValueOptions\"\220\001\n\026Se"
+      "rviceDescriptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006me"
+      "thod\030\002 \003(\0132&.google.protobuf.MethodDescr"
+      "iptorProto\0220\n\007options\030\003 \001(\0132\037.google.pro"
+      "tobuf.ServiceOptions\"\301\001\n\025MethodDescripto"
+      "rProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t"
+      "\022\023\n\013output_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036"
+      ".google.protobuf.MethodOptions\022\037\n\020client"
+      "_streaming\030\005 \001(\010:\005false\022\037\n\020server_stream"
+      "ing\030\006 \001(\010:\005false\"\360\005\n\013FileOptions\022\024\n\014java"
+      "_package\030\001 \001(\t\022\034\n\024java_outer_classname\030\010"
+      " \001(\t\022\"\n\023java_multiple_files\030\n \001(\010:\005false"
+      "\022)\n\035java_generate_equals_and_hash\030\024 \001(\010B"
+      "\002\030\001\022%\n\026java_string_check_utf8\030\033 \001(\010:\005fal"
+      "se\022F\n\014optimize_for\030\t \001(\0162).google.protob"
+      "uf.FileOptions.OptimizeMode:\005SPEED\022\022\n\ngo"
+      "_package\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 "
+      "\001(\010:\005false\022$\n\025java_generic_services\030\021 \001("
+      "\010:\005false\022\"\n\023py_generic_services\030\022 \001(\010:\005f"
+      "alse\022#\n\024php_generic_services\030\023 \001(\010:\005fals"
+      "e\022\031\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enabl"
+      "e_arenas\030\037 \001(\010:\005false\022\031\n\021objc_class_pref"
+      "ix\030$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022\024\n\014sw"
+      "ift_prefix\030\' \001(\t\022\030\n\020php_class_prefix\030( \001"
+      "(\t\022\025\n\rphp_namespace\030) \001(\t\022C\n\024uninterpret"
+      "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint"
+      "erpretedOption\":\n\014OptimizeMode\022\t\n\005SPEED\020"
+      "\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020"
+      "\200\200\200\200\002J\004\010&\020\'\"\362\001\n\016MessageOptions\022&\n\027messag"
+      "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta"
+      "ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031"
+      "\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007"
+      " \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go"
+      "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200"
+      "\200\200\200\002J\004\010\010\020\tJ\004\010\t\020\n\"\236\003\n\014FieldOptions\022:\n\005cty"
+      "pe\030\001 \001(\0162#.google.protobuf.FieldOptions."
+      "CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030"
+      "\006 \001(\0162$.google.protobuf.FieldOptions.JST"
+      "ype:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\nd"
+      "eprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fa"
+      "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+      "gle.protobuf.UninterpretedOption\"/\n\005CTyp"
+      "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020"
+      "\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020"
+      "\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014One"
+      "ofOptions\022C\n\024uninterpreted_option\030\347\007 \003(\013"
+      "2$.google.protobuf.UninterpretedOption*\t"
+      "\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptions\022\023\n\013allow_alias"
+      "\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uni"
+      "nterpreted_option\030\347\007 \003(\0132$.google.protob"
+      "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\""
+      "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:"
+      "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
+      "google.protobuf.UninterpretedOption*\t\010\350\007"
+      "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!"
       " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
       "(\0132$.google.protobuf.UninterpretedOption"
-      "*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"}\n\020EnumValueOptions\022\031\n"
-      "\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterprete"
-      "d_option\030\347\007 \003(\0132$.google.protobuf.Uninte"
-      "rpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptio"
-      "ns\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninter"
-      "preted_option\030\347\007 \003(\0132$.google.protobuf.U"
-      "ninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethod"
-      "Options\022\031\n\ndeprecated\030! \001(\010:\005false\022_\n\021id"
-      "empotency_level\030\" \001(\0162/.google.protobuf."
-      "MethodOptions.IdempotencyLevel:\023IDEMPOTE"
-      "NCY_UNKNOWN\022C\n\024uninterpreted_option\030\347\007 \003"
-      "(\0132$.google.protobuf.UninterpretedOption"
-      "\"P\n\020IdempotencyLevel\022\027\n\023IDEMPOTENCY_UNKN"
-      "OWN\020\000\022\023\n\017NO_SIDE_EFFECTS\020\001\022\016\n\nIDEMPOTENT"
-      "\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022;\n"
-      "\004name\030\002 \003(\0132-.google.protobuf.Uninterpre"
-      "tedOption.NamePart\022\030\n\020identifier_value\030\003"
-      " \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022nega"
-      "tive_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001"
-      "(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_va"
-      "lue\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(\t"
-      "\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeInf"
-      "o\022:\n\010location\030\001 \003(\0132(.google.protobuf.So"
-      "urceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004pa"
-      "th\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leadin"
-      "g_comments\030\003 \001(\t\022\031\n\021trailing_comments\030\004 "
-      "\001(\t\022!\n\031leading_detached_comments\030\006 \003(\t\"\247"
-      "\001\n\021GeneratedCodeInfo\022A\n\nannotation\030\001 \003(\013"
-      "2-.google.protobuf.GeneratedCodeInfo.Ann"
-      "otation\032O\n\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022"
-      "\023\n\013source_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003e"
-      "nd\030\004 \001(\005B\214\001\n\023com.google.protobufB\020Descri"
-      "ptorProtosH\001Z>github.com/golang/protobuf"
-      "/protoc-gen-go/descriptor;descriptor\242\002\003G"
-      "PB\252\002\032Google.Protobuf.Reflection"
+      "*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n\ndepreca"
+      "ted\030! \001(\010:\005false\022_\n\021idempotency_level\030\" "
+      "\001(\0162/.google.protobuf.MethodOptions.Idem"
+      "potencyLevel:\023IDEMPOTENCY_UNKNOWN\022C\n\024uni"
+      "nterpreted_option\030\347\007 \003(\0132$.google.protob"
+      "uf.UninterpretedOption\"P\n\020IdempotencyLev"
+      "el\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_E"
+      "FFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023"
+      "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog"
+      "le.protobuf.UninterpretedOption.NamePart"
+      "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i"
+      "nt_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001"
+      "(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_value"
+      "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP"
+      "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002"
+      " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003("
+      "\0132(.google.protobuf.SourceCodeInfo.Locat"
+      "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp"
+      "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031"
+      "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det"
+      "ached_comments\030\006 \003(\t\"\247\001\n\021GeneratedCodeIn"
+      "fo\022A\n\nannotation\030\001 \003(\0132-.google.protobuf"
+      ".GeneratedCodeInfo.Annotation\032O\n\nAnnotat"
+      "ion\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001"
+      "(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B\214\001\n\023com.g"
+      "oogle.protobufB\020DescriptorProtosH\001Z>gith"
+      "ub.com/golang/protobuf/protoc-gen-go/des"
+      "criptor;descriptor\242\002\003GPB\252\002\032Google.Protob"
+      "uf.Reflection"
   };
   ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
-      descriptor, 5591);
+      descriptor, 5813);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -1053,6 +1130,10 @@
 
 void FileDescriptorSet::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   file_.Clear();
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -1071,7 +1152,7 @@
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_file()));
         } else {
@@ -1082,13 +1163,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1109,34 +1188,37 @@
   (void) cached_has_bits;
 
   // repeated .google.protobuf.FileDescriptorProto file = 1;
-  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      1, this->file(i), output);
+      1, this->file(static_cast<int>(i)), output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorSet)
 }
 
 ::google::protobuf::uint8* FileDescriptorSet::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.FileDescriptorProto file = 1;
-  for (unsigned int i = 0, n = this->file_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->file_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        1, this->file(i), deterministic, target);
+        1, this->file(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet)
   return target;
@@ -1149,16 +1231,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.FileDescriptorProto file = 1;
   {
-    unsigned int count = this->file_size();
+    unsigned int count = static_cast<unsigned int>(this->file_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->file(i));
+          this->file(static_cast<int>(i)));
     }
   }
 
@@ -1218,10 +1300,11 @@
   InternalSwap(other);
 }
 void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) {
+  using std::swap;
   file_.InternalSwap(&other->file_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata FileDescriptorSet::GetMetadata() const {
@@ -1332,8 +1415,9 @@
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   package_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   syntax_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, reinterpret_cast<char*>(&source_code_info_) -
-    reinterpret_cast<char*>(&options_) + sizeof(source_code_info_));
+  ::memset(&options_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&source_code_info_) -
+      reinterpret_cast<char*>(&options_)) + sizeof(source_code_info_));
 }
 
 FileDescriptorProto::~FileDescriptorProto() {
@@ -1345,12 +1429,8 @@
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   syntax_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
-  if (this != internal_default_instance()) {
-    delete source_code_info_;
-  }
+  if (this != internal_default_instance()) delete options_;
+  if (this != internal_default_instance()) delete source_code_info_;
 }
 
 void FileDescriptorProto::SetCachedSize(int size) const {
@@ -1378,6 +1458,10 @@
 
 void FileDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   dependency_.Clear();
   message_type_.Clear();
   enum_type_.Clear();
@@ -1385,24 +1469,25 @@
   extension_.Clear();
   public_dependency_.Clear();
   weak_dependency_.Clear();
-  if (_has_bits_[0 / 32] & 31u) {
-    if (has_name()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 31u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_package()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!package_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*package_.UnsafeRawStringPointer())->clear();
     }
-    if (has_syntax()) {
+    if (cached_has_bits & 0x00000004u) {
       GOOGLE_DCHECK(!syntax_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*syntax_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000008u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::FileOptions::Clear();
     }
-    if (has_source_code_info()) {
+    if (cached_has_bits & 0x00000010u) {
       GOOGLE_DCHECK(source_code_info_ != NULL);
       source_code_info_->::google::protobuf::SourceCodeInfo::Clear();
     }
@@ -1424,11 +1509,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileDescriptorProto.name");
         } else {
@@ -1440,11 +1525,11 @@
       // optional string package = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_package()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->package().data(), this->package().length(),
+            this->package().data(), static_cast<int>(this->package().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileDescriptorProto.package");
         } else {
@@ -1456,12 +1541,12 @@
       // repeated string dependency = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_dependency()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
             this->dependency(this->dependency_size() - 1).data(),
-            this->dependency(this->dependency_size() - 1).length(),
+            static_cast<int>(this->dependency(this->dependency_size() - 1).length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileDescriptorProto.dependency");
         } else {
@@ -1473,7 +1558,7 @@
       // repeated .google.protobuf.DescriptorProto message_type = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_message_type()));
         } else {
@@ -1485,7 +1570,7 @@
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(42u)) {
+            static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_enum_type()));
         } else {
@@ -1497,7 +1582,7 @@
       // repeated .google.protobuf.ServiceDescriptorProto service = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_service()));
         } else {
@@ -1509,7 +1594,7 @@
       // repeated .google.protobuf.FieldDescriptorProto extension = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(58u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_extension()));
         } else {
@@ -1521,7 +1606,7 @@
       // optional .google.protobuf.FileOptions options = 8;
       case 8: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(66u)) {
+            static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -1533,7 +1618,7 @@
       // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
       case 9: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(74u)) {
+            static_cast< ::google::protobuf::uint8>(74u /* 74 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_source_code_info()));
         } else {
@@ -1545,12 +1630,13 @@
       // repeated int32 public_dependency = 10;
       case 10: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(80u)) {
+            static_cast< ::google::protobuf::uint8>(80u /* 80 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  1, 80u, input, this->mutable_public_dependency())));
-        } else if (static_cast< ::google::protobuf::uint8>(tag) ==
-                   static_cast< ::google::protobuf::uint8>(82u)) {
+        } else if (
+            static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, this->mutable_public_dependency())));
@@ -1563,12 +1649,13 @@
       // repeated int32 weak_dependency = 11;
       case 11: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(88u)) {
+            static_cast< ::google::protobuf::uint8>(88u /* 88 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  1, 88u, input, this->mutable_weak_dependency())));
-        } else if (static_cast< ::google::protobuf::uint8>(tag) ==
-                   static_cast< ::google::protobuf::uint8>(90u)) {
+        } else if (
+            static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(90u /* 90 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, this->mutable_weak_dependency())));
@@ -1581,11 +1668,11 @@
       // optional string syntax = 12;
       case 12: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(98u)) {
+            static_cast< ::google::protobuf::uint8>(98u /* 98 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_syntax()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->syntax().data(), this->syntax().length(),
+            this->syntax().data(), static_cast<int>(this->syntax().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileDescriptorProto.syntax");
         } else {
@@ -1596,13 +1683,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1626,7 +1711,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1636,7 +1721,7 @@
   // optional string package = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->package().data(), this->package().length(),
+      this->package().data(), static_cast<int>(this->package().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.package");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1646,7 +1731,7 @@
   // repeated string dependency = 3;
   for (int i = 0, n = this->dependency_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->dependency(i).data(), this->dependency(i).length(),
+      this->dependency(i).data(), static_cast<int>(this->dependency(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.dependency");
     ::google::protobuf::internal::WireFormatLite::WriteString(
@@ -1654,27 +1739,31 @@
   }
 
   // repeated .google.protobuf.DescriptorProto message_type = 4;
-  for (unsigned int i = 0, n = this->message_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->message_type_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      4, this->message_type(i), output);
+      4, this->message_type(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
-  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->enum_type_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      5, this->enum_type(i), output);
+      5, this->enum_type(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
-  for (unsigned int i = 0, n = this->service_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->service_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      6, this->service(i), output);
+      6, this->service(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
-  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->extension_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      7, this->extension(i), output);
+      7, this->extension(static_cast<int>(i)), output);
   }
 
   // optional .google.protobuf.FileOptions options = 8;
@@ -1704,7 +1793,7 @@
   // optional string syntax = 12;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->syntax().data(), this->syntax().length(),
+      this->syntax().data(), static_cast<int>(this->syntax().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.syntax");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1713,13 +1802,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorProto)
 }
 
 ::google::protobuf::uint8* FileDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1728,7 +1818,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.name");
     target =
@@ -1739,7 +1829,7 @@
   // optional string package = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->package().data(), this->package().length(),
+      this->package().data(), static_cast<int>(this->package().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.package");
     target =
@@ -1750,7 +1840,7 @@
   // repeated string dependency = 3;
   for (int i = 0, n = this->dependency_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->dependency(i).data(), this->dependency(i).length(),
+      this->dependency(i).data(), static_cast<int>(this->dependency(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.dependency");
     target = ::google::protobuf::internal::WireFormatLite::
@@ -1758,31 +1848,35 @@
   }
 
   // repeated .google.protobuf.DescriptorProto message_type = 4;
-  for (unsigned int i = 0, n = this->message_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->message_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        4, this->message_type(i), deterministic, target);
+        4, this->message_type(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
-  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->enum_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        5, this->enum_type(i), deterministic, target);
+        5, this->enum_type(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
-  for (unsigned int i = 0, n = this->service_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->service_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        6, this->service(i), deterministic, target);
+        6, this->service(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
-  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->extension_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        7, this->extension(i), deterministic, target);
+        7, this->extension(static_cast<int>(i)), deterministic, target);
   }
 
   // optional .google.protobuf.FileOptions options = 8;
@@ -1810,7 +1904,7 @@
   // optional string syntax = 12;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->syntax().data(), this->syntax().length(),
+      this->syntax().data(), static_cast<int>(this->syntax().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileDescriptorProto.syntax");
     target =
@@ -1820,7 +1914,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto)
   return target;
@@ -1833,7 +1927,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated string dependency = 3;
   total_size += 1 *
@@ -1845,45 +1939,45 @@
 
   // repeated .google.protobuf.DescriptorProto message_type = 4;
   {
-    unsigned int count = this->message_type_size();
+    unsigned int count = static_cast<unsigned int>(this->message_type_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->message_type(i));
+          this->message_type(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
   {
-    unsigned int count = this->enum_type_size();
+    unsigned int count = static_cast<unsigned int>(this->enum_type_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->enum_type(i));
+          this->enum_type(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.ServiceDescriptorProto service = 6;
   {
-    unsigned int count = this->service_size();
+    unsigned int count = static_cast<unsigned int>(this->service_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->service(i));
+          this->service(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 7;
   {
-    unsigned int count = this->extension_size();
+    unsigned int count = static_cast<unsigned int>(this->extension_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->extension(i));
+          this->extension(static_cast<int>(i)));
     }
   }
 
@@ -2031,6 +2125,7 @@
   InternalSwap(other);
 }
 void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) {
+  using std::swap;
   dependency_.InternalSwap(&other->dependency_);
   message_type_.InternalSwap(&other->message_type_);
   enum_type_.InternalSwap(&other->enum_type_);
@@ -2041,11 +2136,11 @@
   name_.Swap(&other->name_);
   package_.Swap(&other->package_);
   syntax_.Swap(&other->syntax_);
-  std::swap(options_, other->options_);
-  std::swap(source_code_info_, other->source_code_info_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(source_code_info_, other->source_code_info_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata FileDescriptorProto::GetMetadata() const {
@@ -2446,9 +2541,10 @@
   clear_has_options();
 }
 const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+  const ::google::protobuf::FileOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::FileOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::FileOptions*>(
+      &::google::protobuf::_FileOptions_default_instance_);
 }
 ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
   set_has_options();
@@ -2491,9 +2587,10 @@
   clear_has_source_code_info();
 }
 const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  const ::google::protobuf::SourceCodeInfo* p = source_code_info_;
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
-  return source_code_info_ != NULL ? *source_code_info_
-                         : *::google::protobuf::SourceCodeInfo::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceCodeInfo*>(
+      &::google::protobuf::_SourceCodeInfo_default_instance_);
 }
 ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
   set_has_source_code_info();
@@ -2591,6 +2688,7 @@
 #if !defined(_MSC_VER) || _MSC_VER >= 1900
 const int DescriptorProto_ExtensionRange::kStartFieldNumber;
 const int DescriptorProto_ExtensionRange::kEndFieldNumber;
+const int DescriptorProto_ExtensionRange::kOptionsFieldNumber;
 #endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
 
 DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange()
@@ -2607,16 +2705,22 @@
       _has_bits_(from._has_bits_),
       _cached_size_(0) {
   _internal_metadata_.MergeFrom(from._internal_metadata_);
+  if (from.has_options()) {
+    options_ = new ::google::protobuf::ExtensionRangeOptions(*from.options_);
+  } else {
+    options_ = NULL;
+  }
   ::memcpy(&start_, &from.start_,
-    reinterpret_cast<char*>(&end_) -
-    reinterpret_cast<char*>(&start_) + sizeof(end_));
+    static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&start_)) + sizeof(end_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange)
 }
 
 void DescriptorProto_ExtensionRange::SharedCtor() {
   _cached_size_ = 0;
-  ::memset(&start_, 0, reinterpret_cast<char*>(&end_) -
-    reinterpret_cast<char*>(&start_) + sizeof(end_));
+  ::memset(&options_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&end_) -
+      reinterpret_cast<char*>(&options_)) + sizeof(end_));
 }
 
 DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() {
@@ -2625,6 +2729,7 @@
 }
 
 void DescriptorProto_ExtensionRange::SharedDtor() {
+  if (this != internal_default_instance()) delete options_;
 }
 
 void DescriptorProto_ExtensionRange::SetCachedSize(int size) const {
@@ -2652,9 +2757,19 @@
 
 void DescriptorProto_ExtensionRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange)
-  if (_has_bits_[0 / 32] & 3u) {
-    ::memset(&start_, 0, reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&start_) + sizeof(end_));
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (has_options()) {
+    GOOGLE_DCHECK(options_ != NULL);
+    options_->::google::protobuf::ExtensionRangeOptions::Clear();
+  }
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 6u) {
+    ::memset(&start_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&end_) -
+        reinterpret_cast<char*>(&start_)) + sizeof(end_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -2673,7 +2788,7 @@
       // optional int32 start = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           set_has_start();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -2687,7 +2802,7 @@
       // optional int32 end = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_end();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -2698,15 +2813,25 @@
         break;
       }
 
+      // optional .google.protobuf.ExtensionRangeOptions options = 3;
+      case 3: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+               input, mutable_options()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -2728,42 +2853,56 @@
 
   cached_has_bits = _has_bits_[0];
   // optional int32 start = 1;
-  if (cached_has_bits & 0x00000001u) {
+  if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output);
   }
 
   // optional int32 end = 2;
-  if (cached_has_bits & 0x00000002u) {
+  if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output);
   }
 
+  // optional .google.protobuf.ExtensionRangeOptions options = 3;
+  if (cached_has_bits & 0x00000001u) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      3, *this->options_, output);
+  }
+
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ExtensionRange)
 }
 
 ::google::protobuf::uint8* DescriptorProto_ExtensionRange::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _has_bits_[0];
   // optional int32 start = 1;
-  if (cached_has_bits & 0x00000001u) {
+  if (cached_has_bits & 0x00000002u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target);
   }
 
   // optional int32 end = 2;
-  if (cached_has_bits & 0x00000002u) {
+  if (cached_has_bits & 0x00000004u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target);
   }
 
+  // optional .google.protobuf.ExtensionRangeOptions options = 3;
+  if (cached_has_bits & 0x00000001u) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageNoVirtualToArray(
+        3, *this->options_, deterministic, target);
+  }
+
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange)
   return target;
@@ -2776,9 +2915,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
-  if (_has_bits_[0 / 32] & 3u) {
+  if (_has_bits_[0 / 32] & 7u) {
+    // optional .google.protobuf.ExtensionRangeOptions options = 3;
+    if (has_options()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          *this->options_);
+    }
+
     // optional int32 start = 1;
     if (has_start()) {
       total_size += 1 +
@@ -2824,11 +2970,14 @@
   (void) cached_has_bits;
 
   cached_has_bits = from._has_bits_[0];
-  if (cached_has_bits & 3u) {
+  if (cached_has_bits & 7u) {
     if (cached_has_bits & 0x00000001u) {
-      start_ = from.start_;
+      mutable_options()->::google::protobuf::ExtensionRangeOptions::MergeFrom(from.options());
     }
     if (cached_has_bits & 0x00000002u) {
+      start_ = from.start_;
+    }
+    if (cached_has_bits & 0x00000004u) {
       end_ = from.end_;
     }
     _has_bits_[0] |= cached_has_bits;
@@ -2850,6 +2999,9 @@
 }
 
 bool DescriptorProto_ExtensionRange::IsInitialized() const {
+  if (has_options()) {
+    if (!this->options_->IsInitialized()) return false;
+  }
   return true;
 }
 
@@ -2858,11 +3010,13 @@
   InternalSwap(other);
 }
 void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange* other) {
-  std::swap(start_, other->start_);
-  std::swap(end_, other->end_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  using std::swap;
+  swap(options_, other->options_);
+  swap(start_, other->start_);
+  swap(end_, other->end_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
@@ -2875,13 +3029,13 @@
 
 // optional int32 start = 1;
 bool DescriptorProto_ExtensionRange::has_start() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
+  return (_has_bits_[0] & 0x00000002u) != 0;
 }
 void DescriptorProto_ExtensionRange::set_has_start() {
-  _has_bits_[0] |= 0x00000001u;
+  _has_bits_[0] |= 0x00000002u;
 }
 void DescriptorProto_ExtensionRange::clear_has_start() {
-  _has_bits_[0] &= ~0x00000001u;
+  _has_bits_[0] &= ~0x00000002u;
 }
 void DescriptorProto_ExtensionRange::clear_start() {
   start_ = 0;
@@ -2899,13 +3053,13 @@
 
 // optional int32 end = 2;
 bool DescriptorProto_ExtensionRange::has_end() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
+  return (_has_bits_[0] & 0x00000004u) != 0;
 }
 void DescriptorProto_ExtensionRange::set_has_end() {
-  _has_bits_[0] |= 0x00000002u;
+  _has_bits_[0] |= 0x00000004u;
 }
 void DescriptorProto_ExtensionRange::clear_has_end() {
-  _has_bits_[0] &= ~0x00000002u;
+  _has_bits_[0] &= ~0x00000004u;
 }
 void DescriptorProto_ExtensionRange::clear_end() {
   end_ = 0;
@@ -2921,6 +3075,52 @@
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
 }
 
+// optional .google.protobuf.ExtensionRangeOptions options = 3;
+bool DescriptorProto_ExtensionRange::has_options() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+void DescriptorProto_ExtensionRange::set_has_options() {
+  _has_bits_[0] |= 0x00000001u;
+}
+void DescriptorProto_ExtensionRange::clear_has_options() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+void DescriptorProto_ExtensionRange::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::ExtensionRangeOptions::Clear();
+  clear_has_options();
+}
+const ::google::protobuf::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const {
+  const ::google::protobuf::ExtensionRangeOptions* p = options_;
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options)
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::ExtensionRangeOptions*>(
+      &::google::protobuf::_ExtensionRangeOptions_default_instance_);
+}
+::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::ExtensionRangeOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options)
+  return options_;
+}
+::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.ExtensionRange.options)
+  clear_has_options();
+  ::google::protobuf::ExtensionRangeOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+void DescriptorProto_ExtensionRange::set_allocated_options(::google::protobuf::ExtensionRangeOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options)
+}
+
 #endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // ===================================================================
@@ -2945,15 +3145,16 @@
       _cached_size_(0) {
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   ::memcpy(&start_, &from.start_,
-    reinterpret_cast<char*>(&end_) -
-    reinterpret_cast<char*>(&start_) + sizeof(end_));
+    static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&start_)) + sizeof(end_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange)
 }
 
 void DescriptorProto_ReservedRange::SharedCtor() {
   _cached_size_ = 0;
-  ::memset(&start_, 0, reinterpret_cast<char*>(&end_) -
-    reinterpret_cast<char*>(&start_) + sizeof(end_));
+  ::memset(&start_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&end_) -
+      reinterpret_cast<char*>(&start_)) + sizeof(end_));
 }
 
 DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() {
@@ -2989,9 +3190,15 @@
 
 void DescriptorProto_ReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange)
-  if (_has_bits_[0 / 32] & 3u) {
-    ::memset(&start_, 0, reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&start_) + sizeof(end_));
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    ::memset(&start_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&end_) -
+        reinterpret_cast<char*>(&start_)) + sizeof(end_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -3010,7 +3217,7 @@
       // optional int32 start = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           set_has_start();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -3024,7 +3231,7 @@
       // optional int32 end = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_end();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -3037,13 +3244,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -3076,13 +3281,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ReservedRange)
 }
 
 ::google::protobuf::uint8* DescriptorProto_ReservedRange::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3100,7 +3306,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange)
   return target;
@@ -3113,7 +3319,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 3u) {
     // optional int32 start = 1;
@@ -3195,11 +3401,12 @@
   InternalSwap(other);
 }
 void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) {
-  std::swap(start_, other->start_);
-  std::swap(end_, other->end_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  using std::swap;
+  swap(start_, other->start_);
+  swap(end_, other->end_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata DescriptorProto_ReservedRange::GetMetadata() const {
@@ -3322,9 +3529,7 @@
 
 void DescriptorProto::SharedDtor() {
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void DescriptorProto::SetCachedSize(int size) const {
@@ -3352,6 +3557,10 @@
 
 void DescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   field_.Clear();
   nested_type_.Clear();
   enum_type_.Clear();
@@ -3360,12 +3569,13 @@
   oneof_decl_.Clear();
   reserved_range_.Clear();
   reserved_name_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_name()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::MessageOptions::Clear();
     }
@@ -3387,11 +3597,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.DescriptorProto.name");
         } else {
@@ -3403,7 +3613,7 @@
       // repeated .google.protobuf.FieldDescriptorProto field = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_field()));
         } else {
@@ -3415,7 +3625,7 @@
       // repeated .google.protobuf.DescriptorProto nested_type = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_nested_type()));
         } else {
@@ -3427,7 +3637,7 @@
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_enum_type()));
         } else {
@@ -3439,7 +3649,7 @@
       // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(42u)) {
+            static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_extension_range()));
         } else {
@@ -3451,7 +3661,7 @@
       // repeated .google.protobuf.FieldDescriptorProto extension = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_extension()));
         } else {
@@ -3463,7 +3673,7 @@
       // optional .google.protobuf.MessageOptions options = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(58u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -3475,7 +3685,7 @@
       // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
       case 8: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(66u)) {
+            static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_oneof_decl()));
         } else {
@@ -3487,7 +3697,7 @@
       // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
       case 9: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(74u)) {
+            static_cast< ::google::protobuf::uint8>(74u /* 74 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_reserved_range()));
         } else {
@@ -3499,12 +3709,12 @@
       // repeated string reserved_name = 10;
       case 10: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(82u)) {
+            static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_reserved_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
             this->reserved_name(this->reserved_name_size() - 1).data(),
-            this->reserved_name(this->reserved_name_size() - 1).length(),
+            static_cast<int>(this->reserved_name(this->reserved_name_size() - 1).length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.DescriptorProto.reserved_name");
         } else {
@@ -3515,13 +3725,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -3545,7 +3753,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.DescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -3553,33 +3761,38 @@
   }
 
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
-  for (unsigned int i = 0, n = this->field_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->field_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->field(i), output);
+      2, this->field(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
-  for (unsigned int i = 0, n = this->nested_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->nested_type_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      3, this->nested_type(i), output);
+      3, this->nested_type(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
-  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->enum_type_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      4, this->enum_type(i), output);
+      4, this->enum_type(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
-  for (unsigned int i = 0, n = this->extension_range_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->extension_range_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      5, this->extension_range(i), output);
+      5, this->extension_range(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
-  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->extension_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      6, this->extension(i), output);
+      6, this->extension(static_cast<int>(i)), output);
   }
 
   // optional .google.protobuf.MessageOptions options = 7;
@@ -3589,21 +3802,23 @@
   }
 
   // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
-  for (unsigned int i = 0, n = this->oneof_decl_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->oneof_decl_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      8, this->oneof_decl(i), output);
+      8, this->oneof_decl(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
-  for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->reserved_range_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      9, this->reserved_range(i), output);
+      9, this->reserved_range(static_cast<int>(i)), output);
   }
 
   // repeated string reserved_name = 10;
   for (int i = 0, n = this->reserved_name_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->reserved_name(i).data(), this->reserved_name(i).length(),
+      this->reserved_name(i).data(), static_cast<int>(this->reserved_name(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.DescriptorProto.reserved_name");
     ::google::protobuf::internal::WireFormatLite::WriteString(
@@ -3612,13 +3827,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto)
 }
 
 ::google::protobuf::uint8* DescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3627,7 +3843,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.DescriptorProto.name");
     target =
@@ -3636,38 +3852,43 @@
   }
 
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
-  for (unsigned int i = 0, n = this->field_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->field_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->field(i), deterministic, target);
+        2, this->field(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
-  for (unsigned int i = 0, n = this->nested_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->nested_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        3, this->nested_type(i), deterministic, target);
+        3, this->nested_type(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
-  for (unsigned int i = 0, n = this->enum_type_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->enum_type_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        4, this->enum_type(i), deterministic, target);
+        4, this->enum_type(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
-  for (unsigned int i = 0, n = this->extension_range_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->extension_range_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        5, this->extension_range(i), deterministic, target);
+        5, this->extension_range(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
-  for (unsigned int i = 0, n = this->extension_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->extension_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        6, this->extension(i), deterministic, target);
+        6, this->extension(static_cast<int>(i)), deterministic, target);
   }
 
   // optional .google.protobuf.MessageOptions options = 7;
@@ -3678,23 +3899,25 @@
   }
 
   // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
-  for (unsigned int i = 0, n = this->oneof_decl_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->oneof_decl_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        8, this->oneof_decl(i), deterministic, target);
+        8, this->oneof_decl(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
-  for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->reserved_range_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        9, this->reserved_range(i), deterministic, target);
+        9, this->reserved_range(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated string reserved_name = 10;
   for (int i = 0, n = this->reserved_name_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->reserved_name(i).data(), this->reserved_name(i).length(),
+      this->reserved_name(i).data(), static_cast<int>(this->reserved_name(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.DescriptorProto.reserved_name");
     target = ::google::protobuf::internal::WireFormatLite::
@@ -3703,7 +3926,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto)
   return target;
@@ -3716,82 +3939,82 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.FieldDescriptorProto field = 2;
   {
-    unsigned int count = this->field_size();
+    unsigned int count = static_cast<unsigned int>(this->field_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->field(i));
+          this->field(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.DescriptorProto nested_type = 3;
   {
-    unsigned int count = this->nested_type_size();
+    unsigned int count = static_cast<unsigned int>(this->nested_type_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->nested_type(i));
+          this->nested_type(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
   {
-    unsigned int count = this->enum_type_size();
+    unsigned int count = static_cast<unsigned int>(this->enum_type_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->enum_type(i));
+          this->enum_type(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
   {
-    unsigned int count = this->extension_range_size();
+    unsigned int count = static_cast<unsigned int>(this->extension_range_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->extension_range(i));
+          this->extension_range(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.FieldDescriptorProto extension = 6;
   {
-    unsigned int count = this->extension_size();
+    unsigned int count = static_cast<unsigned int>(this->extension_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->extension(i));
+          this->extension(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
   {
-    unsigned int count = this->oneof_decl_size();
+    unsigned int count = static_cast<unsigned int>(this->oneof_decl_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->oneof_decl(i));
+          this->oneof_decl(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
   {
-    unsigned int count = this->reserved_range_size();
+    unsigned int count = static_cast<unsigned int>(this->reserved_range_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->reserved_range(i));
+          this->reserved_range(static_cast<int>(i)));
     }
   }
 
@@ -3886,6 +4109,7 @@
   if (!::google::protobuf::internal::AllAreInitialized(this->field())) return false;
   if (!::google::protobuf::internal::AllAreInitialized(this->nested_type())) return false;
   if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false;
+  if (!::google::protobuf::internal::AllAreInitialized(this->extension_range())) return false;
   if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false;
   if (!::google::protobuf::internal::AllAreInitialized(this->oneof_decl())) return false;
   if (has_options()) {
@@ -3899,6 +4123,7 @@
   InternalSwap(other);
 }
 void DescriptorProto::InternalSwap(DescriptorProto* other) {
+  using std::swap;
   field_.InternalSwap(&other->field_);
   nested_type_.InternalSwap(&other->nested_type_);
   enum_type_.InternalSwap(&other->enum_type_);
@@ -3908,10 +4133,10 @@
   reserved_range_.InternalSwap(&other->reserved_range_);
   reserved_name_.InternalSwap(&other->reserved_name_);
   name_.Swap(&other->name_);
-  std::swap(options_, other->options_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata DescriptorProto::GetMetadata() const {
@@ -4180,9 +4405,10 @@
   clear_has_options();
 }
 const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+  const ::google::protobuf::MessageOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::MessageOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::MessageOptions*>(
+      &::google::protobuf::_MessageOptions_default_instance_);
 }
 ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
   set_has_options();
@@ -4314,6 +4540,308 @@
 // ===================================================================
 
 #if !defined(_MSC_VER) || _MSC_VER >= 1900
+const int ExtensionRangeOptions::kUninterpretedOptionFieldNumber;
+#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
+
+ExtensionRangeOptions::ExtensionRangeOptions()
+  : ::google::protobuf::Message(), _internal_metadata_(NULL) {
+  if (GOOGLE_PREDICT_TRUE(this != internal_default_instance())) {
+    protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults();
+  }
+  SharedCtor();
+  // @@protoc_insertion_point(constructor:google.protobuf.ExtensionRangeOptions)
+}
+ExtensionRangeOptions::ExtensionRangeOptions(const ExtensionRangeOptions& from)
+  : ::google::protobuf::Message(),
+      _internal_metadata_(NULL),
+      _has_bits_(from._has_bits_),
+      _cached_size_(0),
+      uninterpreted_option_(from.uninterpreted_option_) {
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  _extensions_.MergeFrom(from._extensions_);
+  // @@protoc_insertion_point(copy_constructor:google.protobuf.ExtensionRangeOptions)
+}
+
+void ExtensionRangeOptions::SharedCtor() {
+  _cached_size_ = 0;
+}
+
+ExtensionRangeOptions::~ExtensionRangeOptions() {
+  // @@protoc_insertion_point(destructor:google.protobuf.ExtensionRangeOptions)
+  SharedDtor();
+}
+
+void ExtensionRangeOptions::SharedDtor() {
+}
+
+void ExtensionRangeOptions::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* ExtensionRangeOptions::descriptor() {
+  protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce();
+  return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages].descriptor;
+}
+
+const ExtensionRangeOptions& ExtensionRangeOptions::default_instance() {
+  protobuf_google_2fprotobuf_2fdescriptor_2eproto::InitDefaults();
+  return *internal_default_instance();
+}
+
+ExtensionRangeOptions* ExtensionRangeOptions::New(::google::protobuf::Arena* arena) const {
+  ExtensionRangeOptions* n = new ExtensionRangeOptions;
+  if (arena != NULL) {
+    arena->Own(n);
+  }
+  return n;
+}
+
+void ExtensionRangeOptions::Clear() {
+// @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _extensions_.Clear();
+  uninterpreted_option_.Clear();
+  _has_bits_.Clear();
+  _internal_metadata_.Clear();
+}
+
+bool ExtensionRangeOptions::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure
+  ::google::protobuf::uint32 tag;
+  // @@protoc_insertion_point(parse_start:google.protobuf.ExtensionRangeOptions)
+  for (;;) {
+    ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(16383u);
+    tag = p.first;
+    if (!p.second) goto handle_unusual;
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+      case 999: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_uninterpreted_option()));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
+      default: {
+      handle_unusual:
+        if (tag == 0) {
+          goto success;
+        }
+        if ((8000u <= tag)) {
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
+          continue;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+success:
+  // @@protoc_insertion_point(parse_success:google.protobuf.ExtensionRangeOptions)
+  return true;
+failure:
+  // @@protoc_insertion_point(parse_failure:google.protobuf.ExtensionRangeOptions)
+  return false;
+#undef DO_
+}
+
+void ExtensionRangeOptions::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // @@protoc_insertion_point(serialize_start:google.protobuf.ExtensionRangeOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
+  }
+
+  // Extension range [1000, 536870912)
+  _extensions_.SerializeWithCachedSizes(
+      1000, 536870912, output);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        _internal_metadata_.unknown_fields(), output);
+  }
+  // @@protoc_insertion_point(serialize_end:google.protobuf.ExtensionRangeOptions)
+}
+
+::google::protobuf::uint8* ExtensionRangeOptions::InternalSerializeWithCachedSizesToArray(
+    bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
+  // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      InternalWriteMessageNoVirtualToArray(
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
+  }
+
+  // Extension range [1000, 536870912)
+  target = _extensions_.InternalSerializeWithCachedSizesToArray(
+      1000, 536870912, deterministic, target);
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields(), target);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ExtensionRangeOptions)
+  return target;
+}
+
+size_t ExtensionRangeOptions::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions)
+  size_t total_size = 0;
+
+  total_size += _extensions_.ByteSize();
+
+  if (_internal_metadata_.have_unknown_fields()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        _internal_metadata_.unknown_fields());
+  }
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  {
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
+    total_size += 2UL * count;
+    for (unsigned int i = 0; i < count; i++) {
+      total_size +=
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->uninterpreted_option(static_cast<int>(i)));
+    }
+  }
+
+  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = cached_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void ExtensionRangeOptions::MergeFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ExtensionRangeOptions)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ExtensionRangeOptions* source =
+      ::google::protobuf::internal::DynamicCastToGenerated<const ExtensionRangeOptions>(
+          &from);
+  if (source == NULL) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ExtensionRangeOptions)
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ExtensionRangeOptions)
+    MergeFrom(*source);
+  }
+}
+
+void ExtensionRangeOptions::MergeFrom(const ExtensionRangeOptions& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ExtensionRangeOptions)
+  GOOGLE_DCHECK_NE(&from, this);
+  _extensions_.MergeFrom(from._extensions_);
+  _internal_metadata_.MergeFrom(from._internal_metadata_);
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  uninterpreted_option_.MergeFrom(from.uninterpreted_option_);
+}
+
+void ExtensionRangeOptions::CopyFrom(const ::google::protobuf::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ExtensionRangeOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ExtensionRangeOptions::CopyFrom(const ExtensionRangeOptions& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ExtensionRangeOptions)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ExtensionRangeOptions::IsInitialized() const {
+  if (!_extensions_.IsInitialized()) {
+    return false;
+  }
+
+  if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false;
+  return true;
+}
+
+void ExtensionRangeOptions::Swap(ExtensionRangeOptions* other) {
+  if (other == this) return;
+  InternalSwap(other);
+}
+void ExtensionRangeOptions::InternalSwap(ExtensionRangeOptions* other) {
+  using std::swap;
+  uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
+  _extensions_.Swap(&other->_extensions_);
+}
+
+::google::protobuf::Metadata ExtensionRangeOptions::GetMetadata() const {
+  protobuf_google_2fprotobuf_2fdescriptor_2eproto::protobuf_AssignDescriptorsOnce();
+  return protobuf_google_2fprotobuf_2fdescriptor_2eproto::file_level_metadata[kIndexInFileMessages];
+}
+
+#if PROTOBUF_INLINE_NOT_IN_HEADERS
+// ExtensionRangeOptions
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+int ExtensionRangeOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+void ExtensionRangeOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+const ::google::protobuf::UninterpretedOption& ExtensionRangeOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+::google::protobuf::UninterpretedOption* ExtensionRangeOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+::google::protobuf::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ExtensionRangeOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ExtensionRangeOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+#endif  // PROTOBUF_INLINE_NOT_IN_HEADERS
+
+// ===================================================================
+
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
 const int FieldDescriptorProto::kNameFieldNumber;
 const int FieldDescriptorProto::kNumberFieldNumber;
 const int FieldDescriptorProto::kLabelFieldNumber;
@@ -4366,8 +4894,8 @@
     options_ = NULL;
   }
   ::memcpy(&number_, &from.number_,
-    reinterpret_cast<char*>(&type_) -
-    reinterpret_cast<char*>(&number_) + sizeof(type_));
+    static_cast<size_t>(reinterpret_cast<char*>(&type_) -
+    reinterpret_cast<char*>(&number_)) + sizeof(type_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto)
 }
 
@@ -4378,8 +4906,9 @@
   type_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, reinterpret_cast<char*>(&oneof_index_) -
-    reinterpret_cast<char*>(&options_) + sizeof(oneof_index_));
+  ::memset(&options_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&oneof_index_) -
+      reinterpret_cast<char*>(&options_)) + sizeof(oneof_index_));
   label_ = 1;
   type_ = 1;
 }
@@ -4395,9 +4924,7 @@
   type_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   default_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   json_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void FieldDescriptorProto::SetCachedSize(int size) const {
@@ -4425,37 +4952,43 @@
 
 void FieldDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto)
-  if (_has_bits_[0 / 32] & 63u) {
-    if (has_name()) {
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 63u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_extendee()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!extendee_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*extendee_.UnsafeRawStringPointer())->clear();
     }
-    if (has_type_name()) {
+    if (cached_has_bits & 0x00000004u) {
       GOOGLE_DCHECK(!type_name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*type_name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_default_value()) {
+    if (cached_has_bits & 0x00000008u) {
       GOOGLE_DCHECK(!default_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*default_value_.UnsafeRawStringPointer())->clear();
     }
-    if (has_json_name()) {
+    if (cached_has_bits & 0x00000010u) {
       GOOGLE_DCHECK(!json_name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*json_name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000020u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::FieldOptions::Clear();
     }
   }
-  if (_has_bits_[0 / 32] & 192u) {
-    ::memset(&number_, 0, reinterpret_cast<char*>(&oneof_index_) -
-      reinterpret_cast<char*>(&number_) + sizeof(oneof_index_));
+  if (cached_has_bits & 192u) {
+    ::memset(&number_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&oneof_index_) -
+        reinterpret_cast<char*>(&number_)) + sizeof(oneof_index_));
   }
-  if (_has_bits_[8 / 32] & 768u) {
+  if (cached_has_bits & 768u) {
     label_ = 1;
     type_ = 1;
   }
@@ -4476,11 +5009,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FieldDescriptorProto.name");
         } else {
@@ -4492,11 +5025,11 @@
       // optional string extendee = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_extendee()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->extendee().data(), this->extendee().length(),
+            this->extendee().data(), static_cast<int>(this->extendee().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FieldDescriptorProto.extendee");
         } else {
@@ -4508,7 +5041,7 @@
       // optional int32 number = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
           set_has_number();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -4522,7 +5055,7 @@
       // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(32u)) {
+            static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -4530,7 +5063,8 @@
           if (::google::protobuf::FieldDescriptorProto_Label_IsValid(value)) {
             set_label(static_cast< ::google::protobuf::FieldDescriptorProto_Label >(value));
           } else {
-            mutable_unknown_fields()->AddVarint(4, value);
+            mutable_unknown_fields()->AddVarint(
+                4, static_cast< ::google::protobuf::uint64>(value));
           }
         } else {
           goto handle_unusual;
@@ -4541,7 +5075,7 @@
       // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(40u)) {
+            static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -4549,7 +5083,8 @@
           if (::google::protobuf::FieldDescriptorProto_Type_IsValid(value)) {
             set_type(static_cast< ::google::protobuf::FieldDescriptorProto_Type >(value));
           } else {
-            mutable_unknown_fields()->AddVarint(5, value);
+            mutable_unknown_fields()->AddVarint(
+                5, static_cast< ::google::protobuf::uint64>(value));
           }
         } else {
           goto handle_unusual;
@@ -4560,11 +5095,11 @@
       // optional string type_name = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_type_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->type_name().data(), this->type_name().length(),
+            this->type_name().data(), static_cast<int>(this->type_name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FieldDescriptorProto.type_name");
         } else {
@@ -4576,11 +5111,11 @@
       // optional string default_value = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(58u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_default_value()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->default_value().data(), this->default_value().length(),
+            this->default_value().data(), static_cast<int>(this->default_value().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FieldDescriptorProto.default_value");
         } else {
@@ -4592,7 +5127,7 @@
       // optional .google.protobuf.FieldOptions options = 8;
       case 8: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(66u)) {
+            static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -4604,7 +5139,7 @@
       // optional int32 oneof_index = 9;
       case 9: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(72u)) {
+            static_cast< ::google::protobuf::uint8>(72u /* 72 & 0xFF */)) {
           set_has_oneof_index();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -4618,11 +5153,11 @@
       // optional string json_name = 10;
       case 10: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(82u)) {
+            static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_json_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->json_name().data(), this->json_name().length(),
+            this->json_name().data(), static_cast<int>(this->json_name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FieldDescriptorProto.json_name");
         } else {
@@ -4633,13 +5168,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -4663,7 +5196,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -4673,7 +5206,7 @@
   // optional string extendee = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->extendee().data(), this->extendee().length(),
+      this->extendee().data(), static_cast<int>(this->extendee().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.extendee");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -4700,7 +5233,7 @@
   // optional string type_name = 6;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->type_name().data(), this->type_name().length(),
+      this->type_name().data(), static_cast<int>(this->type_name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.type_name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -4710,7 +5243,7 @@
   // optional string default_value = 7;
   if (cached_has_bits & 0x00000008u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->default_value().data(), this->default_value().length(),
+      this->default_value().data(), static_cast<int>(this->default_value().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.default_value");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -4731,7 +5264,7 @@
   // optional string json_name = 10;
   if (cached_has_bits & 0x00000010u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->json_name().data(), this->json_name().length(),
+      this->json_name().data(), static_cast<int>(this->json_name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.json_name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -4740,13 +5273,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FieldDescriptorProto)
 }
 
 ::google::protobuf::uint8* FieldDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -4755,7 +5289,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.name");
     target =
@@ -4766,7 +5300,7 @@
   // optional string extendee = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->extendee().data(), this->extendee().length(),
+      this->extendee().data(), static_cast<int>(this->extendee().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.extendee");
     target =
@@ -4794,7 +5328,7 @@
   // optional string type_name = 6;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->type_name().data(), this->type_name().length(),
+      this->type_name().data(), static_cast<int>(this->type_name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.type_name");
     target =
@@ -4805,7 +5339,7 @@
   // optional string default_value = 7;
   if (cached_has_bits & 0x00000008u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->default_value().data(), this->default_value().length(),
+      this->default_value().data(), static_cast<int>(this->default_value().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.default_value");
     target =
@@ -4828,7 +5362,7 @@
   // optional string json_name = 10;
   if (cached_has_bits & 0x00000010u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->json_name().data(), this->json_name().length(),
+      this->json_name().data(), static_cast<int>(this->json_name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FieldDescriptorProto.json_name");
     target =
@@ -4838,7 +5372,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto)
   return target;
@@ -4851,7 +5385,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 255u) {
     // optional string name = 1;
@@ -5024,19 +5558,20 @@
   InternalSwap(other);
 }
 void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) {
+  using std::swap;
   name_.Swap(&other->name_);
   extendee_.Swap(&other->extendee_);
   type_name_.Swap(&other->type_name_);
   default_value_.Swap(&other->default_value_);
   json_name_.Swap(&other->json_name_);
-  std::swap(options_, other->options_);
-  std::swap(number_, other->number_);
-  std::swap(oneof_index_, other->oneof_index_);
-  std::swap(label_, other->label_);
-  std::swap(type_, other->type_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(number_, other->number_);
+  swap(oneof_index_, other->oneof_index_);
+  swap(label_, other->label_);
+  swap(type_, other->type_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata FieldDescriptorProto::GetMetadata() const {
@@ -5475,9 +6010,10 @@
   clear_has_options();
 }
 const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+  const ::google::protobuf::FieldOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::FieldOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::FieldOptions*>(
+      &::google::protobuf::_FieldOptions_default_instance_);
 }
 ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
   set_has_options();
@@ -5553,9 +6089,7 @@
 
 void OneofDescriptorProto::SharedDtor() {
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void OneofDescriptorProto::SetCachedSize(int size) const {
@@ -5583,12 +6117,17 @@
 
 void OneofDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto)
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_name()) {
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::OneofOptions::Clear();
     }
@@ -5610,11 +6149,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.OneofDescriptorProto.name");
         } else {
@@ -5626,7 +6165,7 @@
       // optional .google.protobuf.OneofOptions options = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -5637,13 +6176,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -5667,7 +6204,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.OneofDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -5682,13 +6219,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.OneofDescriptorProto)
 }
 
 ::google::protobuf::uint8* OneofDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -5697,7 +6235,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.OneofDescriptorProto.name");
     target =
@@ -5714,7 +6252,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto)
   return target;
@@ -5727,7 +6265,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 3u) {
     // optional string name = 1;
@@ -5812,11 +6350,12 @@
   InternalSwap(other);
 }
 void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) {
+  using std::swap;
   name_.Swap(&other->name_);
-  std::swap(options_, other->options_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata OneofDescriptorProto::GetMetadata() const {
@@ -5905,9 +6444,10 @@
   clear_has_options();
 }
 const ::google::protobuf::OneofOptions& OneofDescriptorProto::options() const {
+  const ::google::protobuf::OneofOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::OneofOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::OneofOptions*>(
+      &::google::protobuf::_OneofOptions_default_instance_);
 }
 ::google::protobuf::OneofOptions* OneofDescriptorProto::mutable_options() {
   set_has_options();
@@ -5985,9 +6525,7 @@
 
 void EnumDescriptorProto::SharedDtor() {
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void EnumDescriptorProto::SetCachedSize(int size) const {
@@ -6015,13 +6553,18 @@
 
 void EnumDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_name()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::EnumOptions::Clear();
     }
@@ -6043,11 +6586,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.EnumDescriptorProto.name");
         } else {
@@ -6059,7 +6602,7 @@
       // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_value()));
         } else {
@@ -6071,7 +6614,7 @@
       // optional .google.protobuf.EnumOptions options = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -6082,13 +6625,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -6112,7 +6653,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.EnumDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -6120,9 +6661,10 @@
   }
 
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
-  for (unsigned int i = 0, n = this->value_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->value_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->value(i), output);
+      2, this->value(static_cast<int>(i)), output);
   }
 
   // optional .google.protobuf.EnumOptions options = 3;
@@ -6133,13 +6675,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.EnumDescriptorProto)
 }
 
 ::google::protobuf::uint8* EnumDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -6148,7 +6691,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.EnumDescriptorProto.name");
     target =
@@ -6157,10 +6700,11 @@
   }
 
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
-  for (unsigned int i = 0, n = this->value_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->value_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->value(i), deterministic, target);
+        2, this->value(static_cast<int>(i)), deterministic, target);
   }
 
   // optional .google.protobuf.EnumOptions options = 3;
@@ -6172,7 +6716,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto)
   return target;
@@ -6185,16 +6729,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
   {
-    unsigned int count = this->value_size();
+    unsigned int count = static_cast<unsigned int>(this->value_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->value(i));
+          this->value(static_cast<int>(i)));
     }
   }
 
@@ -6283,12 +6827,13 @@
   InternalSwap(other);
 }
 void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) {
+  using std::swap;
   value_.InternalSwap(&other->value_);
   name_.Swap(&other->name_);
-  std::swap(options_, other->options_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata EnumDescriptorProto::GetMetadata() const {
@@ -6407,9 +6952,10 @@
   clear_has_options();
 }
 const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+  const ::google::protobuf::EnumOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::EnumOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::EnumOptions*>(
+      &::google::protobuf::_EnumOptions_default_instance_);
 }
 ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
   set_has_options();
@@ -6477,8 +7023,9 @@
 void EnumValueDescriptorProto::SharedCtor() {
   _cached_size_ = 0;
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, reinterpret_cast<char*>(&number_) -
-    reinterpret_cast<char*>(&options_) + sizeof(number_));
+  ::memset(&options_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&number_) -
+      reinterpret_cast<char*>(&options_)) + sizeof(number_));
 }
 
 EnumValueDescriptorProto::~EnumValueDescriptorProto() {
@@ -6488,9 +7035,7 @@
 
 void EnumValueDescriptorProto::SharedDtor() {
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void EnumValueDescriptorProto::SetCachedSize(int size) const {
@@ -6518,12 +7063,17 @@
 
 void EnumValueDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto)
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_name()) {
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::EnumValueOptions::Clear();
     }
@@ -6546,11 +7096,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.EnumValueDescriptorProto.name");
         } else {
@@ -6562,7 +7112,7 @@
       // optional int32 number = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_number();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -6576,7 +7126,7 @@
       // optional .google.protobuf.EnumValueOptions options = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -6587,13 +7137,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -6617,7 +7165,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.EnumValueDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -6637,13 +7185,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueDescriptorProto)
 }
 
 ::google::protobuf::uint8* EnumValueDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -6652,7 +7201,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.EnumValueDescriptorProto.name");
     target =
@@ -6674,7 +7223,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto)
   return target;
@@ -6687,7 +7236,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 7u) {
     // optional string name = 1;
@@ -6783,12 +7332,13 @@
   InternalSwap(other);
 }
 void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) {
+  using std::swap;
   name_.Swap(&other->name_);
-  std::swap(options_, other->options_);
-  std::swap(number_, other->number_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(number_, other->number_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata EnumValueDescriptorProto::GetMetadata() const {
@@ -6901,9 +7451,10 @@
   clear_has_options();
 }
 const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+  const ::google::protobuf::EnumValueOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::EnumValueOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::EnumValueOptions*>(
+      &::google::protobuf::_EnumValueOptions_default_instance_);
 }
 ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
   set_has_options();
@@ -6981,9 +7532,7 @@
 
 void ServiceDescriptorProto::SharedDtor() {
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void ServiceDescriptorProto::SetCachedSize(int size) const {
@@ -7011,13 +7560,18 @@
 
 void ServiceDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   method_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_name()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::ServiceOptions::Clear();
     }
@@ -7039,11 +7593,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.ServiceDescriptorProto.name");
         } else {
@@ -7055,7 +7609,7 @@
       // repeated .google.protobuf.MethodDescriptorProto method = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_method()));
         } else {
@@ -7067,7 +7621,7 @@
       // optional .google.protobuf.ServiceOptions options = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -7078,13 +7632,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -7108,7 +7660,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.ServiceDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -7116,9 +7668,10 @@
   }
 
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
-  for (unsigned int i = 0, n = this->method_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->method_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->method(i), output);
+      2, this->method(static_cast<int>(i)), output);
   }
 
   // optional .google.protobuf.ServiceOptions options = 3;
@@ -7129,13 +7682,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceDescriptorProto)
 }
 
 ::google::protobuf::uint8* ServiceDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -7144,7 +7698,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.ServiceDescriptorProto.name");
     target =
@@ -7153,10 +7707,11 @@
   }
 
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
-  for (unsigned int i = 0, n = this->method_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->method_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->method(i), deterministic, target);
+        2, this->method(static_cast<int>(i)), deterministic, target);
   }
 
   // optional .google.protobuf.ServiceOptions options = 3;
@@ -7168,7 +7723,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto)
   return target;
@@ -7181,16 +7736,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.MethodDescriptorProto method = 2;
   {
-    unsigned int count = this->method_size();
+    unsigned int count = static_cast<unsigned int>(this->method_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->method(i));
+          this->method(static_cast<int>(i)));
     }
   }
 
@@ -7279,12 +7834,13 @@
   InternalSwap(other);
 }
 void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) {
+  using std::swap;
   method_.InternalSwap(&other->method_);
   name_.Swap(&other->name_);
-  std::swap(options_, other->options_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata ServiceDescriptorProto::GetMetadata() const {
@@ -7403,9 +7959,10 @@
   clear_has_options();
 }
 const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+  const ::google::protobuf::ServiceOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::ServiceOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::ServiceOptions*>(
+      &::google::protobuf::_ServiceOptions_default_instance_);
 }
 ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
   set_has_options();
@@ -7478,8 +8035,8 @@
     options_ = NULL;
   }
   ::memcpy(&client_streaming_, &from.client_streaming_,
-    reinterpret_cast<char*>(&server_streaming_) -
-    reinterpret_cast<char*>(&client_streaming_) + sizeof(server_streaming_));
+    static_cast<size_t>(reinterpret_cast<char*>(&server_streaming_) -
+    reinterpret_cast<char*>(&client_streaming_)) + sizeof(server_streaming_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto)
 }
 
@@ -7488,8 +8045,9 @@
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   input_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   output_type_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&options_, 0, reinterpret_cast<char*>(&server_streaming_) -
-    reinterpret_cast<char*>(&options_) + sizeof(server_streaming_));
+  ::memset(&options_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&server_streaming_) -
+      reinterpret_cast<char*>(&options_)) + sizeof(server_streaming_));
 }
 
 MethodDescriptorProto::~MethodDescriptorProto() {
@@ -7501,9 +8059,7 @@
   name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   input_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   output_type_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  if (this != internal_default_instance()) {
-    delete options_;
-  }
+  if (this != internal_default_instance()) delete options_;
 }
 
 void MethodDescriptorProto::SetCachedSize(int size) const {
@@ -7531,27 +8087,33 @@
 
 void MethodDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto)
-  if (_has_bits_[0 / 32] & 15u) {
-    if (has_name()) {
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 15u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!name_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*name_.UnsafeRawStringPointer())->clear();
     }
-    if (has_input_type()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!input_type_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*input_type_.UnsafeRawStringPointer())->clear();
     }
-    if (has_output_type()) {
+    if (cached_has_bits & 0x00000004u) {
       GOOGLE_DCHECK(!output_type_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*output_type_.UnsafeRawStringPointer())->clear();
     }
-    if (has_options()) {
+    if (cached_has_bits & 0x00000008u) {
       GOOGLE_DCHECK(options_ != NULL);
       options_->::google::protobuf::MethodOptions::Clear();
     }
   }
-  if (_has_bits_[0 / 32] & 48u) {
-    ::memset(&client_streaming_, 0, reinterpret_cast<char*>(&server_streaming_) -
-      reinterpret_cast<char*>(&client_streaming_) + sizeof(server_streaming_));
+  if (cached_has_bits & 48u) {
+    ::memset(&client_streaming_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&server_streaming_) -
+        reinterpret_cast<char*>(&client_streaming_)) + sizeof(server_streaming_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -7570,11 +8132,11 @@
       // optional string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.MethodDescriptorProto.name");
         } else {
@@ -7586,11 +8148,11 @@
       // optional string input_type = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_input_type()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->input_type().data(), this->input_type().length(),
+            this->input_type().data(), static_cast<int>(this->input_type().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.MethodDescriptorProto.input_type");
         } else {
@@ -7602,11 +8164,11 @@
       // optional string output_type = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_output_type()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->output_type().data(), this->output_type().length(),
+            this->output_type().data(), static_cast<int>(this->output_type().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.MethodDescriptorProto.output_type");
         } else {
@@ -7618,7 +8180,7 @@
       // optional .google.protobuf.MethodOptions options = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_options()));
         } else {
@@ -7630,7 +8192,7 @@
       // optional bool client_streaming = 5 [default = false];
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(40u)) {
+            static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
           set_has_client_streaming();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -7644,7 +8206,7 @@
       // optional bool server_streaming = 6 [default = false];
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(48u)) {
+            static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) {
           set_has_server_streaming();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -7657,13 +8219,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -7687,7 +8247,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.MethodDescriptorProto.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -7697,7 +8257,7 @@
   // optional string input_type = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->input_type().data(), this->input_type().length(),
+      this->input_type().data(), static_cast<int>(this->input_type().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.MethodDescriptorProto.input_type");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -7707,7 +8267,7 @@
   // optional string output_type = 3;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->output_type().data(), this->output_type().length(),
+      this->output_type().data(), static_cast<int>(this->output_type().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.MethodDescriptorProto.output_type");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -7732,13 +8292,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.MethodDescriptorProto)
 }
 
 ::google::protobuf::uint8* MethodDescriptorProto::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -7747,7 +8308,7 @@
   // optional string name = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.MethodDescriptorProto.name");
     target =
@@ -7758,7 +8319,7 @@
   // optional string input_type = 2;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->input_type().data(), this->input_type().length(),
+      this->input_type().data(), static_cast<int>(this->input_type().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.MethodDescriptorProto.input_type");
     target =
@@ -7769,7 +8330,7 @@
   // optional string output_type = 3;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->output_type().data(), this->output_type().length(),
+      this->output_type().data(), static_cast<int>(this->output_type().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.MethodDescriptorProto.output_type");
     target =
@@ -7796,7 +8357,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto)
   return target;
@@ -7809,7 +8370,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (_has_bits_[0 / 32] & 63u) {
     // optional string name = 1;
@@ -7933,15 +8494,16 @@
   InternalSwap(other);
 }
 void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) {
+  using std::swap;
   name_.Swap(&other->name_);
   input_type_.Swap(&other->input_type_);
   output_type_.Swap(&other->output_type_);
-  std::swap(options_, other->options_);
-  std::swap(client_streaming_, other->client_streaming_);
-  std::swap(server_streaming_, other->server_streaming_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(options_, other->options_);
+  swap(client_streaming_, other->client_streaming_);
+  swap(server_streaming_, other->server_streaming_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata MethodDescriptorProto::GetMetadata() const {
@@ -8156,9 +8718,10 @@
   clear_has_options();
 }
 const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+  const ::google::protobuf::MethodOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::MethodOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::MethodOptions*>(
+      &::google::protobuf::_MethodOptions_default_instance_);
 }
 ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
   set_has_options();
@@ -8249,12 +8812,14 @@
 const int FileOptions::kCcGenericServicesFieldNumber;
 const int FileOptions::kJavaGenericServicesFieldNumber;
 const int FileOptions::kPyGenericServicesFieldNumber;
+const int FileOptions::kPhpGenericServicesFieldNumber;
 const int FileOptions::kDeprecatedFieldNumber;
 const int FileOptions::kCcEnableArenasFieldNumber;
 const int FileOptions::kObjcClassPrefixFieldNumber;
 const int FileOptions::kCsharpNamespaceFieldNumber;
 const int FileOptions::kSwiftPrefixFieldNumber;
 const int FileOptions::kPhpClassPrefixFieldNumber;
+const int FileOptions::kPhpNamespaceFieldNumber;
 const int FileOptions::kUninterpretedOptionFieldNumber;
 #endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
 
@@ -8302,9 +8867,13 @@
   if (from.has_php_class_prefix()) {
     php_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_class_prefix_);
   }
+  php_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  if (from.has_php_namespace()) {
+    php_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_namespace_);
+  }
   ::memcpy(&java_multiple_files_, &from.java_multiple_files_,
-    reinterpret_cast<char*>(&optimize_for_) -
-    reinterpret_cast<char*>(&java_multiple_files_) + sizeof(optimize_for_));
+    static_cast<size_t>(reinterpret_cast<char*>(&optimize_for_) -
+    reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(optimize_for_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions)
 }
 
@@ -8317,8 +8886,10 @@
   csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   swift_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   php_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&java_multiple_files_, 0, reinterpret_cast<char*>(&cc_enable_arenas_) -
-    reinterpret_cast<char*>(&java_multiple_files_) + sizeof(cc_enable_arenas_));
+  php_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  ::memset(&java_multiple_files_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&cc_enable_arenas_) -
+      reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(cc_enable_arenas_));
   optimize_for_ = 1;
 }
 
@@ -8335,6 +8906,7 @@
   csharp_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   swift_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   php_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  php_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
 }
 
 void FileOptions::SetCachedSize(int size) const {
@@ -8362,42 +8934,54 @@
 
 void FileOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
-  if (_has_bits_[0 / 32] & 127u) {
-    if (has_java_package()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 255u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!java_package_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*java_package_.UnsafeRawStringPointer())->clear();
     }
-    if (has_java_outer_classname()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!java_outer_classname_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*java_outer_classname_.UnsafeRawStringPointer())->clear();
     }
-    if (has_go_package()) {
+    if (cached_has_bits & 0x00000004u) {
       GOOGLE_DCHECK(!go_package_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*go_package_.UnsafeRawStringPointer())->clear();
     }
-    if (has_objc_class_prefix()) {
+    if (cached_has_bits & 0x00000008u) {
       GOOGLE_DCHECK(!objc_class_prefix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*objc_class_prefix_.UnsafeRawStringPointer())->clear();
     }
-    if (has_csharp_namespace()) {
+    if (cached_has_bits & 0x00000010u) {
       GOOGLE_DCHECK(!csharp_namespace_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*csharp_namespace_.UnsafeRawStringPointer())->clear();
     }
-    if (has_swift_prefix()) {
+    if (cached_has_bits & 0x00000020u) {
       GOOGLE_DCHECK(!swift_prefix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*swift_prefix_.UnsafeRawStringPointer())->clear();
     }
-    if (has_php_class_prefix()) {
+    if (cached_has_bits & 0x00000040u) {
       GOOGLE_DCHECK(!php_class_prefix_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*php_class_prefix_.UnsafeRawStringPointer())->clear();
     }
+    if (cached_has_bits & 0x00000080u) {
+      GOOGLE_DCHECK(!php_namespace_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
+      (*php_namespace_.UnsafeRawStringPointer())->clear();
+    }
   }
-  java_multiple_files_ = false;
-  if (_has_bits_[8 / 32] & 65280u) {
-    ::memset(&java_generate_equals_and_hash_, 0, reinterpret_cast<char*>(&cc_enable_arenas_) -
-      reinterpret_cast<char*>(&java_generate_equals_and_hash_) + sizeof(cc_enable_arenas_));
+  if (cached_has_bits & 65280u) {
+    ::memset(&java_multiple_files_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&deprecated_) -
+        reinterpret_cast<char*>(&java_multiple_files_)) + sizeof(deprecated_));
+  }
+  if (cached_has_bits & 196608u) {
+    cc_enable_arenas_ = false;
     optimize_for_ = 1;
   }
   _has_bits_.Clear();
@@ -8417,11 +9001,11 @@
       // optional string java_package = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_java_package()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->java_package().data(), this->java_package().length(),
+            this->java_package().data(), static_cast<int>(this->java_package().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.java_package");
         } else {
@@ -8433,11 +9017,11 @@
       // optional string java_outer_classname = 8;
       case 8: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(66u)) {
+            static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_java_outer_classname()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->java_outer_classname().data(), this->java_outer_classname().length(),
+            this->java_outer_classname().data(), static_cast<int>(this->java_outer_classname().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.java_outer_classname");
         } else {
@@ -8449,7 +9033,7 @@
       // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
       case 9: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(72u)) {
+            static_cast< ::google::protobuf::uint8>(72u /* 72 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -8457,7 +9041,8 @@
           if (::google::protobuf::FileOptions_OptimizeMode_IsValid(value)) {
             set_optimize_for(static_cast< ::google::protobuf::FileOptions_OptimizeMode >(value));
           } else {
-            mutable_unknown_fields()->AddVarint(9, value);
+            mutable_unknown_fields()->AddVarint(
+                9, static_cast< ::google::protobuf::uint64>(value));
           }
         } else {
           goto handle_unusual;
@@ -8468,7 +9053,7 @@
       // optional bool java_multiple_files = 10 [default = false];
       case 10: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(80u)) {
+            static_cast< ::google::protobuf::uint8>(80u /* 80 & 0xFF */)) {
           set_has_java_multiple_files();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8482,11 +9067,11 @@
       // optional string go_package = 11;
       case 11: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(90u)) {
+            static_cast< ::google::protobuf::uint8>(90u /* 90 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_go_package()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->go_package().data(), this->go_package().length(),
+            this->go_package().data(), static_cast<int>(this->go_package().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.go_package");
         } else {
@@ -8498,7 +9083,7 @@
       // optional bool cc_generic_services = 16 [default = false];
       case 16: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(128u)) {
+            static_cast< ::google::protobuf::uint8>(128u /* 128 & 0xFF */)) {
           set_has_cc_generic_services();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8512,7 +9097,7 @@
       // optional bool java_generic_services = 17 [default = false];
       case 17: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(136u)) {
+            static_cast< ::google::protobuf::uint8>(136u /* 136 & 0xFF */)) {
           set_has_java_generic_services();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8526,7 +9111,7 @@
       // optional bool py_generic_services = 18 [default = false];
       case 18: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(144u)) {
+            static_cast< ::google::protobuf::uint8>(144u /* 144 & 0xFF */)) {
           set_has_py_generic_services();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8537,10 +9122,24 @@
         break;
       }
 
+      // optional bool php_generic_services = 19 [default = false];
+      case 19: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(152u /* 152 & 0xFF */)) {
+          set_has_php_generic_services();
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &php_generic_services_)));
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
       // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
       case 20: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(160u)) {
+            static_cast< ::google::protobuf::uint8>(160u /* 160 & 0xFF */)) {
           set_has_java_generate_equals_and_hash();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8554,7 +9153,7 @@
       // optional bool deprecated = 23 [default = false];
       case 23: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(184u)) {
+            static_cast< ::google::protobuf::uint8>(184u /* 184 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8568,7 +9167,7 @@
       // optional bool java_string_check_utf8 = 27 [default = false];
       case 27: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(216u)) {
+            static_cast< ::google::protobuf::uint8>(216u /* 216 & 0xFF */)) {
           set_has_java_string_check_utf8();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8582,7 +9181,7 @@
       // optional bool cc_enable_arenas = 31 [default = false];
       case 31: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(248u)) {
+            static_cast< ::google::protobuf::uint8>(248u /* 248 & 0xFF */)) {
           set_has_cc_enable_arenas();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -8596,11 +9195,11 @@
       // optional string objc_class_prefix = 36;
       case 36: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(290u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 290 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_objc_class_prefix()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+            this->objc_class_prefix().data(), static_cast<int>(this->objc_class_prefix().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.objc_class_prefix");
         } else {
@@ -8612,11 +9211,11 @@
       // optional string csharp_namespace = 37;
       case 37: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(298u)) {
+            static_cast< ::google::protobuf::uint8>(42u /* 298 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_csharp_namespace()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->csharp_namespace().data(), this->csharp_namespace().length(),
+            this->csharp_namespace().data(), static_cast<int>(this->csharp_namespace().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.csharp_namespace");
         } else {
@@ -8628,11 +9227,11 @@
       // optional string swift_prefix = 39;
       case 39: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(314u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 314 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_swift_prefix()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->swift_prefix().data(), this->swift_prefix().length(),
+            this->swift_prefix().data(), static_cast<int>(this->swift_prefix().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.swift_prefix");
         } else {
@@ -8644,11 +9243,11 @@
       // optional string php_class_prefix = 40;
       case 40: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(322u)) {
+            static_cast< ::google::protobuf::uint8>(66u /* 322 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_php_class_prefix()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->php_class_prefix().data(), this->php_class_prefix().length(),
+            this->php_class_prefix().data(), static_cast<int>(this->php_class_prefix().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.FileOptions.php_class_prefix");
         } else {
@@ -8657,10 +9256,26 @@
         break;
       }
 
+      // optional string php_namespace = 41;
+      case 41: {
+        if (static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(74u /* 330 & 0xFF */)) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_php_namespace()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+            this->php_namespace().data(), static_cast<int>(this->php_namespace().length()),
+            ::google::protobuf::internal::WireFormat::PARSE,
+            "google.protobuf.FileOptions.php_namespace");
+        } else {
+          goto handle_unusual;
+        }
+        break;
+      }
+
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -8671,18 +9286,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -8706,7 +9320,7 @@
   // optional string java_package = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->java_package().data(), this->java_package().length(),
+      this->java_package().data(), static_cast<int>(this->java_package().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.java_package");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -8716,7 +9330,7 @@
   // optional string java_outer_classname = 8;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->java_outer_classname().data(), this->java_outer_classname().length(),
+      this->java_outer_classname().data(), static_cast<int>(this->java_outer_classname().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.java_outer_classname");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -8724,20 +9338,20 @@
   }
 
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  if (cached_has_bits & 0x00008000u) {
+  if (cached_has_bits & 0x00020000u) {
     ::google::protobuf::internal::WireFormatLite::WriteEnum(
       9, this->optimize_for(), output);
   }
 
   // optional bool java_multiple_files = 10 [default = false];
-  if (cached_has_bits & 0x00000080u) {
+  if (cached_has_bits & 0x00000100u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->java_multiple_files(), output);
   }
 
   // optional string go_package = 11;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->go_package().data(), this->go_package().length(),
+      this->go_package().data(), static_cast<int>(this->go_package().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.go_package");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -8745,44 +9359,49 @@
   }
 
   // optional bool cc_generic_services = 16 [default = false];
-  if (cached_has_bits & 0x00000400u) {
+  if (cached_has_bits & 0x00000800u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(16, this->cc_generic_services(), output);
   }
 
   // optional bool java_generic_services = 17 [default = false];
-  if (cached_has_bits & 0x00000800u) {
+  if (cached_has_bits & 0x00001000u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(17, this->java_generic_services(), output);
   }
 
   // optional bool py_generic_services = 18 [default = false];
-  if (cached_has_bits & 0x00001000u) {
+  if (cached_has_bits & 0x00002000u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(18, this->py_generic_services(), output);
   }
 
+  // optional bool php_generic_services = 19 [default = false];
+  if (cached_has_bits & 0x00004000u) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(19, this->php_generic_services(), output);
+  }
+
   // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
-  if (cached_has_bits & 0x00000100u) {
+  if (cached_has_bits & 0x00000200u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output);
   }
 
   // optional bool deprecated = 23 [default = false];
-  if (cached_has_bits & 0x00002000u) {
+  if (cached_has_bits & 0x00008000u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(23, this->deprecated(), output);
   }
 
   // optional bool java_string_check_utf8 = 27 [default = false];
-  if (cached_has_bits & 0x00000200u) {
+  if (cached_has_bits & 0x00000400u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(27, this->java_string_check_utf8(), output);
   }
 
   // optional bool cc_enable_arenas = 31 [default = false];
-  if (cached_has_bits & 0x00004000u) {
+  if (cached_has_bits & 0x00010000u) {
     ::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output);
   }
 
   // optional string objc_class_prefix = 36;
   if (cached_has_bits & 0x00000008u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+      this->objc_class_prefix().data(), static_cast<int>(this->objc_class_prefix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.objc_class_prefix");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -8792,7 +9411,7 @@
   // optional string csharp_namespace = 37;
   if (cached_has_bits & 0x00000010u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->csharp_namespace().data(), this->csharp_namespace().length(),
+      this->csharp_namespace().data(), static_cast<int>(this->csharp_namespace().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.csharp_namespace");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -8802,7 +9421,7 @@
   // optional string swift_prefix = 39;
   if (cached_has_bits & 0x00000020u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->swift_prefix().data(), this->swift_prefix().length(),
+      this->swift_prefix().data(), static_cast<int>(this->swift_prefix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.swift_prefix");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -8812,17 +9431,28 @@
   // optional string php_class_prefix = 40;
   if (cached_has_bits & 0x00000040u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->php_class_prefix().data(), this->php_class_prefix().length(),
+      this->php_class_prefix().data(), static_cast<int>(this->php_class_prefix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.php_class_prefix");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
       40, this->php_class_prefix(), output);
   }
 
+  // optional string php_namespace = 41;
+  if (cached_has_bits & 0x00000080u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->php_namespace().data(), static_cast<int>(this->php_namespace().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.php_namespace");
+    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
+      41, this->php_namespace(), output);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -8831,13 +9461,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FileOptions)
 }
 
 ::google::protobuf::uint8* FileOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -8846,7 +9477,7 @@
   // optional string java_package = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->java_package().data(), this->java_package().length(),
+      this->java_package().data(), static_cast<int>(this->java_package().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.java_package");
     target =
@@ -8857,7 +9488,7 @@
   // optional string java_outer_classname = 8;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->java_outer_classname().data(), this->java_outer_classname().length(),
+      this->java_outer_classname().data(), static_cast<int>(this->java_outer_classname().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.java_outer_classname");
     target =
@@ -8866,20 +9497,20 @@
   }
 
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-  if (cached_has_bits & 0x00008000u) {
+  if (cached_has_bits & 0x00020000u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
       9, this->optimize_for(), target);
   }
 
   // optional bool java_multiple_files = 10 [default = false];
-  if (cached_has_bits & 0x00000080u) {
+  if (cached_has_bits & 0x00000100u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->java_multiple_files(), target);
   }
 
   // optional string go_package = 11;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->go_package().data(), this->go_package().length(),
+      this->go_package().data(), static_cast<int>(this->go_package().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.go_package");
     target =
@@ -8888,44 +9519,49 @@
   }
 
   // optional bool cc_generic_services = 16 [default = false];
-  if (cached_has_bits & 0x00000400u) {
+  if (cached_has_bits & 0x00000800u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(16, this->cc_generic_services(), target);
   }
 
   // optional bool java_generic_services = 17 [default = false];
-  if (cached_has_bits & 0x00000800u) {
+  if (cached_has_bits & 0x00001000u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(17, this->java_generic_services(), target);
   }
 
   // optional bool py_generic_services = 18 [default = false];
-  if (cached_has_bits & 0x00001000u) {
+  if (cached_has_bits & 0x00002000u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(18, this->py_generic_services(), target);
   }
 
+  // optional bool php_generic_services = 19 [default = false];
+  if (cached_has_bits & 0x00004000u) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(19, this->php_generic_services(), target);
+  }
+
   // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
-  if (cached_has_bits & 0x00000100u) {
+  if (cached_has_bits & 0x00000200u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target);
   }
 
   // optional bool deprecated = 23 [default = false];
-  if (cached_has_bits & 0x00002000u) {
+  if (cached_has_bits & 0x00008000u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(23, this->deprecated(), target);
   }
 
   // optional bool java_string_check_utf8 = 27 [default = false];
-  if (cached_has_bits & 0x00000200u) {
+  if (cached_has_bits & 0x00000400u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(27, this->java_string_check_utf8(), target);
   }
 
   // optional bool cc_enable_arenas = 31 [default = false];
-  if (cached_has_bits & 0x00004000u) {
+  if (cached_has_bits & 0x00010000u) {
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target);
   }
 
   // optional string objc_class_prefix = 36;
   if (cached_has_bits & 0x00000008u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->objc_class_prefix().data(), this->objc_class_prefix().length(),
+      this->objc_class_prefix().data(), static_cast<int>(this->objc_class_prefix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.objc_class_prefix");
     target =
@@ -8936,7 +9572,7 @@
   // optional string csharp_namespace = 37;
   if (cached_has_bits & 0x00000010u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->csharp_namespace().data(), this->csharp_namespace().length(),
+      this->csharp_namespace().data(), static_cast<int>(this->csharp_namespace().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.csharp_namespace");
     target =
@@ -8947,7 +9583,7 @@
   // optional string swift_prefix = 39;
   if (cached_has_bits & 0x00000020u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->swift_prefix().data(), this->swift_prefix().length(),
+      this->swift_prefix().data(), static_cast<int>(this->swift_prefix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.swift_prefix");
     target =
@@ -8958,7 +9594,7 @@
   // optional string php_class_prefix = 40;
   if (cached_has_bits & 0x00000040u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->php_class_prefix().data(), this->php_class_prefix().length(),
+      this->php_class_prefix().data(), static_cast<int>(this->php_class_prefix().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.FileOptions.php_class_prefix");
     target =
@@ -8966,11 +9602,23 @@
         40, this->php_class_prefix(), target);
   }
 
+  // optional string php_namespace = 41;
+  if (cached_has_bits & 0x00000080u) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->php_namespace().data(), static_cast<int>(this->php_namespace().length()),
+      ::google::protobuf::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileOptions.php_namespace");
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        41, this->php_namespace(), target);
+  }
+
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -8979,7 +9627,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions)
   return target;
@@ -8994,16 +9642,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -9057,13 +9705,20 @@
           this->php_class_prefix());
     }
 
+    // optional string php_namespace = 41;
+    if (has_php_namespace()) {
+      total_size += 2 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->php_namespace());
+    }
+
+  }
+  if (_has_bits_[8 / 32] & 65280u) {
     // optional bool java_multiple_files = 10 [default = false];
     if (has_java_multiple_files()) {
       total_size += 1 + 1;
     }
 
-  }
-  if (_has_bits_[8 / 32] & 65280u) {
     // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
     if (has_java_generate_equals_and_hash()) {
       total_size += 2 + 1;
@@ -9089,11 +9744,18 @@
       total_size += 2 + 1;
     }
 
+    // optional bool php_generic_services = 19 [default = false];
+    if (has_php_generic_services()) {
+      total_size += 2 + 1;
+    }
+
     // optional bool deprecated = 23 [default = false];
     if (has_deprecated()) {
       total_size += 2 + 1;
     }
 
+  }
+  if (_has_bits_[16 / 32] & 196608u) {
     // optional bool cc_enable_arenas = 31 [default = false];
     if (has_cc_enable_arenas()) {
       total_size += 2 + 1;
@@ -9168,33 +9830,42 @@
       php_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_class_prefix_);
     }
     if (cached_has_bits & 0x00000080u) {
-      java_multiple_files_ = from.java_multiple_files_;
+      set_has_php_namespace();
+      php_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.php_namespace_);
     }
-    _has_bits_[0] |= cached_has_bits;
   }
   if (cached_has_bits & 65280u) {
     if (cached_has_bits & 0x00000100u) {
-      java_generate_equals_and_hash_ = from.java_generate_equals_and_hash_;
+      java_multiple_files_ = from.java_multiple_files_;
     }
     if (cached_has_bits & 0x00000200u) {
-      java_string_check_utf8_ = from.java_string_check_utf8_;
+      java_generate_equals_and_hash_ = from.java_generate_equals_and_hash_;
     }
     if (cached_has_bits & 0x00000400u) {
-      cc_generic_services_ = from.cc_generic_services_;
+      java_string_check_utf8_ = from.java_string_check_utf8_;
     }
     if (cached_has_bits & 0x00000800u) {
-      java_generic_services_ = from.java_generic_services_;
+      cc_generic_services_ = from.cc_generic_services_;
     }
     if (cached_has_bits & 0x00001000u) {
-      py_generic_services_ = from.py_generic_services_;
+      java_generic_services_ = from.java_generic_services_;
     }
     if (cached_has_bits & 0x00002000u) {
-      deprecated_ = from.deprecated_;
+      py_generic_services_ = from.py_generic_services_;
     }
     if (cached_has_bits & 0x00004000u) {
-      cc_enable_arenas_ = from.cc_enable_arenas_;
+      php_generic_services_ = from.php_generic_services_;
     }
     if (cached_has_bits & 0x00008000u) {
+      deprecated_ = from.deprecated_;
+    }
+    _has_bits_[0] |= cached_has_bits;
+  }
+  if (cached_has_bits & 196608u) {
+    if (cached_has_bits & 0x00010000u) {
+      cc_enable_arenas_ = from.cc_enable_arenas_;
+    }
+    if (cached_has_bits & 0x00020000u) {
       optimize_for_ = from.optimize_for_;
     }
     _has_bits_[0] |= cached_has_bits;
@@ -9229,6 +9900,7 @@
   InternalSwap(other);
 }
 void FileOptions::InternalSwap(FileOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
   java_package_.Swap(&other->java_package_);
   java_outer_classname_.Swap(&other->java_outer_classname_);
@@ -9237,18 +9909,20 @@
   csharp_namespace_.Swap(&other->csharp_namespace_);
   swift_prefix_.Swap(&other->swift_prefix_);
   php_class_prefix_.Swap(&other->php_class_prefix_);
-  std::swap(java_multiple_files_, other->java_multiple_files_);
-  std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
-  std::swap(java_string_check_utf8_, other->java_string_check_utf8_);
-  std::swap(cc_generic_services_, other->cc_generic_services_);
-  std::swap(java_generic_services_, other->java_generic_services_);
-  std::swap(py_generic_services_, other->py_generic_services_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(cc_enable_arenas_, other->cc_enable_arenas_);
-  std::swap(optimize_for_, other->optimize_for_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  php_namespace_.Swap(&other->php_namespace_);
+  swap(java_multiple_files_, other->java_multiple_files_);
+  swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_);
+  swap(java_string_check_utf8_, other->java_string_check_utf8_);
+  swap(cc_generic_services_, other->cc_generic_services_);
+  swap(java_generic_services_, other->java_generic_services_);
+  swap(py_generic_services_, other->py_generic_services_);
+  swap(php_generic_services_, other->php_generic_services_);
+  swap(deprecated_, other->deprecated_);
+  swap(cc_enable_arenas_, other->cc_enable_arenas_);
+  swap(optimize_for_, other->optimize_for_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -9388,13 +10062,13 @@
 
 // optional bool java_multiple_files = 10 [default = false];
 bool FileOptions::has_java_multiple_files() const {
-  return (_has_bits_[0] & 0x00000080u) != 0;
+  return (_has_bits_[0] & 0x00000100u) != 0;
 }
 void FileOptions::set_has_java_multiple_files() {
-  _has_bits_[0] |= 0x00000080u;
+  _has_bits_[0] |= 0x00000100u;
 }
 void FileOptions::clear_has_java_multiple_files() {
-  _has_bits_[0] &= ~0x00000080u;
+  _has_bits_[0] &= ~0x00000100u;
 }
 void FileOptions::clear_java_multiple_files() {
   java_multiple_files_ = false;
@@ -9412,13 +10086,13 @@
 
 // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
 bool FileOptions::has_java_generate_equals_and_hash() const {
-  return (_has_bits_[0] & 0x00000100u) != 0;
+  return (_has_bits_[0] & 0x00000200u) != 0;
 }
 void FileOptions::set_has_java_generate_equals_and_hash() {
-  _has_bits_[0] |= 0x00000100u;
+  _has_bits_[0] |= 0x00000200u;
 }
 void FileOptions::clear_has_java_generate_equals_and_hash() {
-  _has_bits_[0] &= ~0x00000100u;
+  _has_bits_[0] &= ~0x00000200u;
 }
 void FileOptions::clear_java_generate_equals_and_hash() {
   java_generate_equals_and_hash_ = false;
@@ -9436,13 +10110,13 @@
 
 // optional bool java_string_check_utf8 = 27 [default = false];
 bool FileOptions::has_java_string_check_utf8() const {
-  return (_has_bits_[0] & 0x00000200u) != 0;
+  return (_has_bits_[0] & 0x00000400u) != 0;
 }
 void FileOptions::set_has_java_string_check_utf8() {
-  _has_bits_[0] |= 0x00000200u;
+  _has_bits_[0] |= 0x00000400u;
 }
 void FileOptions::clear_has_java_string_check_utf8() {
-  _has_bits_[0] &= ~0x00000200u;
+  _has_bits_[0] &= ~0x00000400u;
 }
 void FileOptions::clear_java_string_check_utf8() {
   java_string_check_utf8_ = false;
@@ -9460,13 +10134,13 @@
 
 // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
 bool FileOptions::has_optimize_for() const {
-  return (_has_bits_[0] & 0x00008000u) != 0;
+  return (_has_bits_[0] & 0x00020000u) != 0;
 }
 void FileOptions::set_has_optimize_for() {
-  _has_bits_[0] |= 0x00008000u;
+  _has_bits_[0] |= 0x00020000u;
 }
 void FileOptions::clear_has_optimize_for() {
-  _has_bits_[0] &= ~0x00008000u;
+  _has_bits_[0] &= ~0x00020000u;
 }
 void FileOptions::clear_optimize_for() {
   optimize_for_ = 1;
@@ -9548,13 +10222,13 @@
 
 // optional bool cc_generic_services = 16 [default = false];
 bool FileOptions::has_cc_generic_services() const {
-  return (_has_bits_[0] & 0x00000400u) != 0;
+  return (_has_bits_[0] & 0x00000800u) != 0;
 }
 void FileOptions::set_has_cc_generic_services() {
-  _has_bits_[0] |= 0x00000400u;
+  _has_bits_[0] |= 0x00000800u;
 }
 void FileOptions::clear_has_cc_generic_services() {
-  _has_bits_[0] &= ~0x00000400u;
+  _has_bits_[0] &= ~0x00000800u;
 }
 void FileOptions::clear_cc_generic_services() {
   cc_generic_services_ = false;
@@ -9572,13 +10246,13 @@
 
 // optional bool java_generic_services = 17 [default = false];
 bool FileOptions::has_java_generic_services() const {
-  return (_has_bits_[0] & 0x00000800u) != 0;
+  return (_has_bits_[0] & 0x00001000u) != 0;
 }
 void FileOptions::set_has_java_generic_services() {
-  _has_bits_[0] |= 0x00000800u;
+  _has_bits_[0] |= 0x00001000u;
 }
 void FileOptions::clear_has_java_generic_services() {
-  _has_bits_[0] &= ~0x00000800u;
+  _has_bits_[0] &= ~0x00001000u;
 }
 void FileOptions::clear_java_generic_services() {
   java_generic_services_ = false;
@@ -9596,13 +10270,13 @@
 
 // optional bool py_generic_services = 18 [default = false];
 bool FileOptions::has_py_generic_services() const {
-  return (_has_bits_[0] & 0x00001000u) != 0;
+  return (_has_bits_[0] & 0x00002000u) != 0;
 }
 void FileOptions::set_has_py_generic_services() {
-  _has_bits_[0] |= 0x00001000u;
+  _has_bits_[0] |= 0x00002000u;
 }
 void FileOptions::clear_has_py_generic_services() {
-  _has_bits_[0] &= ~0x00001000u;
+  _has_bits_[0] &= ~0x00002000u;
 }
 void FileOptions::clear_py_generic_services() {
   py_generic_services_ = false;
@@ -9618,15 +10292,39 @@
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
 }
 
+// optional bool php_generic_services = 19 [default = false];
+bool FileOptions::has_php_generic_services() const {
+  return (_has_bits_[0] & 0x00004000u) != 0;
+}
+void FileOptions::set_has_php_generic_services() {
+  _has_bits_[0] |= 0x00004000u;
+}
+void FileOptions::clear_has_php_generic_services() {
+  _has_bits_[0] &= ~0x00004000u;
+}
+void FileOptions::clear_php_generic_services() {
+  php_generic_services_ = false;
+  clear_has_php_generic_services();
+}
+bool FileOptions::php_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_generic_services)
+  return php_generic_services_;
+}
+void FileOptions::set_php_generic_services(bool value) {
+  set_has_php_generic_services();
+  php_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_generic_services)
+}
+
 // optional bool deprecated = 23 [default = false];
 bool FileOptions::has_deprecated() const {
-  return (_has_bits_[0] & 0x00002000u) != 0;
+  return (_has_bits_[0] & 0x00008000u) != 0;
 }
 void FileOptions::set_has_deprecated() {
-  _has_bits_[0] |= 0x00002000u;
+  _has_bits_[0] |= 0x00008000u;
 }
 void FileOptions::clear_has_deprecated() {
-  _has_bits_[0] &= ~0x00002000u;
+  _has_bits_[0] &= ~0x00008000u;
 }
 void FileOptions::clear_deprecated() {
   deprecated_ = false;
@@ -9644,13 +10342,13 @@
 
 // optional bool cc_enable_arenas = 31 [default = false];
 bool FileOptions::has_cc_enable_arenas() const {
-  return (_has_bits_[0] & 0x00004000u) != 0;
+  return (_has_bits_[0] & 0x00010000u) != 0;
 }
 void FileOptions::set_has_cc_enable_arenas() {
-  _has_bits_[0] |= 0x00004000u;
+  _has_bits_[0] |= 0x00010000u;
 }
 void FileOptions::clear_has_cc_enable_arenas() {
-  _has_bits_[0] &= ~0x00004000u;
+  _has_bits_[0] &= ~0x00010000u;
 }
 void FileOptions::clear_cc_enable_arenas() {
   cc_enable_arenas_ = false;
@@ -9918,6 +10616,69 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix)
 }
 
+// optional string php_namespace = 41;
+bool FileOptions::has_php_namespace() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+void FileOptions::set_has_php_namespace() {
+  _has_bits_[0] |= 0x00000080u;
+}
+void FileOptions::clear_has_php_namespace() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+void FileOptions::clear_php_namespace() {
+  php_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_php_namespace();
+}
+const ::std::string& FileOptions::php_namespace() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace)
+  return php_namespace_.GetNoArena();
+}
+void FileOptions::set_php_namespace(const ::std::string& value) {
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace)
+}
+#if LANG_CXX11
+void FileOptions::set_php_namespace(::std::string&& value) {
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace)
+}
+#endif
+void FileOptions::set_php_namespace(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace)
+}
+void FileOptions::set_php_namespace(const char* value, size_t size) {
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace)
+}
+::std::string* FileOptions::mutable_php_namespace() {
+  set_has_php_namespace();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace)
+  return php_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+::std::string* FileOptions::release_php_namespace() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace)
+  clear_has_php_namespace();
+  return php_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+void FileOptions::set_allocated_php_namespace(::std::string* php_namespace) {
+  if (php_namespace != NULL) {
+    set_has_php_namespace();
+  } else {
+    clear_has_php_namespace();
+  }
+  php_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), php_namespace);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace)
+}
+
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 int FileOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
@@ -9977,15 +10738,16 @@
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   _extensions_.MergeFrom(from._extensions_);
   ::memcpy(&message_set_wire_format_, &from.message_set_wire_format_,
-    reinterpret_cast<char*>(&map_entry_) -
-    reinterpret_cast<char*>(&message_set_wire_format_) + sizeof(map_entry_));
+    static_cast<size_t>(reinterpret_cast<char*>(&map_entry_) -
+    reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions)
 }
 
 void MessageOptions::SharedCtor() {
   _cached_size_ = 0;
-  ::memset(&message_set_wire_format_, 0, reinterpret_cast<char*>(&map_entry_) -
-    reinterpret_cast<char*>(&message_set_wire_format_) + sizeof(map_entry_));
+  ::memset(&message_set_wire_format_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&map_entry_) -
+      reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
 }
 
 MessageOptions::~MessageOptions() {
@@ -10021,11 +10783,17 @@
 
 void MessageOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
-  if (_has_bits_[0 / 32] & 15u) {
-    ::memset(&message_set_wire_format_, 0, reinterpret_cast<char*>(&map_entry_) -
-      reinterpret_cast<char*>(&message_set_wire_format_) + sizeof(map_entry_));
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 15u) {
+    ::memset(&message_set_wire_format_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&map_entry_) -
+        reinterpret_cast<char*>(&message_set_wire_format_)) + sizeof(map_entry_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -10044,7 +10812,7 @@
       // optional bool message_set_wire_format = 1 [default = false];
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           set_has_message_set_wire_format();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10058,7 +10826,7 @@
       // optional bool no_standard_descriptor_accessor = 2 [default = false];
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_no_standard_descriptor_accessor();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10072,7 +10840,7 @@
       // optional bool deprecated = 3 [default = false];
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10086,7 +10854,7 @@
       // optional bool map_entry = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(56u)) {
+            static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) {
           set_has_map_entry();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10100,7 +10868,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -10111,18 +10879,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -10164,9 +10931,10 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -10175,13 +10943,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.MessageOptions)
 }
 
 ::google::protobuf::uint8* MessageOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -10208,10 +10977,11 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -10220,7 +10990,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions)
   return target;
@@ -10235,16 +11005,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -10347,14 +11117,15 @@
   InternalSwap(other);
 }
 void MessageOptions::InternalSwap(MessageOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(message_set_wire_format_, other->message_set_wire_format_);
-  std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(map_entry_, other->map_entry_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(message_set_wire_format_, other->message_set_wire_format_);
+  swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_);
+  swap(deprecated_, other->deprecated_);
+  swap(map_entry_, other->map_entry_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -10523,15 +11294,16 @@
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   _extensions_.MergeFrom(from._extensions_);
   ::memcpy(&ctype_, &from.ctype_,
-    reinterpret_cast<char*>(&jstype_) -
-    reinterpret_cast<char*>(&ctype_) + sizeof(jstype_));
+    static_cast<size_t>(reinterpret_cast<char*>(&jstype_) -
+    reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions)
 }
 
 void FieldOptions::SharedCtor() {
   _cached_size_ = 0;
-  ::memset(&ctype_, 0, reinterpret_cast<char*>(&jstype_) -
-    reinterpret_cast<char*>(&ctype_) + sizeof(jstype_));
+  ::memset(&ctype_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&jstype_) -
+      reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
 }
 
 FieldOptions::~FieldOptions() {
@@ -10567,11 +11339,17 @@
 
 void FieldOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
-  if (_has_bits_[0 / 32] & 63u) {
-    ::memset(&ctype_, 0, reinterpret_cast<char*>(&jstype_) -
-      reinterpret_cast<char*>(&ctype_) + sizeof(jstype_));
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 63u) {
+    ::memset(&ctype_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&jstype_) -
+        reinterpret_cast<char*>(&ctype_)) + sizeof(jstype_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -10590,7 +11368,7 @@
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -10598,7 +11376,8 @@
           if (::google::protobuf::FieldOptions_CType_IsValid(value)) {
             set_ctype(static_cast< ::google::protobuf::FieldOptions_CType >(value));
           } else {
-            mutable_unknown_fields()->AddVarint(1, value);
+            mutable_unknown_fields()->AddVarint(
+                1, static_cast< ::google::protobuf::uint64>(value));
           }
         } else {
           goto handle_unusual;
@@ -10609,7 +11388,7 @@
       // optional bool packed = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_packed();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10623,7 +11402,7 @@
       // optional bool deprecated = 3 [default = false];
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10637,7 +11416,7 @@
       // optional bool lazy = 5 [default = false];
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(40u)) {
+            static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
           set_has_lazy();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10651,7 +11430,7 @@
       // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(48u)) {
+            static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -10659,7 +11438,8 @@
           if (::google::protobuf::FieldOptions_JSType_IsValid(value)) {
             set_jstype(static_cast< ::google::protobuf::FieldOptions_JSType >(value));
           } else {
-            mutable_unknown_fields()->AddVarint(6, value);
+            mutable_unknown_fields()->AddVarint(
+                6, static_cast< ::google::protobuf::uint64>(value));
           }
         } else {
           goto handle_unusual;
@@ -10670,7 +11450,7 @@
       // optional bool weak = 10 [default = false];
       case 10: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(80u)) {
+            static_cast< ::google::protobuf::uint8>(80u /* 80 & 0xFF */)) {
           set_has_weak();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -10684,7 +11464,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -10695,18 +11475,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -10760,9 +11539,10 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -10771,13 +11551,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FieldOptions)
 }
 
 ::google::protobuf::uint8* FieldOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -10816,10 +11597,11 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -10828,7 +11610,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions)
   return target;
@@ -10843,16 +11625,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -10973,16 +11755,17 @@
   InternalSwap(other);
 }
 void FieldOptions::InternalSwap(FieldOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(ctype_, other->ctype_);
-  std::swap(packed_, other->packed_);
-  std::swap(lazy_, other->lazy_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(weak_, other->weak_);
-  std::swap(jstype_, other->jstype_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(ctype_, other->ctype_);
+  swap(packed_, other->packed_);
+  swap(lazy_, other->lazy_);
+  swap(deprecated_, other->deprecated_);
+  swap(weak_, other->weak_);
+  swap(jstype_, other->jstype_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -11234,6 +12017,10 @@
 
 void OneofOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
   _has_bits_.Clear();
@@ -11253,7 +12040,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -11264,18 +12051,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -11296,9 +12082,10 @@
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -11307,22 +12094,24 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.OneofOptions)
 }
 
 ::google::protobuf::uint8* OneofOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -11331,7 +12120,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofOptions)
   return target;
@@ -11346,16 +12135,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -11420,10 +12209,11 @@
   InternalSwap(other);
 }
 void OneofOptions::InternalSwap(OneofOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -11492,15 +12282,16 @@
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   _extensions_.MergeFrom(from._extensions_);
   ::memcpy(&allow_alias_, &from.allow_alias_,
-    reinterpret_cast<char*>(&deprecated_) -
-    reinterpret_cast<char*>(&allow_alias_) + sizeof(deprecated_));
+    static_cast<size_t>(reinterpret_cast<char*>(&deprecated_) -
+    reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions)
 }
 
 void EnumOptions::SharedCtor() {
   _cached_size_ = 0;
-  ::memset(&allow_alias_, 0, reinterpret_cast<char*>(&deprecated_) -
-    reinterpret_cast<char*>(&allow_alias_) + sizeof(deprecated_));
+  ::memset(&allow_alias_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&deprecated_) -
+      reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
 }
 
 EnumOptions::~EnumOptions() {
@@ -11536,11 +12327,17 @@
 
 void EnumOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    ::memset(&allow_alias_, 0, reinterpret_cast<char*>(&deprecated_) -
-      reinterpret_cast<char*>(&allow_alias_) + sizeof(deprecated_));
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    ::memset(&allow_alias_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&deprecated_) -
+        reinterpret_cast<char*>(&allow_alias_)) + sizeof(deprecated_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -11559,7 +12356,7 @@
       // optional bool allow_alias = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_allow_alias();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -11573,7 +12370,7 @@
       // optional bool deprecated = 3 [default = false];
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -11587,7 +12384,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -11598,18 +12395,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -11641,9 +12437,10 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -11652,13 +12449,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.EnumOptions)
 }
 
 ::google::protobuf::uint8* EnumOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -11675,10 +12473,11 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -11687,7 +12486,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions)
   return target;
@@ -11702,16 +12501,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -11798,12 +12597,13 @@
   InternalSwap(other);
 }
 void EnumOptions::InternalSwap(EnumOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(allow_alias_, other->allow_alias_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(allow_alias_, other->allow_alias_);
+  swap(deprecated_, other->deprecated_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -11960,6 +12760,10 @@
 
 void EnumValueOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
   deprecated_ = false;
@@ -11980,7 +12784,7 @@
       // optional bool deprecated = 1 [default = false];
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -11994,7 +12798,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -12005,18 +12809,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -12043,9 +12846,10 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -12054,13 +12858,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueOptions)
 }
 
 ::google::protobuf::uint8* EnumValueOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -12072,10 +12877,11 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -12084,7 +12890,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions)
   return target;
@@ -12099,16 +12905,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -12181,11 +12987,12 @@
   InternalSwap(other);
 }
 void EnumValueOptions::InternalSwap(EnumValueOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(deprecated_, other->deprecated_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -12318,6 +13125,10 @@
 
 void ServiceOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
   deprecated_ = false;
@@ -12338,7 +13149,7 @@
       // optional bool deprecated = 33 [default = false];
       case 33: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(264u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 264 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -12352,7 +13163,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -12363,18 +13174,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -12401,9 +13211,10 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -12412,13 +13223,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceOptions)
 }
 
 ::google::protobuf::uint8* ServiceOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -12430,10 +13242,11 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -12442,7 +13255,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions)
   return target;
@@ -12457,16 +13270,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -12539,11 +13352,12 @@
   InternalSwap(other);
 }
 void ServiceOptions::InternalSwap(ServiceOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(deprecated_, other->deprecated_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -12636,15 +13450,16 @@
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   _extensions_.MergeFrom(from._extensions_);
   ::memcpy(&deprecated_, &from.deprecated_,
-    reinterpret_cast<char*>(&idempotency_level_) -
-    reinterpret_cast<char*>(&deprecated_) + sizeof(idempotency_level_));
+    static_cast<size_t>(reinterpret_cast<char*>(&idempotency_level_) -
+    reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions)
 }
 
 void MethodOptions::SharedCtor() {
   _cached_size_ = 0;
-  ::memset(&deprecated_, 0, reinterpret_cast<char*>(&idempotency_level_) -
-    reinterpret_cast<char*>(&deprecated_) + sizeof(idempotency_level_));
+  ::memset(&deprecated_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&idempotency_level_) -
+      reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
 }
 
 MethodOptions::~MethodOptions() {
@@ -12680,11 +13495,17 @@
 
 void MethodOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   _extensions_.Clear();
   uninterpreted_option_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    ::memset(&deprecated_, 0, reinterpret_cast<char*>(&idempotency_level_) -
-      reinterpret_cast<char*>(&deprecated_) + sizeof(idempotency_level_));
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    ::memset(&deprecated_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&idempotency_level_) -
+        reinterpret_cast<char*>(&deprecated_)) + sizeof(idempotency_level_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -12703,7 +13524,7 @@
       // optional bool deprecated = 33 [default = false];
       case 33: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(264u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 264 & 0xFF */)) {
           set_has_deprecated();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -12717,7 +13538,7 @@
       // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];
       case 34: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(272u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 272 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -12725,7 +13546,8 @@
           if (::google::protobuf::MethodOptions_IdempotencyLevel_IsValid(value)) {
             set_idempotency_level(static_cast< ::google::protobuf::MethodOptions_IdempotencyLevel >(value));
           } else {
-            mutable_unknown_fields()->AddVarint(34, value);
+            mutable_unknown_fields()->AddVarint(
+                34, static_cast< ::google::protobuf::uint64>(value));
           }
         } else {
           goto handle_unusual;
@@ -12736,7 +13558,7 @@
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(7994u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 7994 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_uninterpreted_option()));
         } else {
@@ -12747,18 +13569,17 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         if ((8000u <= tag)) {
-          DO_(_extensions_.ParseField(tag, input, internal_default_instance(),
-                                      mutable_unknown_fields()));
+          DO_(_extensions_.ParseField(tag, input,
+              internal_default_instance(),
+              _internal_metadata_.mutable_unknown_fields()));
           continue;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -12791,9 +13612,10 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      999, this->uninterpreted_option(i), output);
+      999, this->uninterpreted_option(static_cast<int>(i)), output);
   }
 
   // Extension range [1000, 536870912)
@@ -12802,13 +13624,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.MethodOptions)
 }
 
 ::google::protobuf::uint8* MethodOptions::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -12826,10 +13649,11 @@
   }
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
-  for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->uninterpreted_option_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        999, this->uninterpreted_option(i), deterministic, target);
+        999, this->uninterpreted_option(static_cast<int>(i)), deterministic, target);
   }
 
   // Extension range [1000, 536870912)
@@ -12838,7 +13662,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions)
   return target;
@@ -12853,16 +13677,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
   {
-    unsigned int count = this->uninterpreted_option_size();
+    unsigned int count = static_cast<unsigned int>(this->uninterpreted_option_size());
     total_size += 2UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->uninterpreted_option(i));
+          this->uninterpreted_option(static_cast<int>(i)));
     }
   }
 
@@ -12950,12 +13774,13 @@
   InternalSwap(other);
 }
 void MethodOptions::InternalSwap(MethodOptions* other) {
+  using std::swap;
   uninterpreted_option_.InternalSwap(&other->uninterpreted_option_);
-  std::swap(deprecated_, other->deprecated_);
-  std::swap(idempotency_level_, other->idempotency_level_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(deprecated_, other->deprecated_);
+  swap(idempotency_level_, other->idempotency_level_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
   _extensions_.Swap(&other->_extensions_);
 }
 
@@ -13117,6 +13942,10 @@
 
 void UninterpretedOption_NamePart::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   if (has_name_part()) {
     GOOGLE_DCHECK(!name_part_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
     (*name_part_.UnsafeRawStringPointer())->clear();
@@ -13139,11 +13968,11 @@
       // required string name_part = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name_part()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->name_part().data(), this->name_part().length(),
+            this->name_part().data(), static_cast<int>(this->name_part().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.UninterpretedOption.NamePart.name_part");
         } else {
@@ -13155,7 +13984,7 @@
       // required bool is_extension = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           set_has_is_extension();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -13168,13 +13997,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -13198,7 +14025,7 @@
   // required string name_part = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name_part().data(), this->name_part().length(),
+      this->name_part().data(), static_cast<int>(this->name_part().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.UninterpretedOption.NamePart.name_part");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -13212,13 +14039,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption.NamePart)
 }
 
 ::google::protobuf::uint8* UninterpretedOption_NamePart::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -13227,7 +14055,7 @@
   // required string name_part = 1;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->name_part().data(), this->name_part().length(),
+      this->name_part().data(), static_cast<int>(this->name_part().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.UninterpretedOption.NamePart.name_part");
     target =
@@ -13242,7 +14070,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart)
   return target;
@@ -13273,7 +14101,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   if (((_has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) {  // All required fields are present.
     // required string name_part = 1;
@@ -13353,11 +14181,12 @@
   InternalSwap(other);
 }
 void UninterpretedOption_NamePart::InternalSwap(UninterpretedOption_NamePart* other) {
+  using std::swap;
   name_part_.Swap(&other->name_part_);
-  std::swap(is_extension_, other->is_extension_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(is_extension_, other->is_extension_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata UninterpretedOption_NamePart::GetMetadata() const {
@@ -13497,8 +14326,8 @@
     aggregate_value_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.aggregate_value_);
   }
   ::memcpy(&positive_int_value_, &from.positive_int_value_,
-    reinterpret_cast<char*>(&double_value_) -
-    reinterpret_cast<char*>(&positive_int_value_) + sizeof(double_value_));
+    static_cast<size_t>(reinterpret_cast<char*>(&double_value_) -
+    reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption)
 }
 
@@ -13507,8 +14336,9 @@
   identifier_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   aggregate_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&positive_int_value_, 0, reinterpret_cast<char*>(&double_value_) -
-    reinterpret_cast<char*>(&positive_int_value_) + sizeof(double_value_));
+  ::memset(&positive_int_value_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&double_value_) -
+      reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
 }
 
 UninterpretedOption::~UninterpretedOption() {
@@ -13547,24 +14377,30 @@
 
 void UninterpretedOption::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   name_.Clear();
-  if (_has_bits_[0 / 32] & 7u) {
-    if (has_identifier_value()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 7u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!identifier_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*identifier_value_.UnsafeRawStringPointer())->clear();
     }
-    if (has_string_value()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!string_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*string_value_.UnsafeRawStringPointer())->clear();
     }
-    if (has_aggregate_value()) {
+    if (cached_has_bits & 0x00000004u) {
       GOOGLE_DCHECK(!aggregate_value_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*aggregate_value_.UnsafeRawStringPointer())->clear();
     }
   }
-  if (_has_bits_[0 / 32] & 56u) {
-    ::memset(&positive_int_value_, 0, reinterpret_cast<char*>(&double_value_) -
-      reinterpret_cast<char*>(&positive_int_value_) + sizeof(double_value_));
+  if (cached_has_bits & 56u) {
+    ::memset(&positive_int_value_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&double_value_) -
+        reinterpret_cast<char*>(&positive_int_value_)) + sizeof(double_value_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -13583,7 +14419,7 @@
       // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_name()));
         } else {
@@ -13595,11 +14431,11 @@
       // optional string identifier_value = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_identifier_value()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->identifier_value().data(), this->identifier_value().length(),
+            this->identifier_value().data(), static_cast<int>(this->identifier_value().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.UninterpretedOption.identifier_value");
         } else {
@@ -13611,7 +14447,7 @@
       // optional uint64 positive_int_value = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(32u)) {
+            static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) {
           set_has_positive_int_value();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
@@ -13625,7 +14461,7 @@
       // optional int64 negative_int_value = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(40u)) {
+            static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
           set_has_negative_int_value();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
@@ -13639,7 +14475,7 @@
       // optional double double_value = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(49u)) {
+            static_cast< ::google::protobuf::uint8>(49u /* 49 & 0xFF */)) {
           set_has_double_value();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
@@ -13653,7 +14489,7 @@
       // optional bytes string_value = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(58u)) {
+            static_cast< ::google::protobuf::uint8>(58u /* 58 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
                 input, this->mutable_string_value()));
         } else {
@@ -13665,11 +14501,11 @@
       // optional string aggregate_value = 8;
       case 8: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(66u)) {
+            static_cast< ::google::protobuf::uint8>(66u /* 66 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_aggregate_value()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->aggregate_value().data(), this->aggregate_value().length(),
+            this->aggregate_value().data(), static_cast<int>(this->aggregate_value().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.UninterpretedOption.aggregate_value");
         } else {
@@ -13680,13 +14516,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -13707,16 +14541,17 @@
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
-  for (unsigned int i = 0, n = this->name_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->name_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->name(i), output);
+      2, this->name(static_cast<int>(i)), output);
   }
 
   cached_has_bits = _has_bits_[0];
   // optional string identifier_value = 3;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->identifier_value().data(), this->identifier_value().length(),
+      this->identifier_value().data(), static_cast<int>(this->identifier_value().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.UninterpretedOption.identifier_value");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -13747,7 +14582,7 @@
   // optional string aggregate_value = 8;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->aggregate_value().data(), this->aggregate_value().length(),
+      this->aggregate_value().data(), static_cast<int>(this->aggregate_value().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.UninterpretedOption.aggregate_value");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -13756,29 +14591,31 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption)
 }
 
 ::google::protobuf::uint8* UninterpretedOption::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
-  for (unsigned int i = 0, n = this->name_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->name_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->name(i), deterministic, target);
+        2, this->name(static_cast<int>(i)), deterministic, target);
   }
 
   cached_has_bits = _has_bits_[0];
   // optional string identifier_value = 3;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->identifier_value().data(), this->identifier_value().length(),
+      this->identifier_value().data(), static_cast<int>(this->identifier_value().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.UninterpretedOption.identifier_value");
     target =
@@ -13811,7 +14648,7 @@
   // optional string aggregate_value = 8;
   if (cached_has_bits & 0x00000004u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->aggregate_value().data(), this->aggregate_value().length(),
+      this->aggregate_value().data(), static_cast<int>(this->aggregate_value().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.UninterpretedOption.aggregate_value");
     target =
@@ -13821,7 +14658,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption)
   return target;
@@ -13834,16 +14671,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
   {
-    unsigned int count = this->name_size();
+    unsigned int count = static_cast<unsigned int>(this->name_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->name(i));
+          this->name(static_cast<int>(i)));
     }
   }
 
@@ -13970,16 +14807,17 @@
   InternalSwap(other);
 }
 void UninterpretedOption::InternalSwap(UninterpretedOption* other) {
+  using std::swap;
   name_.InternalSwap(&other->name_);
   identifier_value_.Swap(&other->identifier_value_);
   string_value_.Swap(&other->string_value_);
   aggregate_value_.Swap(&other->aggregate_value_);
-  std::swap(positive_int_value_, other->positive_int_value_);
-  std::swap(negative_int_value_, other->negative_int_value_);
-  std::swap(double_value_, other->double_value_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(positive_int_value_, other->positive_int_value_);
+  swap(negative_int_value_, other->negative_int_value_);
+  swap(double_value_, other->double_value_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata UninterpretedOption::GetMetadata() const {
@@ -14362,15 +15200,20 @@
 
 void SourceCodeInfo_Location::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   path_.Clear();
   span_.Clear();
   leading_detached_comments_.Clear();
-  if (_has_bits_[0 / 32] & 3u) {
-    if (has_leading_comments()) {
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 3u) {
+    if (cached_has_bits & 0x00000001u) {
       GOOGLE_DCHECK(!leading_comments_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*leading_comments_.UnsafeRawStringPointer())->clear();
     }
-    if (has_trailing_comments()) {
+    if (cached_has_bits & 0x00000002u) {
       GOOGLE_DCHECK(!trailing_comments_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
       (*trailing_comments_.UnsafeRawStringPointer())->clear();
     }
@@ -14392,12 +15235,13 @@
       // repeated int32 path = 1 [packed = true];
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, this->mutable_path())));
-        } else if (static_cast< ::google::protobuf::uint8>(tag) ==
-                   static_cast< ::google::protobuf::uint8>(8u)) {
+        } else if (
+            static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  1, 10u, input, this->mutable_path())));
@@ -14410,12 +15254,13 @@
       // repeated int32 span = 2 [packed = true];
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, this->mutable_span())));
-        } else if (static_cast< ::google::protobuf::uint8>(tag) ==
-                   static_cast< ::google::protobuf::uint8>(16u)) {
+        } else if (
+            static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  1, 18u, input, this->mutable_span())));
@@ -14428,11 +15273,11 @@
       // optional string leading_comments = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_leading_comments()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->leading_comments().data(), this->leading_comments().length(),
+            this->leading_comments().data(), static_cast<int>(this->leading_comments().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.SourceCodeInfo.Location.leading_comments");
         } else {
@@ -14444,11 +15289,11 @@
       // optional string trailing_comments = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_trailing_comments()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->trailing_comments().data(), this->trailing_comments().length(),
+            this->trailing_comments().data(), static_cast<int>(this->trailing_comments().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.SourceCodeInfo.Location.trailing_comments");
         } else {
@@ -14460,12 +15305,12 @@
       // repeated string leading_detached_comments = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_leading_detached_comments()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
             this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(),
-            this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(),
+            static_cast<int>(this->leading_detached_comments(this->leading_detached_comments_size() - 1).length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
         } else {
@@ -14476,13 +15321,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -14505,7 +15348,8 @@
   // repeated int32 path = 1 [packed = true];
   if (this->path_size() > 0) {
     ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
-    output->WriteVarint32(_path_cached_byte_size_);
+    output->WriteVarint32(static_cast< ::google::protobuf::uint32>(
+        _path_cached_byte_size_));
   }
   for (int i = 0, n = this->path_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
@@ -14515,7 +15359,8 @@
   // repeated int32 span = 2 [packed = true];
   if (this->span_size() > 0) {
     ::google::protobuf::internal::WireFormatLite::WriteTag(2, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
-    output->WriteVarint32(_span_cached_byte_size_);
+    output->WriteVarint32(static_cast< ::google::protobuf::uint32>(
+        _span_cached_byte_size_));
   }
   for (int i = 0, n = this->span_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
@@ -14526,7 +15371,7 @@
   // optional string leading_comments = 3;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->leading_comments().data(), this->leading_comments().length(),
+      this->leading_comments().data(), static_cast<int>(this->leading_comments().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.SourceCodeInfo.Location.leading_comments");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -14536,7 +15381,7 @@
   // optional string trailing_comments = 4;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->trailing_comments().data(), this->trailing_comments().length(),
+      this->trailing_comments().data(), static_cast<int>(this->trailing_comments().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.SourceCodeInfo.Location.trailing_comments");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -14546,7 +15391,7 @@
   // repeated string leading_detached_comments = 6;
   for (int i = 0, n = this->leading_detached_comments_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+      this->leading_detached_comments(i).data(), static_cast<int>(this->leading_detached_comments(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
     ::google::protobuf::internal::WireFormatLite::WriteString(
@@ -14555,13 +15400,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo.Location)
 }
 
 ::google::protobuf::uint8* SourceCodeInfo_Location::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -14573,7 +15419,8 @@
       ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
       target);
     target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
-      _path_cached_byte_size_, target);
+        static_cast< ::google::protobuf::uint32>(
+            _path_cached_byte_size_), target);
     target = ::google::protobuf::internal::WireFormatLite::
       WriteInt32NoTagToArray(this->path_, target);
   }
@@ -14585,7 +15432,8 @@
       ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
       target);
     target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
-      _span_cached_byte_size_, target);
+        static_cast< ::google::protobuf::uint32>(
+            _span_cached_byte_size_), target);
     target = ::google::protobuf::internal::WireFormatLite::
       WriteInt32NoTagToArray(this->span_, target);
   }
@@ -14594,7 +15442,7 @@
   // optional string leading_comments = 3;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->leading_comments().data(), this->leading_comments().length(),
+      this->leading_comments().data(), static_cast<int>(this->leading_comments().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.SourceCodeInfo.Location.leading_comments");
     target =
@@ -14605,7 +15453,7 @@
   // optional string trailing_comments = 4;
   if (cached_has_bits & 0x00000002u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->trailing_comments().data(), this->trailing_comments().length(),
+      this->trailing_comments().data(), static_cast<int>(this->trailing_comments().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.SourceCodeInfo.Location.trailing_comments");
     target =
@@ -14616,7 +15464,7 @@
   // repeated string leading_detached_comments = 6;
   for (int i = 0, n = this->leading_detached_comments_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(),
+      this->leading_detached_comments(i).data(), static_cast<int>(this->leading_detached_comments(i).length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.SourceCodeInfo.Location.leading_detached_comments");
     target = ::google::protobuf::internal::WireFormatLite::
@@ -14625,7 +15473,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location)
   return target;
@@ -14638,7 +15486,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated int32 path = 1 [packed = true];
   {
@@ -14646,7 +15494,8 @@
       Int32Size(this->path_);
     if (data_size > 0) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+            static_cast< ::google::protobuf::int32>(data_size));
     }
     int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);
     GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
@@ -14661,7 +15510,8 @@
       Int32Size(this->span_);
     if (data_size > 0) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+            static_cast< ::google::protobuf::int32>(data_size));
     }
     int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);
     GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
@@ -14762,14 +15612,15 @@
   InternalSwap(other);
 }
 void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) {
+  using std::swap;
   path_.InternalSwap(&other->path_);
   span_.InternalSwap(&other->span_);
   leading_detached_comments_.InternalSwap(&other->leading_detached_comments_);
   leading_comments_.Swap(&other->leading_comments_);
   trailing_comments_.Swap(&other->trailing_comments_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata SourceCodeInfo_Location::GetMetadata() const {
@@ -15098,6 +15949,10 @@
 
 void SourceCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   location_.Clear();
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -15116,7 +15971,7 @@
       // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_location()));
         } else {
@@ -15127,13 +15982,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -15154,34 +16007,37 @@
   (void) cached_has_bits;
 
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
-  for (unsigned int i = 0, n = this->location_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->location_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      1, this->location(i), output);
+      1, this->location(static_cast<int>(i)), output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo)
 }
 
 ::google::protobuf::uint8* SourceCodeInfo::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
-  for (unsigned int i = 0, n = this->location_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->location_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        1, this->location(i), deterministic, target);
+        1, this->location(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo)
   return target;
@@ -15194,16 +16050,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
   {
-    unsigned int count = this->location_size();
+    unsigned int count = static_cast<unsigned int>(this->location_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->location(i));
+          this->location(static_cast<int>(i)));
     }
   }
 
@@ -15262,10 +16118,11 @@
   InternalSwap(other);
 }
 void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) {
+  using std::swap;
   location_.InternalSwap(&other->location_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata SourceCodeInfo::GetMetadata() const {
@@ -15337,16 +16194,17 @@
     source_file_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.source_file_);
   }
   ::memcpy(&begin_, &from.begin_,
-    reinterpret_cast<char*>(&end_) -
-    reinterpret_cast<char*>(&begin_) + sizeof(end_));
+    static_cast<size_t>(reinterpret_cast<char*>(&end_) -
+    reinterpret_cast<char*>(&begin_)) + sizeof(end_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation)
 }
 
 void GeneratedCodeInfo_Annotation::SharedCtor() {
   _cached_size_ = 0;
   source_file_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&begin_, 0, reinterpret_cast<char*>(&end_) -
-    reinterpret_cast<char*>(&begin_) + sizeof(end_));
+  ::memset(&begin_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&end_) -
+      reinterpret_cast<char*>(&begin_)) + sizeof(end_));
 }
 
 GeneratedCodeInfo_Annotation::~GeneratedCodeInfo_Annotation() {
@@ -15383,14 +16241,20 @@
 
 void GeneratedCodeInfo_Annotation::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   path_.Clear();
   if (has_source_file()) {
     GOOGLE_DCHECK(!source_file_.IsDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()));
     (*source_file_.UnsafeRawStringPointer())->clear();
   }
-  if (_has_bits_[0 / 32] & 6u) {
-    ::memset(&begin_, 0, reinterpret_cast<char*>(&end_) -
-      reinterpret_cast<char*>(&begin_) + sizeof(end_));
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 6u) {
+    ::memset(&begin_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&end_) -
+        reinterpret_cast<char*>(&begin_)) + sizeof(end_));
   }
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -15409,12 +16273,13 @@
       // repeated int32 path = 1 [packed = true];
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  input, this->mutable_path())));
-        } else if (static_cast< ::google::protobuf::uint8>(tag) ==
-                   static_cast< ::google::protobuf::uint8>(8u)) {
+        } else if (
+            static_cast< ::google::protobuf::uint8>(tag) ==
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
                  1, 10u, input, this->mutable_path())));
@@ -15427,11 +16292,11 @@
       // optional string source_file = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_source_file()));
           ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-            this->source_file().data(), this->source_file().length(),
+            this->source_file().data(), static_cast<int>(this->source_file().length()),
             ::google::protobuf::internal::WireFormat::PARSE,
             "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
         } else {
@@ -15443,7 +16308,7 @@
       // optional int32 begin = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
           set_has_begin();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -15457,7 +16322,7 @@
       // optional int32 end = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(32u)) {
+            static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) {
           set_has_end();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -15470,13 +16335,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -15499,7 +16362,8 @@
   // repeated int32 path = 1 [packed = true];
   if (this->path_size() > 0) {
     ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output);
-    output->WriteVarint32(_path_cached_byte_size_);
+    output->WriteVarint32(static_cast< ::google::protobuf::uint32>(
+        _path_cached_byte_size_));
   }
   for (int i = 0, n = this->path_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteInt32NoTag(
@@ -15510,7 +16374,7 @@
   // optional string source_file = 2;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->source_file().data(), this->source_file().length(),
+      this->source_file().data(), static_cast<int>(this->source_file().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -15529,13 +16393,14 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo.Annotation)
 }
 
 ::google::protobuf::uint8* GeneratedCodeInfo_Annotation::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -15547,7 +16412,8 @@
       ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED,
       target);
     target = ::google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(
-      _path_cached_byte_size_, target);
+        static_cast< ::google::protobuf::uint32>(
+            _path_cached_byte_size_), target);
     target = ::google::protobuf::internal::WireFormatLite::
       WriteInt32NoTagToArray(this->path_, target);
   }
@@ -15556,7 +16422,7 @@
   // optional string source_file = 2;
   if (cached_has_bits & 0x00000001u) {
     ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(
-      this->source_file().data(), this->source_file().length(),
+      this->source_file().data(), static_cast<int>(this->source_file().length()),
       ::google::protobuf::internal::WireFormat::SERIALIZE,
       "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
     target =
@@ -15576,7 +16442,7 @@
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo.Annotation)
   return target;
@@ -15589,7 +16455,7 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated int32 path = 1 [packed = true];
   {
@@ -15597,7 +16463,8 @@
       Int32Size(this->path_);
     if (data_size > 0) {
       total_size += 1 +
-        ::google::protobuf::internal::WireFormatLite::Int32Size(data_size);
+        ::google::protobuf::internal::WireFormatLite::Int32Size(
+            static_cast< ::google::protobuf::int32>(data_size));
     }
     int cached_size = ::google::protobuf::internal::ToCachedSize(data_size);
     GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
@@ -15698,13 +16565,14 @@
   InternalSwap(other);
 }
 void GeneratedCodeInfo_Annotation::InternalSwap(GeneratedCodeInfo_Annotation* other) {
+  using std::swap;
   path_.InternalSwap(&other->path_);
   source_file_.Swap(&other->source_file_);
-  std::swap(begin_, other->begin_);
-  std::swap(end_, other->end_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(begin_, other->begin_);
+  swap(end_, other->end_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const {
@@ -15919,6 +16787,10 @@
 
 void GeneratedCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   annotation_.Clear();
   _has_bits_.Clear();
   _internal_metadata_.Clear();
@@ -15937,7 +16809,7 @@
       // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_annotation()));
         } else {
@@ -15948,13 +16820,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
         DO_(::google::protobuf::internal::WireFormat::SkipField(
-              input, tag, mutable_unknown_fields()));
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -15975,34 +16845,37 @@
   (void) cached_has_bits;
 
   // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
-  for (unsigned int i = 0, n = this->annotation_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->annotation_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      1, this->annotation(i), output);
+      1, this->annotation(static_cast<int>(i)), output);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
-        unknown_fields(), output);
+        _internal_metadata_.unknown_fields(), output);
   }
   // @@protoc_insertion_point(serialize_end:google.protobuf.GeneratedCodeInfo)
 }
 
 ::google::protobuf::uint8* GeneratedCodeInfo::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
-  for (unsigned int i = 0, n = this->annotation_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->annotation_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        1, this->annotation(i), deterministic, target);
+        1, this->annotation(static_cast<int>(i)), deterministic, target);
   }
 
   if (_internal_metadata_.have_unknown_fields()) {
     target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
-        unknown_fields(), target);
+        _internal_metadata_.unknown_fields(), target);
   }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.GeneratedCodeInfo)
   return target;
@@ -16015,16 +16888,16 @@
   if (_internal_metadata_.have_unknown_fields()) {
     total_size +=
       ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
-        unknown_fields());
+        _internal_metadata_.unknown_fields());
   }
   // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
   {
-    unsigned int count = this->annotation_size();
+    unsigned int count = static_cast<unsigned int>(this->annotation_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->annotation(i));
+          this->annotation(static_cast<int>(i)));
     }
   }
 
@@ -16083,10 +16956,11 @@
   InternalSwap(other);
 }
 void GeneratedCodeInfo::InternalSwap(GeneratedCodeInfo* other) {
+  using std::swap;
   annotation_.InternalSwap(&other->annotation_);
-  std::swap(_has_bits_[0], other->_has_bits_[0]);
+  swap(_has_bits_[0], other->_has_bits_[0]);
   _internal_metadata_.Swap(&other->_internal_metadata_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata GeneratedCodeInfo::GetMetadata() const {
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index d1ed2b1..7ec516a 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -54,6 +54,9 @@
 class EnumValueOptions;
 class EnumValueOptionsDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
+class ExtensionRangeOptions;
+class ExtensionRangeOptionsDefaultTypeInternal;
+LIBPROTOBUF_EXPORT extern ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
 class FieldDescriptorProto;
 class FieldDescriptorProtoDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
@@ -121,8 +124,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -276,11 +280,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FileDescriptorSet(FileDescriptorSet&& from) noexcept
+    : FileDescriptorSet() {
+    *this = ::std::move(from);
+  }
 
+  inline FileDescriptorSet& operator=(FileDescriptorSet&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -296,6 +313,9 @@
     0;
 
   void Swap(FileDescriptorSet* other);
+  friend void swap(FileDescriptorSet& a, FileDescriptorSet& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -371,11 +391,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FileDescriptorProto(FileDescriptorProto&& from) noexcept
+    : FileDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline FileDescriptorProto& operator=(FileDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -391,6 +424,9 @@
     1;
 
   void Swap(FileDescriptorProto* other);
+  friend void swap(FileDescriptorProto& a, FileDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -632,11 +668,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  DescriptorProto_ExtensionRange(DescriptorProto_ExtensionRange&& from) noexcept
+    : DescriptorProto_ExtensionRange() {
+    *this = ::std::move(from);
+  }
 
+  inline DescriptorProto_ExtensionRange& operator=(DescriptorProto_ExtensionRange&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -652,6 +701,9 @@
     2;
 
   void Swap(DescriptorProto_ExtensionRange* other);
+  friend void swap(DescriptorProto_ExtensionRange& a, DescriptorProto_ExtensionRange& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -693,6 +745,15 @@
 
   // accessors -------------------------------------------------------
 
+  // optional .google.protobuf.ExtensionRangeOptions options = 3;
+  bool has_options() const;
+  void clear_options();
+  static const int kOptionsFieldNumber = 3;
+  const ::google::protobuf::ExtensionRangeOptions& options() const;
+  ::google::protobuf::ExtensionRangeOptions* mutable_options();
+  ::google::protobuf::ExtensionRangeOptions* release_options();
+  void set_allocated_options(::google::protobuf::ExtensionRangeOptions* options);
+
   // optional int32 start = 1;
   bool has_start() const;
   void clear_start();
@@ -713,10 +774,13 @@
   void clear_has_start();
   void set_has_end();
   void clear_has_end();
+  void set_has_options();
+  void clear_has_options();
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
   ::google::protobuf::internal::HasBits<1> _has_bits_;
   mutable int _cached_size_;
+  ::google::protobuf::ExtensionRangeOptions* options_;
   ::google::protobuf::int32 start_;
   ::google::protobuf::int32 end_;
   friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct;
@@ -734,11 +798,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  DescriptorProto_ReservedRange(DescriptorProto_ReservedRange&& from) noexcept
+    : DescriptorProto_ReservedRange() {
+    *this = ::std::move(from);
+  }
 
+  inline DescriptorProto_ReservedRange& operator=(DescriptorProto_ReservedRange&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -754,6 +831,9 @@
     3;
 
   void Swap(DescriptorProto_ReservedRange* other);
+  friend void swap(DescriptorProto_ReservedRange& a, DescriptorProto_ReservedRange& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -836,11 +916,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  DescriptorProto(DescriptorProto&& from) noexcept
+    : DescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline DescriptorProto& operator=(DescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -856,6 +949,9 @@
     4;
 
   void Swap(DescriptorProto* other);
+  friend void swap(DescriptorProto& a, DescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -1054,6 +1150,120 @@
 };
 // -------------------------------------------------------------------
 
+class LIBPROTOBUF_EXPORT ExtensionRangeOptions : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ {
+ public:
+  ExtensionRangeOptions();
+  virtual ~ExtensionRangeOptions();
+
+  ExtensionRangeOptions(const ExtensionRangeOptions& from);
+
+  inline ExtensionRangeOptions& operator=(const ExtensionRangeOptions& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  #if LANG_CXX11
+  ExtensionRangeOptions(ExtensionRangeOptions&& from) noexcept
+    : ExtensionRangeOptions() {
+    *this = ::std::move(from);
+  }
+
+  inline ExtensionRangeOptions& operator=(ExtensionRangeOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _internal_metadata_.unknown_fields();
+  }
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return _internal_metadata_.mutable_unknown_fields();
+  }
+
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const ExtensionRangeOptions& default_instance();
+
+  static inline const ExtensionRangeOptions* internal_default_instance() {
+    return reinterpret_cast<const ExtensionRangeOptions*>(
+               &_ExtensionRangeOptions_default_instance_);
+  }
+  static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
+    5;
+
+  void Swap(ExtensionRangeOptions* other);
+  friend void swap(ExtensionRangeOptions& a, ExtensionRangeOptions& b) {
+    a.Swap(&b);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ExtensionRangeOptions* New() const PROTOBUF_FINAL { return New(NULL); }
+
+  ExtensionRangeOptions* New(::google::protobuf::Arena* arena) const PROTOBUF_FINAL;
+  void CopyFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void MergeFrom(const ::google::protobuf::Message& from) PROTOBUF_FINAL;
+  void CopyFrom(const ExtensionRangeOptions& from);
+  void MergeFrom(const ExtensionRangeOptions& from);
+  void Clear() PROTOBUF_FINAL;
+  bool IsInitialized() const PROTOBUF_FINAL;
+
+  size_t ByteSizeLong() const PROTOBUF_FINAL;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input) PROTOBUF_FINAL;
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const PROTOBUF_FINAL;
+  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
+      bool deterministic, ::google::protobuf::uint8* target) const PROTOBUF_FINAL;
+  int GetCachedSize() const PROTOBUF_FINAL { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const PROTOBUF_FINAL;
+  void InternalSwap(ExtensionRangeOptions* other);
+  private:
+  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
+    return NULL;
+  }
+  inline void* MaybeArenaPtr() const {
+    return NULL;
+  }
+  public:
+
+  ::google::protobuf::Metadata GetMetadata() const PROTOBUF_FINAL;
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+  int uninterpreted_option_size() const;
+  void clear_uninterpreted_option();
+  static const int kUninterpretedOptionFieldNumber = 999;
+  const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const;
+  ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index);
+  ::google::protobuf::UninterpretedOption* add_uninterpreted_option();
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+      mutable_uninterpreted_option();
+  const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+      uninterpreted_option() const;
+
+  GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ExtensionRangeOptions)
+  // @@protoc_insertion_point(class_scope:google.protobuf.ExtensionRangeOptions)
+ private:
+
+  ::google::protobuf::internal::ExtensionSet _extensions_;
+
+  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
+  ::google::protobuf::internal::HasBits<1> _has_bits_;
+  mutable int _cached_size_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  friend struct protobuf_google_2fprotobuf_2fdescriptor_2eproto::TableStruct;
+};
+// -------------------------------------------------------------------
+
 class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ {
  public:
   FieldDescriptorProto();
@@ -1065,11 +1275,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FieldDescriptorProto(FieldDescriptorProto&& from) noexcept
+    : FieldDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline FieldDescriptorProto& operator=(FieldDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -1082,9 +1305,12 @@
                &_FieldDescriptorProto_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    5;
+    6;
 
   void Swap(FieldDescriptorProto* other);
+  friend void swap(FieldDescriptorProto& a, FieldDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -1375,11 +1601,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  OneofDescriptorProto(OneofDescriptorProto&& from) noexcept
+    : OneofDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline OneofDescriptorProto& operator=(OneofDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -1392,9 +1631,12 @@
                &_OneofDescriptorProto_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    6;
+    7;
 
   void Swap(OneofDescriptorProto* other);
+  friend void swap(OneofDescriptorProto& a, OneofDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -1487,11 +1729,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  EnumDescriptorProto(EnumDescriptorProto&& from) noexcept
+    : EnumDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline EnumDescriptorProto& operator=(EnumDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -1504,9 +1759,12 @@
                &_EnumDescriptorProto_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    7;
+    8;
 
   void Swap(EnumDescriptorProto* other);
+  friend void swap(EnumDescriptorProto& a, EnumDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -1612,11 +1870,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  EnumValueDescriptorProto(EnumValueDescriptorProto&& from) noexcept
+    : EnumValueDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline EnumValueDescriptorProto& operator=(EnumValueDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -1629,9 +1900,12 @@
                &_EnumValueDescriptorProto_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    8;
+    9;
 
   void Swap(EnumValueDescriptorProto* other);
+  friend void swap(EnumValueDescriptorProto& a, EnumValueDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -1734,11 +2008,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  ServiceDescriptorProto(ServiceDescriptorProto&& from) noexcept
+    : ServiceDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline ServiceDescriptorProto& operator=(ServiceDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -1751,9 +2038,12 @@
                &_ServiceDescriptorProto_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    9;
+    10;
 
   void Swap(ServiceDescriptorProto* other);
+  friend void swap(ServiceDescriptorProto& a, ServiceDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -1859,11 +2149,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  MethodDescriptorProto(MethodDescriptorProto&& from) noexcept
+    : MethodDescriptorProto() {
+    *this = ::std::move(from);
+  }
 
+  inline MethodDescriptorProto& operator=(MethodDescriptorProto&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -1876,9 +2179,12 @@
                &_MethodDescriptorProto_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    10;
+    11;
 
   void Swap(MethodDescriptorProto* other);
+  friend void swap(MethodDescriptorProto& a, MethodDescriptorProto& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -2027,11 +2333,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FileOptions(FileOptions&& from) noexcept
+    : FileOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline FileOptions& operator=(FileOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -2044,9 +2363,12 @@
                &_FileOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    11;
+    12;
 
   void Swap(FileOptions* other);
+  friend void swap(FileOptions& a, FileOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -2233,6 +2555,21 @@
   ::std::string* release_php_class_prefix();
   void set_allocated_php_class_prefix(::std::string* php_class_prefix);
 
+  // optional string php_namespace = 41;
+  bool has_php_namespace() const;
+  void clear_php_namespace();
+  static const int kPhpNamespaceFieldNumber = 41;
+  const ::std::string& php_namespace() const;
+  void set_php_namespace(const ::std::string& value);
+  #if LANG_CXX11
+  void set_php_namespace(::std::string&& value);
+  #endif
+  void set_php_namespace(const char* value);
+  void set_php_namespace(const char* value, size_t size);
+  ::std::string* mutable_php_namespace();
+  ::std::string* release_php_namespace();
+  void set_allocated_php_namespace(::std::string* php_namespace);
+
   // optional bool java_multiple_files = 10 [default = false];
   bool has_java_multiple_files() const;
   void clear_java_multiple_files();
@@ -2275,6 +2612,13 @@
   bool py_generic_services() const;
   void set_py_generic_services(bool value);
 
+  // optional bool php_generic_services = 19 [default = false];
+  bool has_php_generic_services() const;
+  void clear_php_generic_services();
+  static const int kPhpGenericServicesFieldNumber = 19;
+  bool php_generic_services() const;
+  void set_php_generic_services(bool value);
+
   // optional bool deprecated = 23 [default = false];
   bool has_deprecated() const;
   void clear_deprecated();
@@ -2319,6 +2663,8 @@
   void clear_has_java_generic_services();
   void set_has_py_generic_services();
   void clear_has_py_generic_services();
+  void set_has_php_generic_services();
+  void clear_has_php_generic_services();
   void set_has_deprecated();
   void clear_has_deprecated();
   void set_has_cc_enable_arenas();
@@ -2331,6 +2677,8 @@
   void clear_has_swift_prefix();
   void set_has_php_class_prefix();
   void clear_has_php_class_prefix();
+  void set_has_php_namespace();
+  void clear_has_php_namespace();
 
   ::google::protobuf::internal::ExtensionSet _extensions_;
 
@@ -2345,12 +2693,14 @@
   ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
   ::google::protobuf::internal::ArenaStringPtr swift_prefix_;
   ::google::protobuf::internal::ArenaStringPtr php_class_prefix_;
+  ::google::protobuf::internal::ArenaStringPtr php_namespace_;
   bool java_multiple_files_;
   bool java_generate_equals_and_hash_;
   bool java_string_check_utf8_;
   bool cc_generic_services_;
   bool java_generic_services_;
   bool py_generic_services_;
+  bool php_generic_services_;
   bool deprecated_;
   bool cc_enable_arenas_;
   int optimize_for_;
@@ -2369,11 +2719,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  MessageOptions(MessageOptions&& from) noexcept
+    : MessageOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline MessageOptions& operator=(MessageOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -2386,9 +2749,12 @@
                &_MessageOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    12;
+    13;
 
   void Swap(MessageOptions* other);
+  friend void swap(MessageOptions& a, MessageOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -2507,11 +2873,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FieldOptions(FieldOptions&& from) noexcept
+    : FieldOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline FieldOptions& operator=(FieldOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -2524,9 +2903,12 @@
                &_FieldOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    13;
+    14;
 
   void Swap(FieldOptions* other);
+  friend void swap(FieldOptions& a, FieldOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -2721,11 +3103,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  OneofOptions(OneofOptions&& from) noexcept
+    : OneofOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline OneofOptions& operator=(OneofOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -2738,9 +3133,12 @@
                &_OneofOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    14;
+    15;
 
   void Swap(OneofOptions* other);
+  friend void swap(OneofOptions& a, OneofOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -2819,11 +3217,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  EnumOptions(EnumOptions&& from) noexcept
+    : EnumOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline EnumOptions& operator=(EnumOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -2836,9 +3247,12 @@
                &_EnumOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    15;
+    16;
 
   void Swap(EnumOptions* other);
+  friend void swap(EnumOptions& a, EnumOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -2937,11 +3351,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  EnumValueOptions(EnumValueOptions&& from) noexcept
+    : EnumValueOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline EnumValueOptions& operator=(EnumValueOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -2954,9 +3381,12 @@
                &_EnumValueOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    16;
+    17;
 
   void Swap(EnumValueOptions* other);
+  friend void swap(EnumValueOptions& a, EnumValueOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3045,11 +3475,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  ServiceOptions(ServiceOptions&& from) noexcept
+    : ServiceOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline ServiceOptions& operator=(ServiceOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3062,9 +3505,12 @@
                &_ServiceOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    17;
+    18;
 
   void Swap(ServiceOptions* other);
+  friend void swap(ServiceOptions& a, ServiceOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3153,11 +3599,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  MethodOptions(MethodOptions&& from) noexcept
+    : MethodOptions() {
+    *this = ::std::move(from);
+  }
 
+  inline MethodOptions& operator=(MethodOptions&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3170,9 +3629,12 @@
                &_MethodOptions_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    18;
+    19;
 
   void Swap(MethodOptions* other);
+  friend void swap(MethodOptions& a, MethodOptions& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3299,11 +3761,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  UninterpretedOption_NamePart(UninterpretedOption_NamePart&& from) noexcept
+    : UninterpretedOption_NamePart() {
+    *this = ::std::move(from);
+  }
 
+  inline UninterpretedOption_NamePart& operator=(UninterpretedOption_NamePart&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3316,9 +3791,12 @@
                &_UninterpretedOption_NamePart_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    19;
+    20;
 
   void Swap(UninterpretedOption_NamePart* other);
+  friend void swap(UninterpretedOption_NamePart& a, UninterpretedOption_NamePart& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3412,11 +3890,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  UninterpretedOption(UninterpretedOption&& from) noexcept
+    : UninterpretedOption() {
+    *this = ::std::move(from);
+  }
 
+  inline UninterpretedOption& operator=(UninterpretedOption&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3429,9 +3920,12 @@
                &_UninterpretedOption_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    20;
+    21;
 
   void Swap(UninterpretedOption* other);
+  friend void swap(UninterpretedOption& a, UninterpretedOption& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3593,11 +4087,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  SourceCodeInfo_Location(SourceCodeInfo_Location&& from) noexcept
+    : SourceCodeInfo_Location() {
+    *this = ::std::move(from);
+  }
 
+  inline SourceCodeInfo_Location& operator=(SourceCodeInfo_Location&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3610,9 +4117,12 @@
                &_SourceCodeInfo_Location_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    21;
+    22;
 
   void Swap(SourceCodeInfo_Location* other);
+  friend void swap(SourceCodeInfo_Location& a, SourceCodeInfo_Location& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3762,11 +4272,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  SourceCodeInfo(SourceCodeInfo&& from) noexcept
+    : SourceCodeInfo() {
+    *this = ::std::move(from);
+  }
 
+  inline SourceCodeInfo& operator=(SourceCodeInfo&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3779,9 +4302,12 @@
                &_SourceCodeInfo_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    22;
+    23;
 
   void Swap(SourceCodeInfo* other);
+  friend void swap(SourceCodeInfo& a, SourceCodeInfo& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3859,11 +4385,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  GeneratedCodeInfo_Annotation(GeneratedCodeInfo_Annotation&& from) noexcept
+    : GeneratedCodeInfo_Annotation() {
+    *this = ::std::move(from);
+  }
 
+  inline GeneratedCodeInfo_Annotation& operator=(GeneratedCodeInfo_Annotation&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -3876,9 +4415,12 @@
                &_GeneratedCodeInfo_Annotation_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    23;
+    24;
 
   void Swap(GeneratedCodeInfo_Annotation* other);
+  friend void swap(GeneratedCodeInfo_Annotation& a, GeneratedCodeInfo_Annotation& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -3993,11 +4535,24 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  GeneratedCodeInfo(GeneratedCodeInfo&& from) noexcept
+    : GeneratedCodeInfo() {
+    *this = ::std::move(from);
+  }
 
+  inline GeneratedCodeInfo& operator=(GeneratedCodeInfo&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
     return _internal_metadata_.unknown_fields();
   }
-
   inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
     return _internal_metadata_.mutable_unknown_fields();
   }
@@ -4010,9 +4565,12 @@
                &_GeneratedCodeInfo_default_instance_);
   }
   static PROTOBUF_CONSTEXPR int const kIndexInFileMessages =
-    24;
+    25;
 
   void Swap(GeneratedCodeInfo* other);
+  friend void swap(GeneratedCodeInfo& a, GeneratedCodeInfo& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -4083,6 +4641,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // FileDescriptorSet
 
 // repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -4509,9 +5071,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const {
+  const ::google::protobuf::FileOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::FileOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::FileOptions*>(
+      &::google::protobuf::_FileOptions_default_instance_);
 }
 inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() {
   set_has_options();
@@ -4554,9 +5117,10 @@
   clear_has_source_code_info();
 }
 inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const {
+  const ::google::protobuf::SourceCodeInfo* p = source_code_info_;
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info)
-  return source_code_info_ != NULL ? *source_code_info_
-                         : *::google::protobuf::SourceCodeInfo::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceCodeInfo*>(
+      &::google::protobuf::_SourceCodeInfo_default_instance_);
 }
 inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() {
   set_has_source_code_info();
@@ -4653,13 +5217,13 @@
 
 // optional int32 start = 1;
 inline bool DescriptorProto_ExtensionRange::has_start() const {
-  return (_has_bits_[0] & 0x00000001u) != 0;
+  return (_has_bits_[0] & 0x00000002u) != 0;
 }
 inline void DescriptorProto_ExtensionRange::set_has_start() {
-  _has_bits_[0] |= 0x00000001u;
+  _has_bits_[0] |= 0x00000002u;
 }
 inline void DescriptorProto_ExtensionRange::clear_has_start() {
-  _has_bits_[0] &= ~0x00000001u;
+  _has_bits_[0] &= ~0x00000002u;
 }
 inline void DescriptorProto_ExtensionRange::clear_start() {
   start_ = 0;
@@ -4677,13 +5241,13 @@
 
 // optional int32 end = 2;
 inline bool DescriptorProto_ExtensionRange::has_end() const {
-  return (_has_bits_[0] & 0x00000002u) != 0;
+  return (_has_bits_[0] & 0x00000004u) != 0;
 }
 inline void DescriptorProto_ExtensionRange::set_has_end() {
-  _has_bits_[0] |= 0x00000002u;
+  _has_bits_[0] |= 0x00000004u;
 }
 inline void DescriptorProto_ExtensionRange::clear_has_end() {
-  _has_bits_[0] &= ~0x00000002u;
+  _has_bits_[0] &= ~0x00000004u;
 }
 inline void DescriptorProto_ExtensionRange::clear_end() {
   end_ = 0;
@@ -4699,6 +5263,52 @@
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
 }
 
+// optional .google.protobuf.ExtensionRangeOptions options = 3;
+inline bool DescriptorProto_ExtensionRange::has_options() const {
+  return (_has_bits_[0] & 0x00000001u) != 0;
+}
+inline void DescriptorProto_ExtensionRange::set_has_options() {
+  _has_bits_[0] |= 0x00000001u;
+}
+inline void DescriptorProto_ExtensionRange::clear_has_options() {
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline void DescriptorProto_ExtensionRange::clear_options() {
+  if (options_ != NULL) options_->::google::protobuf::ExtensionRangeOptions::Clear();
+  clear_has_options();
+}
+inline const ::google::protobuf::ExtensionRangeOptions& DescriptorProto_ExtensionRange::options() const {
+  const ::google::protobuf::ExtensionRangeOptions* p = options_;
+  // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.options)
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::ExtensionRangeOptions*>(
+      &::google::protobuf::_ExtensionRangeOptions_default_instance_);
+}
+inline ::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::mutable_options() {
+  set_has_options();
+  if (options_ == NULL) {
+    options_ = new ::google::protobuf::ExtensionRangeOptions;
+  }
+  // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.ExtensionRange.options)
+  return options_;
+}
+inline ::google::protobuf::ExtensionRangeOptions* DescriptorProto_ExtensionRange::release_options() {
+  // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.ExtensionRange.options)
+  clear_has_options();
+  ::google::protobuf::ExtensionRangeOptions* temp = options_;
+  options_ = NULL;
+  return temp;
+}
+inline void DescriptorProto_ExtensionRange::set_allocated_options(::google::protobuf::ExtensionRangeOptions* options) {
+  delete options_;
+  options_ = options;
+  if (options) {
+    set_has_options();
+  } else {
+    clear_has_options();
+  }
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.ExtensionRange.options)
+}
+
 // -------------------------------------------------------------------
 
 // DescriptorProto_ReservedRange
@@ -5013,9 +5623,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const {
+  const ::google::protobuf::MessageOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::MessageOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::MessageOptions*>(
+      &::google::protobuf::_MessageOptions_default_instance_);
 }
 inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() {
   set_has_options();
@@ -5144,6 +5755,40 @@
 
 // -------------------------------------------------------------------
 
+// ExtensionRangeOptions
+
+// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
+inline int ExtensionRangeOptions::uninterpreted_option_size() const {
+  return uninterpreted_option_.size();
+}
+inline void ExtensionRangeOptions::clear_uninterpreted_option() {
+  uninterpreted_option_.Clear();
+}
+inline const ::google::protobuf::UninterpretedOption& ExtensionRangeOptions::uninterpreted_option(int index) const {
+  // @@protoc_insertion_point(field_get:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_.Get(index);
+}
+inline ::google::protobuf::UninterpretedOption* ExtensionRangeOptions::mutable_uninterpreted_option(int index) {
+  // @@protoc_insertion_point(field_mutable:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_.Mutable(index);
+}
+inline ::google::protobuf::UninterpretedOption* ExtensionRangeOptions::add_uninterpreted_option() {
+  // @@protoc_insertion_point(field_add:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_.Add();
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >*
+ExtensionRangeOptions::mutable_uninterpreted_option() {
+  // @@protoc_insertion_point(field_mutable_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return &uninterpreted_option_;
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >&
+ExtensionRangeOptions::uninterpreted_option() const {
+  // @@protoc_insertion_point(field_list:google.protobuf.ExtensionRangeOptions.uninterpreted_option)
+  return uninterpreted_option_;
+}
+
+// -------------------------------------------------------------------
+
 // FieldDescriptorProto
 
 // optional string name = 1;
@@ -5574,9 +6219,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const {
+  const ::google::protobuf::FieldOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::FieldOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::FieldOptions*>(
+      &::google::protobuf::_FieldOptions_default_instance_);
 }
 inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() {
   set_has_options();
@@ -5686,9 +6332,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::OneofOptions& OneofDescriptorProto::options() const {
+  const ::google::protobuf::OneofOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::OneofOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::OneofOptions*>(
+      &::google::protobuf::_OneofOptions_default_instance_);
 }
 inline ::google::protobuf::OneofOptions* OneofDescriptorProto::mutable_options() {
   set_has_options();
@@ -5828,9 +6475,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const {
+  const ::google::protobuf::EnumOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::EnumOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::EnumOptions*>(
+      &::google::protobuf::_EnumOptions_default_instance_);
 }
 inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() {
   set_has_options();
@@ -5964,9 +6612,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const {
+  const ::google::protobuf::EnumValueOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::EnumValueOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::EnumValueOptions*>(
+      &::google::protobuf::_EnumValueOptions_default_instance_);
 }
 inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() {
   set_has_options();
@@ -6106,9 +6755,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const {
+  const ::google::protobuf::ServiceOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::ServiceOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::ServiceOptions*>(
+      &::google::protobuf::_ServiceOptions_default_instance_);
 }
 inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() {
   set_has_options();
@@ -6344,9 +6994,10 @@
   clear_has_options();
 }
 inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const {
+  const ::google::protobuf::MethodOptions* p = options_;
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options)
-  return options_ != NULL ? *options_
-                         : *::google::protobuf::MethodOptions::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::MethodOptions*>(
+      &::google::protobuf::_MethodOptions_default_instance_);
 }
 inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() {
   set_has_options();
@@ -6554,13 +7205,13 @@
 
 // optional bool java_multiple_files = 10 [default = false];
 inline bool FileOptions::has_java_multiple_files() const {
-  return (_has_bits_[0] & 0x00000080u) != 0;
+  return (_has_bits_[0] & 0x00000100u) != 0;
 }
 inline void FileOptions::set_has_java_multiple_files() {
-  _has_bits_[0] |= 0x00000080u;
+  _has_bits_[0] |= 0x00000100u;
 }
 inline void FileOptions::clear_has_java_multiple_files() {
-  _has_bits_[0] &= ~0x00000080u;
+  _has_bits_[0] &= ~0x00000100u;
 }
 inline void FileOptions::clear_java_multiple_files() {
   java_multiple_files_ = false;
@@ -6578,13 +7229,13 @@
 
 // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
 inline bool FileOptions::has_java_generate_equals_and_hash() const {
-  return (_has_bits_[0] & 0x00000100u) != 0;
+  return (_has_bits_[0] & 0x00000200u) != 0;
 }
 inline void FileOptions::set_has_java_generate_equals_and_hash() {
-  _has_bits_[0] |= 0x00000100u;
+  _has_bits_[0] |= 0x00000200u;
 }
 inline void FileOptions::clear_has_java_generate_equals_and_hash() {
-  _has_bits_[0] &= ~0x00000100u;
+  _has_bits_[0] &= ~0x00000200u;
 }
 inline void FileOptions::clear_java_generate_equals_and_hash() {
   java_generate_equals_and_hash_ = false;
@@ -6602,13 +7253,13 @@
 
 // optional bool java_string_check_utf8 = 27 [default = false];
 inline bool FileOptions::has_java_string_check_utf8() const {
-  return (_has_bits_[0] & 0x00000200u) != 0;
+  return (_has_bits_[0] & 0x00000400u) != 0;
 }
 inline void FileOptions::set_has_java_string_check_utf8() {
-  _has_bits_[0] |= 0x00000200u;
+  _has_bits_[0] |= 0x00000400u;
 }
 inline void FileOptions::clear_has_java_string_check_utf8() {
-  _has_bits_[0] &= ~0x00000200u;
+  _has_bits_[0] &= ~0x00000400u;
 }
 inline void FileOptions::clear_java_string_check_utf8() {
   java_string_check_utf8_ = false;
@@ -6626,13 +7277,13 @@
 
 // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
 inline bool FileOptions::has_optimize_for() const {
-  return (_has_bits_[0] & 0x00008000u) != 0;
+  return (_has_bits_[0] & 0x00020000u) != 0;
 }
 inline void FileOptions::set_has_optimize_for() {
-  _has_bits_[0] |= 0x00008000u;
+  _has_bits_[0] |= 0x00020000u;
 }
 inline void FileOptions::clear_has_optimize_for() {
-  _has_bits_[0] &= ~0x00008000u;
+  _has_bits_[0] &= ~0x00020000u;
 }
 inline void FileOptions::clear_optimize_for() {
   optimize_for_ = 1;
@@ -6714,13 +7365,13 @@
 
 // optional bool cc_generic_services = 16 [default = false];
 inline bool FileOptions::has_cc_generic_services() const {
-  return (_has_bits_[0] & 0x00000400u) != 0;
+  return (_has_bits_[0] & 0x00000800u) != 0;
 }
 inline void FileOptions::set_has_cc_generic_services() {
-  _has_bits_[0] |= 0x00000400u;
+  _has_bits_[0] |= 0x00000800u;
 }
 inline void FileOptions::clear_has_cc_generic_services() {
-  _has_bits_[0] &= ~0x00000400u;
+  _has_bits_[0] &= ~0x00000800u;
 }
 inline void FileOptions::clear_cc_generic_services() {
   cc_generic_services_ = false;
@@ -6738,13 +7389,13 @@
 
 // optional bool java_generic_services = 17 [default = false];
 inline bool FileOptions::has_java_generic_services() const {
-  return (_has_bits_[0] & 0x00000800u) != 0;
+  return (_has_bits_[0] & 0x00001000u) != 0;
 }
 inline void FileOptions::set_has_java_generic_services() {
-  _has_bits_[0] |= 0x00000800u;
+  _has_bits_[0] |= 0x00001000u;
 }
 inline void FileOptions::clear_has_java_generic_services() {
-  _has_bits_[0] &= ~0x00000800u;
+  _has_bits_[0] &= ~0x00001000u;
 }
 inline void FileOptions::clear_java_generic_services() {
   java_generic_services_ = false;
@@ -6762,13 +7413,13 @@
 
 // optional bool py_generic_services = 18 [default = false];
 inline bool FileOptions::has_py_generic_services() const {
-  return (_has_bits_[0] & 0x00001000u) != 0;
+  return (_has_bits_[0] & 0x00002000u) != 0;
 }
 inline void FileOptions::set_has_py_generic_services() {
-  _has_bits_[0] |= 0x00001000u;
+  _has_bits_[0] |= 0x00002000u;
 }
 inline void FileOptions::clear_has_py_generic_services() {
-  _has_bits_[0] &= ~0x00001000u;
+  _has_bits_[0] &= ~0x00002000u;
 }
 inline void FileOptions::clear_py_generic_services() {
   py_generic_services_ = false;
@@ -6784,15 +7435,39 @@
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services)
 }
 
+// optional bool php_generic_services = 19 [default = false];
+inline bool FileOptions::has_php_generic_services() const {
+  return (_has_bits_[0] & 0x00004000u) != 0;
+}
+inline void FileOptions::set_has_php_generic_services() {
+  _has_bits_[0] |= 0x00004000u;
+}
+inline void FileOptions::clear_has_php_generic_services() {
+  _has_bits_[0] &= ~0x00004000u;
+}
+inline void FileOptions::clear_php_generic_services() {
+  php_generic_services_ = false;
+  clear_has_php_generic_services();
+}
+inline bool FileOptions::php_generic_services() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_generic_services)
+  return php_generic_services_;
+}
+inline void FileOptions::set_php_generic_services(bool value) {
+  set_has_php_generic_services();
+  php_generic_services_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_generic_services)
+}
+
 // optional bool deprecated = 23 [default = false];
 inline bool FileOptions::has_deprecated() const {
-  return (_has_bits_[0] & 0x00002000u) != 0;
+  return (_has_bits_[0] & 0x00008000u) != 0;
 }
 inline void FileOptions::set_has_deprecated() {
-  _has_bits_[0] |= 0x00002000u;
+  _has_bits_[0] |= 0x00008000u;
 }
 inline void FileOptions::clear_has_deprecated() {
-  _has_bits_[0] &= ~0x00002000u;
+  _has_bits_[0] &= ~0x00008000u;
 }
 inline void FileOptions::clear_deprecated() {
   deprecated_ = false;
@@ -6810,13 +7485,13 @@
 
 // optional bool cc_enable_arenas = 31 [default = false];
 inline bool FileOptions::has_cc_enable_arenas() const {
-  return (_has_bits_[0] & 0x00004000u) != 0;
+  return (_has_bits_[0] & 0x00010000u) != 0;
 }
 inline void FileOptions::set_has_cc_enable_arenas() {
-  _has_bits_[0] |= 0x00004000u;
+  _has_bits_[0] |= 0x00010000u;
 }
 inline void FileOptions::clear_has_cc_enable_arenas() {
-  _has_bits_[0] &= ~0x00004000u;
+  _has_bits_[0] &= ~0x00010000u;
 }
 inline void FileOptions::clear_cc_enable_arenas() {
   cc_enable_arenas_ = false;
@@ -7084,6 +7759,69 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_class_prefix)
 }
 
+// optional string php_namespace = 41;
+inline bool FileOptions::has_php_namespace() const {
+  return (_has_bits_[0] & 0x00000080u) != 0;
+}
+inline void FileOptions::set_has_php_namespace() {
+  _has_bits_[0] |= 0x00000080u;
+}
+inline void FileOptions::clear_has_php_namespace() {
+  _has_bits_[0] &= ~0x00000080u;
+}
+inline void FileOptions::clear_php_namespace() {
+  php_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  clear_has_php_namespace();
+}
+inline const ::std::string& FileOptions::php_namespace() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace)
+  return php_namespace_.GetNoArena();
+}
+inline void FileOptions::set_php_namespace(const ::std::string& value) {
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace)
+}
+#if LANG_CXX11
+inline void FileOptions::set_php_namespace(::std::string&& value) {
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace)
+}
+#endif
+inline void FileOptions::set_php_namespace(const char* value) {
+  GOOGLE_DCHECK(value != NULL);
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
+  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace)
+}
+inline void FileOptions::set_php_namespace(const char* value, size_t size) {
+  set_has_php_namespace();
+  php_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
+      ::std::string(reinterpret_cast<const char*>(value), size));
+  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace)
+}
+inline ::std::string* FileOptions::mutable_php_namespace() {
+  set_has_php_namespace();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.php_namespace)
+  return php_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline ::std::string* FileOptions::release_php_namespace() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace)
+  clear_has_php_namespace();
+  return php_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+inline void FileOptions::set_allocated_php_namespace(::std::string* php_namespace) {
+  if (php_namespace != NULL) {
+    set_has_php_namespace();
+  } else {
+    clear_has_php_namespace();
+  }
+  php_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), php_namespace);
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.php_namespace)
+}
+
 // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
 inline int FileOptions::uninterpreted_option_size() const {
   return uninterpreted_option_.size();
@@ -8597,6 +9335,9 @@
   return annotation_;
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 // -------------------------------------------------------------------
 
@@ -8646,6 +9387,8 @@
 
 // -------------------------------------------------------------------
 
+// -------------------------------------------------------------------
+
 
 // @@protoc_insertion_point(namespace_scope)
 
@@ -8653,7 +9396,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#ifndef SWIG
 namespace google {
 namespace protobuf {
 
@@ -8690,7 +9432,6 @@
 
 }  // namespace protobuf
 }  // namespace google
-#endif  // SWIG
 
 // @@protoc_insertion_point(global_scope)
 
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index f859c42..f1ec573 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -101,6 +101,8 @@
   message ExtensionRange {
     optional int32 start = 1;
     optional int32 end = 2;
+
+    optional ExtensionRangeOptions options = 3;
   }
   repeated ExtensionRange extension_range = 5;
 
@@ -121,6 +123,14 @@
   repeated string reserved_name = 10;
 }
 
+message ExtensionRangeOptions {
+  // The parser stores options it doesn't recognize here. See above.
+  repeated UninterpretedOption uninterpreted_option = 999;
+
+  // Clients can define custom options in extensions of this message. See above.
+  extensions 1000 to max;
+}
+
 // Describes a field within a message.
 message FieldDescriptorProto {
   enum Type {
@@ -351,6 +361,7 @@
   optional bool cc_generic_services = 16 [default=false];
   optional bool java_generic_services = 17 [default=false];
   optional bool py_generic_services = 18 [default=false];
+  optional bool php_generic_services = 19 [default=false];
 
   // Is this file deprecated?
   // Depending on the target platform, this can emit Deprecated annotations
@@ -380,6 +391,11 @@
   // from this .proto. Default is empty.
   optional string php_class_prefix = 40;
 
+  // Use this option to change the namespace of php generated classes. Default
+  // is empty. When this option is empty, the package name will be used for
+  // determining the namespace.
+  optional string php_namespace = 41;
+
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
@@ -477,13 +493,15 @@
 
   // The jstype option determines the JavaScript type used for values of the
   // field.  The option is permitted only for 64 bit integral and fixed types
-  // (int64, uint64, sint64, fixed64, sfixed64).  By default these types are
-  // represented as JavaScript strings.  This avoids loss of precision that can
-  // happen when a large value is converted to a floating point JavaScript
-  // numbers.  Specifying JS_NUMBER for the jstype causes the generated
-  // JavaScript code to use the JavaScript "number" type instead of strings.
-  // This option is an enum to permit additional types to be added,
-  // e.g. goog.math.Integer.
+  // (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+  // is represented as JavaScript string, which avoids loss of precision that
+  // can happen when a large value is converted to a floating point JavaScript.
+  // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+  // use the JavaScript "number" type.  The behavior of the default option
+  // JS_NORMAL is implementation dependent.
+  //
+  // This option is an enum to permit additional types to be added, e.g.
+  // goog.math.Integer.
   optional JSType jstype = 6 [default = JS_NORMAL];
   enum JSType {
     // Use the default type.
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 4e46b2a..ba85ef1 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -39,8 +39,9 @@
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 #include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stl_util.h>
+
 #include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/stl_util.h>
 
 namespace google {
 namespace protobuf {
@@ -230,7 +231,7 @@
     const string& sub_symbol, const string& super_symbol) {
   return sub_symbol == super_symbol ||
          (HasPrefixString(super_symbol, sub_symbol) &&
-             super_symbol[sub_symbol.size()] == '.');
+          super_symbol[sub_symbol.size()] == '.');
 }
 
 template <typename Value>
diff --git a/src/google/protobuf/drop_unknown_fields_test.cc b/src/google/protobuf/drop_unknown_fields_test.cc
index 6f16dc5..f2f2f74 100644
--- a/src/google/protobuf/drop_unknown_fields_test.cc
+++ b/src/google/protobuf/drop_unknown_fields_test.cc
@@ -35,6 +35,7 @@
 
 #include <google/protobuf/unittest_drop_unknown_fields.pb.h>
 #include <google/protobuf/dynamic_message.h>
+#include <google/protobuf/message_lite.h>
 #include <gtest/gtest.h>
 
 namespace google {
@@ -43,7 +44,8 @@
 
 namespace protobuf {
 
-TEST(DropUnknownFieldsTest, GeneratedMessage) {
+TEST(DropUnknownFieldsTest, GeneratedMessageDefaultDrop) {
+  ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(false);
   FooWithExtraFields foo_with_extra_fields;
   foo_with_extra_fields.set_int32_value(1);
   foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
@@ -54,8 +56,6 @@
   EXPECT_EQ(1, foo.int32_value());
   EXPECT_EQ(static_cast<int>(FooWithExtraFields::QUX),
             static_cast<int>(foo.enum_value()));
-  // We don't generate unknown field accessors but the UnknownFieldSet is
-  // still exposed through reflection API.
   EXPECT_TRUE(foo.GetReflection()->GetUnknownFields(foo).empty());
 
   ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo.SerializeAsString()));
@@ -65,7 +65,29 @@
   EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value());
 }
 
-TEST(DropUnknownFieldsTest, DynamicMessage) {
+TEST(DropUnknownFieldsTest, GeneratedMessageDefaultPreserve) {
+  ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(true);
+  FooWithExtraFields foo_with_extra_fields;
+  foo_with_extra_fields.set_int32_value(1);
+  foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
+  foo_with_extra_fields.set_extra_int32_value(2);
+
+  Foo foo;
+  ASSERT_TRUE(foo.ParseFromString(foo_with_extra_fields.SerializeAsString()));
+  EXPECT_EQ(1, foo.int32_value());
+  EXPECT_EQ(static_cast<int>(FooWithExtraFields::QUX),
+            static_cast<int>(foo.enum_value()));
+  EXPECT_FALSE(foo.GetReflection()->GetUnknownFields(foo).empty());
+
+  ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo.SerializeAsString()));
+  EXPECT_EQ(1, foo_with_extra_fields.int32_value());
+  EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value());
+  // The "extra_int32_value" field should not be lost.
+  EXPECT_EQ(2, foo_with_extra_fields.extra_int32_value());
+}
+
+TEST(DropUnknownFieldsTest, DynamicMessageDefaultDrop) {
+  internal::SetProto3PreserveUnknownsDefault(false);
   FooWithExtraFields foo_with_extra_fields;
   foo_with_extra_fields.set_int32_value(1);
   foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
@@ -84,5 +106,25 @@
   EXPECT_EQ(0, foo_with_extra_fields.extra_int32_value());
 }
 
+TEST(DropUnknownFieldsTest, DynamicMessageDefaultPreserve) {
+  internal::SetProto3PreserveUnknownsDefault(true);
+  FooWithExtraFields foo_with_extra_fields;
+  foo_with_extra_fields.set_int32_value(1);
+  foo_with_extra_fields.set_enum_value(FooWithExtraFields::QUX);
+  foo_with_extra_fields.set_extra_int32_value(2);
+
+  google::protobuf::DynamicMessageFactory factory;
+  google::protobuf::scoped_ptr<google::protobuf::Message> foo(
+      factory.GetPrototype(Foo::descriptor())->New());
+  ASSERT_TRUE(foo->ParseFromString(foo_with_extra_fields.SerializeAsString()));
+  EXPECT_FALSE(foo->GetReflection()->GetUnknownFields(*foo).empty());
+
+  ASSERT_TRUE(foo_with_extra_fields.ParseFromString(foo->SerializeAsString()));
+  EXPECT_EQ(1, foo_with_extra_fields.int32_value());
+  EXPECT_EQ(FooWithExtraFields::QUX, foo_with_extra_fields.enum_value());
+  // The "extra_int32_value" field should not be lost.
+  EXPECT_EQ(2, foo_with_extra_fields.extra_int32_value());
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index ae1a5e0..ad0eeb4 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -19,7 +19,10 @@
 
 namespace google {
 namespace protobuf {
-class DurationDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Duration> {
+class DurationDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Duration>
+     _instance;
 } _Duration_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fduration_2eproto {
@@ -32,20 +35,20 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -54,8 +57,7 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, seconds_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Duration, nanos_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Duration)},
 };
 
@@ -85,26 +87,22 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Duration_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _Duration_default_instance_.DefaultConstruct();
-}
+  _Duration_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Duration_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\036google/protobuf/duration.proto\022\017google"
       ".protobuf\"*\n\010Duration\022\017\n\007seconds\030\001 \001(\003\022\r"
       "\n\005nanos\030\002 \001(\005B|\n\023com.google.protobufB\rDu"
@@ -116,14 +114,14 @@
       descriptor, 227);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/duration.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -151,9 +149,7 @@
 Duration::Duration(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fduration_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Duration)
@@ -164,14 +160,15 @@
       _cached_size_(0) {
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   ::memcpy(&seconds_, &from.seconds_,
-    reinterpret_cast<char*>(&nanos_) -
-    reinterpret_cast<char*>(&seconds_) + sizeof(nanos_));
+    static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Duration)
 }
 
 void Duration::SharedCtor() {
-  ::memset(&seconds_, 0, reinterpret_cast<char*>(&nanos_) -
-    reinterpret_cast<char*>(&seconds_) + sizeof(nanos_));
+  ::memset(&seconds_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&nanos_) -
+      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
   _cached_size_ = 0;
 }
 
@@ -182,6 +179,7 @@
 
 void Duration::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -215,8 +213,14 @@
 
 void Duration::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
-  ::memset(&seconds_, 0, reinterpret_cast<char*>(&nanos_) -
-    reinterpret_cast<char*>(&seconds_) + sizeof(nanos_));
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  ::memset(&seconds_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&nanos_) -
+      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+  _internal_metadata_.Clear();
 }
 
 bool Duration::MergePartialFromCodedStream(
@@ -232,7 +236,7 @@
       // int64 seconds = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
@@ -246,7 +250,7 @@
       // int32 nanos = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -259,12 +263,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -294,11 +297,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Duration)
 }
 
 ::google::protobuf::uint8* Duration::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -313,6 +321,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Duration)
   return target;
 }
@@ -321,6 +333,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // int64 seconds = 1;
   if (this->seconds() != 0) {
     total_size += 1 +
@@ -410,9 +427,11 @@
   InternalSwap(other);
 }
 void Duration::InternalSwap(Duration* other) {
-  std::swap(seconds_, other->seconds_);
-  std::swap(nanos_, other->nanos_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(seconds_, other->seconds_);
+  swap(nanos_, other->nanos_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Duration::GetMetadata() const {
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index 34873d9..bed112b 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -48,8 +48,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -68,7 +69,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Duration(Duration&& from) noexcept
+    : Duration() {
+    *this = ::std::move(from);
+  }
 
+  inline Duration& operator=(Duration&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -87,6 +102,9 @@
 
   void UnsafeArenaSwap(Duration* other);
   void Swap(Duration* other);
+  friend void swap(Duration& a, Duration& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -149,7 +167,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::int64 seconds_;
@@ -163,6 +181,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Duration
 
 // int64 seconds = 1;
@@ -193,6 +215,9 @@
   // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index ee8113e..cdd4324 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -250,6 +250,10 @@
   };
 
   DynamicMessage(const TypeInfo* type_info);
+
+  // This should only be used by GetPrototypeNoLock() to avoid dead lock.
+  DynamicMessage(const TypeInfo* type_info, bool lock_factory);
+
   ~DynamicMessage();
 
   // Called on the prototype after construction to initialize message fields.
@@ -280,7 +284,8 @@
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
   DynamicMessage(const TypeInfo* type_info, ::google::protobuf::Arena* arena);
-  void SharedCtor();
+
+  void SharedCtor(bool lock_factory);
 
   inline bool is_prototype() const {
     return type_info_->prototype == this ||
@@ -304,17 +309,22 @@
 DynamicMessage::DynamicMessage(const TypeInfo* type_info)
   : type_info_(type_info),
     cached_byte_size_(0) {
-  SharedCtor();
+  SharedCtor(true);
 }
 
 DynamicMessage::DynamicMessage(const TypeInfo* type_info,
                                ::google::protobuf::Arena* arena)
   : type_info_(type_info),
     cached_byte_size_(0) {
-  SharedCtor();
+  SharedCtor(true);
 }
 
-void DynamicMessage::SharedCtor() {
+DynamicMessage::DynamicMessage(const TypeInfo* type_info, bool lock_factory)
+    : type_info_(type_info), cached_byte_size_(0) {
+  SharedCtor(lock_factory);
+}
+
+void DynamicMessage::SharedCtor(bool lock_factory) {
   // We need to call constructors for various fields manually and set
   // default values where appropriate.  We use placement new to call
   // constructors.  If you haven't heard of placement new, I suggest Googling
@@ -398,8 +408,17 @@
           new(field_ptr) Message*(NULL);
         } else {
           if (IsMapFieldInApi(field)) {
-            new (field_ptr) DynamicMapField(
-                type_info_->factory->GetPrototypeNoLock(field->message_type()));
+            // We need to lock in most cases to avoid data racing. Only not lock
+            // when the constructor is called inside GetPrototype(), in which
+            // case we have already locked the factory.
+            if (lock_factory) {
+              new (field_ptr) DynamicMapField(
+                  type_info_->factory->GetPrototype(field->message_type()));
+            } else {
+              new (field_ptr)
+                  DynamicMapField(type_info_->factory->GetPrototypeNoLock(
+                      field->message_type()));
+            }
           } else {
             new (field_ptr) RepeatedPtrField<Message>();
           }
@@ -751,7 +770,10 @@
   // map). To break the cyclic dependency, we have to assgin the address of
   // prototype into type_info first.
   type_info->prototype = static_cast<DynamicMessage*>(base);
-  DynamicMessage* prototype = new(base) DynamicMessage(type_info);
+
+  // We have already locked the factory so we should not lock in the constructor
+  // of dynamic message to avoid dead lock.
+  DynamicMessage* prototype = new (base) DynamicMessage(type_info, false);
 
   if (type->oneof_decl_count() > 0 || num_weak_fields > 0) {
     // Construct default oneof instance.
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index 816170e..e29b148 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -156,24 +156,24 @@
                                           int map_size,
                                           const Reflection* reflection,
                                           const FieldDescriptor* field) {
-    std::vector<const Message*> result(map_size);
+    std::vector<const Message*> result(static_cast<size_t>(map_size));
     const RepeatedPtrField<Message>& map_field =
         reflection->GetRepeatedPtrField<Message>(message, field);
-    int i = 0;
+    size_t i = 0;
     for (RepeatedPtrField<Message>::const_pointer_iterator it =
              map_field.pointer_begin(); it != map_field.pointer_end(); ) {
       result[i++] = *it++;
     }
-    GOOGLE_DCHECK_EQ(result.size(), static_cast<size_t>(i));
+    GOOGLE_DCHECK_EQ(result.size(), i);
     MapEntryMessageComparator comparator(field->message_type());
-    std::sort(result.begin(), result.end(), comparator);
+    std::stable_sort(result.begin(), result.end(), comparator);
     // Complain if the keys aren't in ascending order.
 #ifndef NDEBUG
-    for (int j = 1; j < map_size; j++) {
+    for (size_t j = 1; j < static_cast<size_t>(map_size); j++) {
       if (!comparator(result[j - 1], result[j])) {
         GOOGLE_LOG(ERROR) << (comparator(result[j], result[j - 1]) ?
-                       "internal error in map key sorting" :
-                       "map keys are not unique");
+                      "internal error in map key sorting" :
+                      "map keys are not unique");
       }
     }
 #endif
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 7119505..6d2ea33 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -19,7 +19,10 @@
 
 namespace google {
 namespace protobuf {
-class EmptyDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Empty> {
+class EmptyDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Empty>
+     _instance;
 } _Empty_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fempty_2eproto {
@@ -32,28 +35,27 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Empty, _internal_metadata_),
   ~0u,  // no _extensions_
   ~0u,  // no _oneof_case_
   ~0u,  // no _weak_field_map_
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Empty)},
 };
 
@@ -83,26 +85,22 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Empty_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _Empty_default_instance_.DefaultConstruct();
-}
+  _Empty_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Empty_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\033google/protobuf/empty.proto\022\017google.pr"
       "otobuf\"\007\n\005EmptyBv\n\023com.google.protobufB\n"
       "EmptyProtoP\001Z\'github.com/golang/protobuf"
@@ -113,14 +111,14 @@
       descriptor, 183);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/empty.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -146,9 +144,7 @@
 Empty::Empty(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fempty_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Empty)
@@ -172,6 +168,7 @@
 
 void Empty::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -205,6 +202,11 @@
 
 void Empty::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Empty)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _internal_metadata_.Clear();
 }
 
 bool Empty::MergePartialFromCodedStream(
@@ -217,12 +219,11 @@
     tag = p.first;
     if (!p.second) goto handle_unusual;
   handle_unusual:
-    if (tag == 0 ||
-        ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-        ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+    if (tag == 0) {
       goto success;
     }
-    DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+    DO_(::google::protobuf::internal::WireFormat::SkipField(
+          input, tag, _internal_metadata_.mutable_unknown_fields()));
   }
 success:
   // @@protoc_insertion_point(parse_success:google.protobuf.Empty)
@@ -239,15 +240,24 @@
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Empty)
 }
 
 ::google::protobuf::uint8* Empty::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Empty)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Empty)
   return target;
 }
@@ -256,6 +266,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Empty)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
   GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
   _cached_size_ = cached_size;
@@ -325,7 +340,9 @@
   InternalSwap(other);
 }
 void Empty::InternalSwap(Empty* other) {
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Empty::GetMetadata() const {
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index f28dc19..1c6e53e 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -48,8 +48,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -68,7 +69,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Empty(Empty&& from) noexcept
+    : Empty() {
+    *this = ::std::move(from);
+  }
 
+  inline Empty& operator=(Empty&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -87,6 +102,9 @@
 
   void UnsafeArenaSwap(Empty* other);
   void Swap(Empty* other);
+  friend void swap(Empty& a, Empty& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -137,7 +155,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   mutable int _cached_size_;
@@ -149,8 +167,15 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Empty
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index cf5f652..6f47c4a 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -438,6 +438,11 @@
   // SpaceUsed()).
   size_t SpaceUsedExcludingSelfLong() const;
 
+  // This method just calls SpaceUsedExcludingSelfLong() but it can not be
+  // inlined because the definition of SpaceUsedExcludingSelfLong() is not
+  // included in lite runtime and when an inline method refers to it MSVC
+  // will complain about unresolved symbols when building the lite runtime
+  // as .dll.
   int SpaceUsedExcludingSelf() const;
 
  private:
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 772d273..3e71b25 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -32,6 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/extension_set.h>
 #include <google/protobuf/unittest.pb.h>
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 094c4cc..afc3db5 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -19,7 +19,10 @@
 
 namespace google {
 namespace protobuf {
-class FieldMaskDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FieldMask> {
+class FieldMaskDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FieldMask>
+     _instance;
 } _FieldMask_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2ffield_5fmask_2eproto {
@@ -32,20 +35,20 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -53,8 +56,7 @@
   ~0u,  // no _weak_field_map_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldMask, paths_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(FieldMask)},
 };
 
@@ -84,26 +86,22 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _FieldMask_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _FieldMask_default_instance_.DefaultConstruct();
-}
+  _FieldMask_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FieldMask_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n google/protobuf/field_mask.proto\022\017goog"
       "le.protobuf\"\032\n\tFieldMask\022\r\n\005paths\030\001 \003(\tB"
       "\211\001\n\023com.google.protobufB\016FieldMaskProtoP"
@@ -115,14 +113,14 @@
       descriptor, 227);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/field_mask.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -192,7 +190,12 @@
 
 void FieldMask::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   paths_.Clear();
+  _internal_metadata_.Clear();
 }
 
 bool FieldMask::MergePartialFromCodedStream(
@@ -208,12 +211,12 @@
       // repeated string paths = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_paths()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
             this->paths(this->paths_size() - 1).data(),
-            this->paths(this->paths_size() - 1).length(),
+            static_cast<int>(this->paths(this->paths_size() - 1).length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.FieldMask.paths"));
         } else {
@@ -224,12 +227,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -252,18 +254,23 @@
   // repeated string paths = 1;
   for (int i = 0, n = this->paths_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->paths(i).data(), this->paths(i).length(),
+      this->paths(i).data(), static_cast<int>(this->paths(i).length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.FieldMask.paths");
     ::google::protobuf::internal::WireFormatLite::WriteString(
       1, this->paths(i), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FieldMask)
 }
 
 ::google::protobuf::uint8* FieldMask::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -271,13 +278,17 @@
   // repeated string paths = 1;
   for (int i = 0, n = this->paths_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->paths(i).data(), this->paths(i).length(),
+      this->paths(i).data(), static_cast<int>(this->paths(i).length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.FieldMask.paths");
     target = ::google::protobuf::internal::WireFormatLite::
       WriteStringToArray(1, this->paths(i), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldMask)
   return target;
 }
@@ -286,6 +297,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated string paths = 1;
   total_size += 1 *
       ::google::protobuf::internal::FromIntSize(this->paths_size());
@@ -349,8 +365,10 @@
   InternalSwap(other);
 }
 void FieldMask::InternalSwap(FieldMask* other) {
+  using std::swap;
   paths_.InternalSwap(&other->paths_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata FieldMask::GetMetadata() const {
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index 742c1cf..b8f1038 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -48,8 +48,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -68,7 +69,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FieldMask(FieldMask&& from) noexcept
+    : FieldMask() {
+    *this = ::std::move(from);
+  }
 
+  inline FieldMask& operator=(FieldMask&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   static const ::google::protobuf::Descriptor* descriptor();
   static const FieldMask& default_instance();
 
@@ -80,6 +95,9 @@
     0;
 
   void Swap(FieldMask* other);
+  friend void swap(FieldMask& a, FieldMask& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -157,6 +175,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // FieldMask
 
 // repeated string paths = 1;
@@ -228,6 +250,9 @@
   return &paths_;
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 9aebd90..263d52a 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -44,7 +44,7 @@
 #include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/map_field.h>
 #include <google/protobuf/repeated_field.h>
-// #include "google/protobuf/bridge/compatibility_mode_support.h"
+#include <google/protobuf/wire_format.h>
 
 
 #define GOOGLE_PROTOBUF_HAS_ONEOF
@@ -197,32 +197,14 @@
 
 GeneratedMessageReflection::~GeneratedMessageReflection() {}
 
-namespace {
-UnknownFieldSet* empty_unknown_field_set_ = NULL;
-GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_);
-
-void DeleteEmptyUnknownFieldSet() {
-  delete empty_unknown_field_set_;
-  empty_unknown_field_set_ = NULL;
-}
-
-void InitEmptyUnknownFieldSet() {
-  empty_unknown_field_set_ = new UnknownFieldSet;
-  internal::OnShutdown(&DeleteEmptyUnknownFieldSet);
-}
-
-const UnknownFieldSet& GetEmptyUnknownFieldSet() {
-  ::google::protobuf::GoogleOnceInit(&empty_unknown_field_set_once_, &InitEmptyUnknownFieldSet);
-  return *empty_unknown_field_set_;
-}
-}  // namespace
-
 const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
     const Message& message) const {
-  if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+  if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+      !GetProto3PreserveUnknownsDefault()) {
     // We have to ensure that any mutations made to the return value of
-    // MutableUnknownFields() are not reflected here.
-    return GetEmptyUnknownFieldSet();
+    // MutableUnknownFields() are not reflected here when Proto3 defaults to
+    // discard unknowns.
+    return *UnknownFieldSet::default_instance();
   } else {
     return GetInternalMetadataWithArena(message).unknown_fields();
   }
@@ -1020,7 +1002,7 @@
       schema_.HasHasbits() ? GetHasBits(message) : NULL;
   const uint32* const has_bits_indices = schema_.has_bit_indices_;
   const uint32* const oneof_case_array =
-      &GetConstRefAtOffset<uint32>(message, schema_.oneof_case_offset_);
+      GetConstPointerAtOffset<uint32>(&message, schema_.oneof_case_offset_);
   output->reserve(descriptor_->field_count());
   for (int i = 0; i <= last_non_weak_field_index_; i++) {
     const FieldDescriptor* field = descriptor_->field(i);
@@ -2288,6 +2270,8 @@
     file_level_enum_descriptors_++;
   }
 
+  const Metadata* GetCurrentMetadataPtr() const { return file_level_metadata_; }
+
  private:
   MessageFactory* factory_;
   Metadata* file_level_metadata_;
@@ -2297,6 +2281,41 @@
   const uint32* offsets_;
 };
 
+// We have the routines that assign descriptors and build reflection
+// automatically delete the allocated reflection. MetadataOwner owns
+// all the allocated reflection instances.
+struct MetadataOwner {
+  void AddArray(const Metadata* begin, const Metadata* end) {
+    MutexLock lock(&mu_);
+    metadata_arrays_.push_back(std::make_pair(begin, end));
+  }
+
+  static MetadataOwner* Instance() {
+    static MetadataOwner* res = new MetadataOwner;
+    return res;
+  }
+
+ private:
+  // Use the constructor to register the shutdown code. Because c++ makes sure
+  // this called only once.
+  MetadataOwner() { OnShutdown(&DeleteMetadata); }
+  ~MetadataOwner() {
+    for (int i = 0; i < metadata_arrays_.size(); i++) {
+      for (const Metadata* m = metadata_arrays_[i].first;
+           m < metadata_arrays_[i].second; m++) {
+        delete m->reflection;
+      }
+    }
+  }
+
+  static void DeleteMetadata() {
+    delete Instance();
+  }
+
+  Mutex mu_;
+  std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;
+};
+
 }  // namespace
 
 void AssignDescriptors(
@@ -2329,6 +2348,8 @@
       file_level_service_descriptors[i] = file->service(i);
     }
   }
+  MetadataOwner::Instance()->AddArray(
+      file_level_metadata, helper.GetCurrentMetadataPtr());
 }
 
 void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) {
@@ -2349,6 +2370,18 @@
   RegisterAllTypesInternal(file_level_metadata, size);
 }
 
+void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag,
+                               uint32 has_offset,
+                               ::google::protobuf::io::CodedOutputStream* output) {
+  const void* ptr = base + offset;
+  const InternalMetadataWithArena* metadata =
+      static_cast<const InternalMetadataWithArena*>(ptr);
+  if (metadata->have_unknown_fields()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        metadata->unknown_fields(), output);
+  }
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 12b73ca..f6ce16a 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -129,7 +129,7 @@
 struct ReflectionSchema {
  public:
   // Size of a google::protobuf::Message object of this type.
-  uint32 GetObjectSize() const { return object_size_; }
+  uint32 GetObjectSize() const { return static_cast<uint32>(object_size_); }
 
   // Offset of a non-oneof field.  Getting a field offset is slightly more
   // efficient when we know statically that it is not a oneof field.
@@ -141,8 +141,9 @@
   // Offset of any field.
   uint32 GetFieldOffset(const FieldDescriptor* field) const {
     if (field->containing_oneof()) {
-      size_t offset = field->containing_type()->field_count() +
-                      field->containing_oneof()->index();
+      size_t offset =
+          static_cast<size_t>(field->containing_type()->field_count() +
+          field->containing_oneof()->index());
       return offsets_[offset];
     } else {
       return GetFieldOffsetNonOneof(field);
@@ -150,7 +151,9 @@
   }
 
   uint32 GetOneofCaseOffset(const OneofDescriptor* oneof_descriptor) const {
-    return oneof_case_offset_ + (oneof_descriptor->index() * sizeof(uint32));
+    return static_cast<uint32>(oneof_case_offset_) +
+           static_cast<uint32>(
+               static_cast<size_t>(oneof_descriptor->index()) * sizeof(uint32));
   }
 
   bool HasHasbits() const { return has_bits_offset_ != -1; }
@@ -164,7 +167,7 @@
   // Byte offset of the hasbits array.
   uint32 HasBitsOffset() const {
     GOOGLE_DCHECK(HasHasbits());
-    return has_bits_offset_;
+    return static_cast<uint32>(has_bits_offset_);
   }
 
   // The offset of the InternalMetadataWithArena member.
@@ -172,7 +175,7 @@
   // The schema doesn't contain enough information to distinguish between
   // these two cases.
   uint32 GetMetadataOffset() const {
-    return metadata_offset_;
+    return static_cast<uint32>(metadata_offset_);
   }
 
   // Whether this message has an ExtensionSet.
@@ -181,7 +184,7 @@
   // The offset of the ExtensionSet in this message.
   uint32 GetExtensionSetOffset() const {
     GOOGLE_DCHECK(HasExtensionSet());
-    return extensions_offset_;
+    return static_cast<uint32>(extensions_offset_);
   }
 
   // The off set of WeakFieldMap when the message contains weak fields.
@@ -714,6 +717,11 @@
 
 LIBPROTOBUF_EXPORT void RegisterAllTypes(const Metadata* file_level_metadata, int size);
 
+// These cannot be in lite so we put them in the reflection.
+LIBPROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset, uint32 tag,
+                               uint32 has_offset,
+                               ::google::protobuf::io::CodedOutputStream* output);
+
 }  // namespace internal
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/generated_message_table_driven.cc b/src/google/protobuf/generated_message_table_driven.cc
index e281266..29af1ef 100644
--- a/src/google/protobuf/generated_message_table_driven.cc
+++ b/src/google/protobuf/generated_message_table_driven.cc
@@ -32,643 +32,70 @@
 
 #include <google/protobuf/stubs/type_traits.h>
 
+#include <google/protobuf/generated_message_table_driven_lite.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/metadata.h>
 #include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format.h>
 #include <google/protobuf/wire_format_lite.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 
-
 namespace google {
 namespace protobuf {
 namespace internal {
 
-
 namespace {
 
-enum StringType {
-  StringType_STRING = 0,
-  StringType_CORD = 1,
-  StringType_STRING_PIECE = 2
-};
-
-template <typename Type>
-inline Type* Raw(MessageLite* msg, int64 offset) {
-  return reinterpret_cast<Type*>(reinterpret_cast<uint8*>(msg) + offset);
-}
-
-template <typename Type>
-inline const Type* Raw(const MessageLite* msg, int64 offset) {
-  return reinterpret_cast<const Type*>(reinterpret_cast<const uint8*>(msg) +
-                                       offset);
-}
-
-inline Arena* GetArena(MessageLite* msg, int64 arena_offset) {
-  if (GOOGLE_PREDICT_FALSE(arena_offset == -1)) {
-    return NULL;
-  }
-
-  return Raw<InternalMetadataWithArenaLite>(msg, arena_offset)->arena();
-}
-
-template <typename Type>
-inline Type* AddField(MessageLite* msg, int64 offset) {
-#if LANG_CXX11
-  static_assert(std::is_trivially_copy_assignable<Type>::value,
-                "Do not assign");
-#endif
-
-  google::protobuf::RepeatedField<Type>* repeated =
-      Raw<google::protobuf::RepeatedField<Type> >(msg, offset);
-  return repeated->Add();
-}
-
-template <>
-inline string* AddField<string>(MessageLite* msg, int64 offset) {
-  google::protobuf::RepeatedPtrField<string>* repeated =
-      Raw<google::protobuf::RepeatedPtrField<string> >(msg, offset);
-  return repeated->Add();
-}
-
-
-template <typename Type>
-inline void AddField(MessageLite* msg, int64 offset, Type value) {
-#if LANG_CXX11
-  static_assert(std::is_trivially_copy_assignable<Type>::value,
-                "Do not assign");
-#endif
-  *AddField<Type>(msg, offset) = value;
-}
-
-inline void SetBit(uint32* has_bits, uint32 has_bit_index) {
-  GOOGLE_DCHECK(has_bits != NULL);
-
-  uint32 mask = static_cast<uint32>(1u) << (has_bit_index % 32);
-  has_bits[has_bit_index / 32u] |= mask;
-}
-
-template <typename Type>
-inline Type* MutableField(MessageLite* msg, uint32* has_bits,
-                          uint32 has_bit_index, int64 offset) {
-  SetBit(has_bits, has_bit_index);
-  return Raw<Type>(msg, offset);
-}
-
-template <typename Type>
-inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
-                     int64 offset, Type value) {
-#if LANG_CXX11
-  static_assert(std::is_trivially_copy_assignable<Type>::value,
-                "Do not assign");
-#endif
-  *MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
-}
-
-template <bool repeated, bool validate, StringType ctype>
-static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg,
-                                Arena* arena, uint32* has_bits,
-                                uint32 has_bit_index, int64 offset,
-                                const void* default_ptr, bool strict_utf8,
-                                const char* field_name) {
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  const char* sdata;
-  size_t size;
-#endif
-
-    string* value;
-    if (repeated) {
-      value = AddField<string>(msg, offset);
-      GOOGLE_DCHECK(value != NULL);
-    } else {
-      // TODO(ckennelly): Is this optimal?
-      value = MutableField<ArenaStringPtr>(msg, has_bits, has_bit_index, offset)
-                  ->Mutable(static_cast<const string*>(default_ptr), arena);
-      GOOGLE_DCHECK(value != NULL);
-    }
-
-    if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) {
-      return false;
-    }
-
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-    sdata = value->data();
-    size = value->size();
-#endif
-
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-  if (validate) {
-    if (strict_utf8) {
-      if (GOOGLE_PREDICT_FALSE(!WireFormatLite::VerifyUtf8String(
-              sdata, size, WireFormatLite::PARSE, field_name))) {
-        return false;
-      }
-    } else {
-      WireFormatLite::VerifyUTF8String(
-          sdata, size, WireFormat::PARSE, field_name);
-    }
-  }
-#endif
-
-  return true;
-}
-
-string* MutableUnknownFields(MessageLite* msg, int64 arena_offset) {
-  return Raw<InternalMetadataWithArenaLite>(msg, arena_offset)
+UnknownFieldSet* MutableUnknownFields(MessageLite* msg, int64 arena_offset) {
+  return Raw<InternalMetadataWithArena>(msg, arena_offset)
       ->mutable_unknown_fields();
 }
 
-// RepeatedMessageTypeHandler allows us to operate on RepeatedPtrField fields
-// without instantiating the specific template.
-class RepeatedMessageTypeHandler {
- public:
-  typedef MessageLite Type;
-  static Arena* GetArena(Type* t) { return t->GetArena(); }
-  static void* GetMaybeArenaPointer(Type* t) {
-    return t->GetMaybeArenaPointer();
+struct UnknownFieldHandler {
+  static bool Skip(MessageLite* msg, const ParseTable& table,
+                   io::CodedInputStream* input,
+                   int tag) {
+    GOOGLE_DCHECK(table.unknown_field_set);
+
+    return WireFormat::SkipField(input, tag,
+        MutableUnknownFields(msg, table.arena_offset));
   }
-  static inline Type* NewFromPrototype(const Type* prototype,
-                                       Arena* arena = NULL) {
-    return prototype->New(arena);
+
+  static void Varint(MessageLite* msg, const ParseTable& table,
+                     int tag, int value) {
+    GOOGLE_DCHECK(table.unknown_field_set);
+
+    MutableUnknownFields(msg, table.arena_offset)->AddVarint(
+        WireFormatLite::GetTagFieldNumber(tag), value);
   }
-  static void Delete(Type* t, Arena* arena = NULL) {
-    if (arena == NULL) {
-      delete t;
+
+  static bool ParseExtension(
+      MessageLite* msg, const ParseTable& table,
+      io::CodedInputStream* input, int tag) {
+    ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset);
+    if (extensions == NULL) {
+      return false;
     }
+
+    const Message* prototype = down_cast<const Message*>(
+        table.default_instance());
+
+    GOOGLE_DCHECK(prototype != NULL);
+    GOOGLE_DCHECK(table.unknown_field_set);
+    UnknownFieldSet* unknown_fields =
+        MutableUnknownFields(msg, table.arena_offset);
+
+    return extensions->ParseField(tag, input, prototype, unknown_fields);
   }
 };
 
-inline bool ReadGroup(int field_number, io::CodedInputStream* input,
-                      MessageLite* value, const ParseTable& table) {
-  if (GOOGLE_PREDICT_FALSE(!input->IncrementRecursionDepth())) {
-    return false;
-  }
-
-  if (GOOGLE_PREDICT_FALSE(!MergePartialFromCodedStream(value, table, input))) {
-    return false;
-  }
-
-  input->DecrementRecursionDepth();
-  // Make sure the last thing read was an end tag for this group.
-  if (GOOGLE_PREDICT_FALSE(!input->LastTagWas(WireFormatLite::MakeTag(
-          field_number, WireFormatLite::WIRETYPE_END_GROUP)))) {
-    return false;
-  }
-
-  return true;
-}
-
-inline bool ReadMessage(io::CodedInputStream* input, MessageLite* value,
-                        const ParseTable& table) {
-  int length;
-  if (GOOGLE_PREDICT_FALSE(!input->ReadVarintSizeAsInt(&length))) {
-    return false;
-  }
-
-  std::pair<io::CodedInputStream::Limit, int> p =
-      input->IncrementRecursionDepthAndPushLimit(length);
-  if (GOOGLE_PREDICT_FALSE(p.second < 0 ||
-                    !MergePartialFromCodedStream(value, table, input))) {
-    return false;
-  }
-
-  // Make sure that parsing stopped when the limit was hit, not at an endgroup
-  // tag.
-  return input->DecrementRecursionDepthAndPopLimit(p.first);
-}
-
 }  // namespace
 
-class MergePartialFromCodedStreamHelper {
- public:
-  static MessageLite* Add(RepeatedPtrFieldBase* field,
-                          const MessageLite* prototype) {
-    return field->Add<RepeatedMessageTypeHandler>(
-        const_cast<MessageLite*>(prototype));
-  }
-};
-
-bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
-                                 io::CodedInputStream* input) {
-  // We require that has_bits are present, as to avoid having to check for them
-  // for every field.
-  //
-  // TODO(ckennelly):  Make this a compile-time parameter with templates.
-  GOOGLE_DCHECK_GE(table.has_bits_offset, 0);
-  uint32* has_bits = Raw<uint32>(msg, table.has_bits_offset);
-  GOOGLE_DCHECK(has_bits != NULL);
-
-  while (true) {
-    uint32 tag = input->ReadTag();
-
-    const WireFormatLite::WireType wire_type =
-        WireFormatLite::GetTagWireType(tag);
-    const int field_number = WireFormatLite::GetTagFieldNumber(tag);
-
-    if (GOOGLE_PREDICT_FALSE(field_number > table.max_field_number)) {
-      GOOGLE_DCHECK(!table.unknown_field_set);
-      ::google::protobuf::io::StringOutputStream unknown_fields_string(
-          MutableUnknownFields(msg, table.arena_offset));
-      ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
-          &unknown_fields_string, false);
-
-      if (!::google::protobuf::internal::WireFormatLite::SkipField(
-          input, tag, &unknown_fields_stream)) {
-        return false;
-      }
-
-      continue;
-    }
-
-    // We implicitly verify that data points to a valid field as we check the
-    // wire types.  Entries in table.fields[i] that do not correspond to valid
-    // field numbers have their normal_wiretype and packed_wiretype fields set
-    // with the kInvalidMask value.  As wire_type cannot take on that value, we
-    // will never match.
-    const ParseTableField* data = table.fields + field_number;
-
-    // TODO(ckennelly): Avoid sign extension
-    const int64 has_bit_index = data->has_bit_index;
-    const int64 offset = data->offset;
-    const unsigned char processing_type = data->processing_type;
-
-    if (data->normal_wiretype == static_cast<unsigned char>(wire_type)) {
-      // TODO(ckennelly): Use a computed goto on GCC/LLVM or otherwise eliminate
-      // the bounds check on processing_type.
-
-      switch (processing_type) {
-#define STR(S) #S
-#define HANDLE_TYPE(TYPE, CPPTYPE)                                        \
-  case (WireFormatLite::TYPE_##TYPE): {                                   \
-    CPPTYPE value;                                                        \
-    if (GOOGLE_PREDICT_FALSE(                                                    \
-            (!WireFormatLite::ReadPrimitive<                              \
-                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) { \
-      return false;                                                       \
-    }                                                                     \
-    SetField(msg, has_bits, has_bit_index, offset, value);                \
-    break;                                                                \
-  }                                                                       \
-  case (WireFormatLite::TYPE_##TYPE) | kRepeatedMask: {                   \
-    google::protobuf::RepeatedField<CPPTYPE>* values =                              \
-        Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset);                \
-    if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive<            \
-                       CPPTYPE, WireFormatLite::TYPE_##TYPE>(             \
-            data->tag_size, tag, input, values)))) {                      \
-      return false;                                                       \
-    }                                                                     \
-    break;                                                                \
-  }
-
-        HANDLE_TYPE(INT32, int32)
-        HANDLE_TYPE(INT64, int64)
-        HANDLE_TYPE(SINT32, int32)
-        HANDLE_TYPE(SINT64, int64)
-        HANDLE_TYPE(UINT32, uint32)
-        HANDLE_TYPE(UINT64, uint64)
-
-        HANDLE_TYPE(FIXED32, uint32)
-        HANDLE_TYPE(FIXED64, uint64)
-        HANDLE_TYPE(SFIXED32, int32)
-        HANDLE_TYPE(SFIXED64, int64)
-
-        HANDLE_TYPE(FLOAT, float)
-        HANDLE_TYPE(DOUBLE, double)
-
-        HANDLE_TYPE(BOOL, bool)
-#undef HANDLE_TYPE
-#undef STR
-        case WireFormatLite::TYPE_BYTES:
-#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-        case WireFormatLite::TYPE_STRING:
-#endif
-        {
-          GOOGLE_DCHECK(!table.unknown_field_set);
-          Arena* const arena = GetArena(msg, table.arena_offset);
-          const void* default_ptr = table.aux[field_number].strings.default_ptr;
-
-          if (GOOGLE_PREDICT_FALSE((!HandleString<false, false, StringType_STRING>(
-                  input, msg, arena, has_bits, has_bit_index, offset,
-                  default_ptr, false, NULL)))) {
-            return false;
-          }
-          break;
-        }
-        case (WireFormatLite::TYPE_BYTES) | kRepeatedMask:
-#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-        case (WireFormatLite::TYPE_STRING) | kRepeatedMask:
-#endif
-        {
-          GOOGLE_DCHECK(!table.unknown_field_set);
-          Arena* const arena = GetArena(msg, table.arena_offset);
-          const void* default_ptr =
-              table.aux[field_number].strings.default_ptr;
-
-          if (GOOGLE_PREDICT_FALSE((!HandleString<true, false, StringType_STRING>(
-                  input, msg, arena, has_bits, has_bit_index, offset,
-                  default_ptr, false, NULL)))) {
-            return false;
-          }
-          break;
-        }
-#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-        case (WireFormatLite::TYPE_STRING): {
-          GOOGLE_DCHECK(!table.unknown_field_set);
-          Arena* const arena = GetArena(msg, table.arena_offset);
-          const void* default_ptr = table.aux[field_number].strings.default_ptr;
-          const char* field_name = table.aux[field_number].strings.field_name;
-          const bool strict_utf8 = table.aux[field_number].strings.strict_utf8;
-
-          if (GOOGLE_PREDICT_FALSE((!HandleString<false, true, StringType_STRING>(
-                  input, msg, arena, has_bits, has_bit_index, offset,
-                  default_ptr, strict_utf8, field_name)))) {
-            return false;
-          }
-          break;
-        }
-        case (WireFormatLite::TYPE_STRING) | kRepeatedMask: {
-          GOOGLE_DCHECK(!table.unknown_field_set);
-          Arena* const arena = GetArena(msg, table.arena_offset);
-          const void* default_ptr = table.aux[field_number].strings.default_ptr;
-          const char* field_name = table.aux[field_number].strings.field_name;
-          const bool strict_utf8 = table.aux[field_number].strings.strict_utf8;
-
-          if (GOOGLE_PREDICT_FALSE((!HandleString<true, true, StringType_STRING>(
-                  input, msg, arena, has_bits, has_bit_index, offset,
-                  default_ptr, strict_utf8, field_name)))) {
-            return false;
-          }
-          break;
-        }
-#endif
-        case WireFormatLite::TYPE_ENUM: {
-          int value;
-          if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadPrimitive<
-                             int, WireFormatLite::TYPE_ENUM>(input, &value)))) {
-            return false;
-          }
-
-          AuxillaryParseTableField::EnumValidator validator =
-              table.aux[field_number].enums.validator;
-          if (validator(value)) {
-            SetField(msg, has_bits, has_bit_index, offset, value);
-          } else {
-            GOOGLE_DCHECK(!table.unknown_field_set);
-
-            ::google::protobuf::io::StringOutputStream unknown_fields_string(
-                MutableUnknownFields(msg, table.arena_offset));
-            ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
-                &unknown_fields_string, false);
-            unknown_fields_stream.WriteVarint32(tag);
-            unknown_fields_stream.WriteVarint32(value);
-          }
-          break;
-        }
-        case WireFormatLite::TYPE_ENUM | kRepeatedMask: {
-          int value;
-          if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadPrimitive<
-                             int, WireFormatLite::TYPE_ENUM>(input, &value)))) {
-            return false;
-          }
-
-          AuxillaryParseTableField::EnumValidator validator =
-              table.aux[field_number].enums.validator;
-          if (validator(value)) {
-            AddField(msg, offset, value);
-          } else {
-            GOOGLE_DCHECK(!table.unknown_field_set);
-
-            ::google::protobuf::io::StringOutputStream unknown_fields_string(
-                MutableUnknownFields(msg, table.arena_offset));
-            ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
-                &unknown_fields_string, false);
-            unknown_fields_stream.WriteVarint32(tag);
-            unknown_fields_stream.WriteVarint32(value);
-          }
-
-          break;
-        }
-        case WireFormatLite::TYPE_GROUP: {
-          MessageLite** submsg_holder =
-              MutableField<MessageLite*>(msg, has_bits, has_bit_index, offset);
-          MessageLite* submsg = *submsg_holder;
-
-          if (submsg == NULL) {
-            GOOGLE_DCHECK(!table.unknown_field_set);
-            Arena* const arena = GetArena(msg, table.arena_offset);
-            const MessageLite* prototype =
-                table.aux[field_number].messages.default_message();
-            submsg = prototype->New(arena);
-            *submsg_holder = submsg;
-          }
-
-          const ParseTable* ptable =
-              table.aux[field_number].messages.parse_table;
-
-          if (ptable) {
-            if (GOOGLE_PREDICT_FALSE(
-                    !ReadGroup(field_number, input, submsg, *ptable))) {
-              return false;
-            }
-          } else if (!WireFormatLite::ReadGroup(field_number, input, submsg)) {
-            return false;
-          }
-
-          break;
-        }
-        case WireFormatLite::TYPE_GROUP | kRepeatedMask: {
-          RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
-          const MessageLite* prototype =
-              table.aux[field_number].messages.default_message();
-          GOOGLE_DCHECK(prototype != NULL);
-
-          MessageLite* submsg =
-              MergePartialFromCodedStreamHelper::Add(field, prototype);
-          const ParseTable* ptable =
-              table.aux[field_number].messages.parse_table;
-
-          if (ptable) {
-            if (GOOGLE_PREDICT_FALSE(
-                    !ReadGroup(field_number, input, submsg, *ptable))) {
-              return false;
-            }
-          } else if (!WireFormatLite::ReadGroup(field_number, input, submsg)) {
-            return false;
-          }
-
-          break;
-        }
-        case WireFormatLite::TYPE_MESSAGE: {
-          MessageLite** submsg_holder =
-              MutableField<MessageLite*>(msg, has_bits, has_bit_index, offset);
-          MessageLite* submsg = *submsg_holder;
-
-          if (submsg == NULL) {
-            GOOGLE_DCHECK(!table.unknown_field_set);
-            Arena* const arena = GetArena(msg, table.arena_offset);
-            const MessageLite* prototype =
-                table.aux[field_number].messages.default_message();
-            submsg = prototype->New(arena);
-            *submsg_holder = submsg;
-          }
-
-          const ParseTable* ptable =
-              table.aux[field_number].messages.parse_table;
-
-          if (ptable) {
-            if (GOOGLE_PREDICT_FALSE(!ReadMessage(input, submsg, *ptable))) {
-              return false;
-            }
-          } else if (!WireFormatLite::ReadMessage(input, submsg)) {
-            return false;
-          }
-
-          break;
-        }
-        // TODO(ckennelly):  Adapt ReadMessageNoVirtualNoRecursionDepth and
-        // manage input->IncrementRecursionDepth() here.
-        case WireFormatLite::TYPE_MESSAGE | kRepeatedMask: {
-          RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
-          const MessageLite* prototype =
-              table.aux[field_number].messages.default_message();
-          GOOGLE_DCHECK(prototype != NULL);
-
-          MessageLite* submsg =
-              MergePartialFromCodedStreamHelper::Add(field, prototype);
-          const ParseTable* ptable =
-              table.aux[field_number].messages.parse_table;
-
-          if (ptable) {
-            if (GOOGLE_PREDICT_FALSE(!ReadMessage(input, submsg, *ptable))) {
-              return false;
-            }
-          } else if (!WireFormatLite::ReadMessage(input, submsg)) {
-            return false;
-          }
-
-          break;
-        }
-        case 0: {
-          // Done.
-          return true;
-        }
-        default:
-          break;
-      }
-    } else if (data->packed_wiretype == static_cast<unsigned char>(wire_type)) {
-      // Non-packable fields have their packed_wiretype masked with
-      // kNotPackedMask, which is impossible to match here.
-      GOOGLE_DCHECK(processing_type & kRepeatedMask);
-      GOOGLE_DCHECK_NE(processing_type, kRepeatedMask);
-
-
-
-      // TODO(ckennelly): Use a computed goto on GCC/LLVM.
-      //
-      // Mask out kRepeatedMask bit, allowing the jump table to be smaller.
-      switch (static_cast<WireFormatLite::FieldType>(
-          processing_type ^ kRepeatedMask)) {
-#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD)                 \
-  case WireFormatLite::TYPE_##TYPE: {                                     \
-    google::protobuf::RepeatedField<CPPTYPE>* values =                              \
-        Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset);                \
-    if (GOOGLE_PREDICT_FALSE(                                                    \
-            (!WireFormatLite::ReadPackedPrimitive<                        \
-                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \
-      return false;                                                       \
-    }                                                                     \
-    break;                                                                \
-  }
-
-        HANDLE_PACKED_TYPE(INT32, int32, Int32)
-        HANDLE_PACKED_TYPE(INT64, int64, Int64)
-        HANDLE_PACKED_TYPE(SINT32, int32, Int32)
-        HANDLE_PACKED_TYPE(SINT64, int64, Int64)
-        HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
-        HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
-
-        HANDLE_PACKED_TYPE(FIXED32, uint32, UInt32)
-        HANDLE_PACKED_TYPE(FIXED64, uint64, UInt64)
-        HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
-        HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
-
-        HANDLE_PACKED_TYPE(FLOAT, float, Float)
-        HANDLE_PACKED_TYPE(DOUBLE, double, Double)
-
-        HANDLE_PACKED_TYPE(BOOL, bool, Bool)
-#undef HANDLE_PACKED_TYPE
-        case WireFormatLite::TYPE_ENUM: {
-          // To avoid unnecessarily calling MutableUnknownFields (which mutates
-          // InternalMetadataWithArena) when all inputs in the repeated series
-          // are valid, we implement our own parser rather than call
-          // WireFormat::ReadPackedEnumPreserveUnknowns.
-          uint32 length;
-          if (GOOGLE_PREDICT_FALSE(!input->ReadVarint32(&length))) {
-            return false;
-          }
-
-          AuxillaryParseTableField::EnumValidator validator =
-              table.aux[field_number].enums.validator;
-          google::protobuf::RepeatedField<int>* values =
-              Raw<google::protobuf::RepeatedField<int> >(msg, offset);
-          string* unknown_fields = NULL;
-
-          io::CodedInputStream::Limit limit = input->PushLimit(length);
-          while (input->BytesUntilLimit() > 0) {
-            int value;
-            if (GOOGLE_PREDICT_FALSE(
-                    (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
-                        int, WireFormatLite::TYPE_ENUM>(input, &value)))) {
-              return false;
-            }
-
-            if (validator(value)) {
-              values->Add(value);
-            } else {
-              if (GOOGLE_PREDICT_FALSE(unknown_fields == NULL)) {
-                GOOGLE_DCHECK(!table.unknown_field_set);
-                unknown_fields = MutableUnknownFields(msg, table.arena_offset);
-              }
-
-              ::google::protobuf::io::StringOutputStream unknown_fields_string(
-                  unknown_fields);
-              ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
-                  &unknown_fields_string, false);
-              unknown_fields_stream.WriteVarint32(tag);
-              unknown_fields_stream.WriteVarint32(value);
-            }
-          }
-          input->PopLimit(limit);
-
-          break;
-        }
-        case WireFormatLite::TYPE_STRING:
-        case WireFormatLite::TYPE_GROUP:
-        case WireFormatLite::TYPE_MESSAGE:
-        case WireFormatLite::TYPE_BYTES:
-          GOOGLE_DCHECK(false);
-          return false;
-        default:
-          break;
-      }
-    } else {
-      if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
-        // Must be the end of the message.
-        return true;
-      }
-
-      // process unknown field.
-      GOOGLE_DCHECK(!table.unknown_field_set);
-      ::google::protobuf::io::StringOutputStream unknown_fields_string(
-          MutableUnknownFields(msg, table.arena_offset));
-      ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
-          &unknown_fields_string, false);
-
-      if (!::google::protobuf::internal::WireFormatLite::SkipField(
-          input, tag, &unknown_fields_stream)) {
-        return false;
-      }
-    }
-  }
+bool MergePartialFromCodedStream(
+    MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) {
+  return MergePartialFromCodedStreamImpl<UnknownFieldHandler,
+                                         InternalMetadataWithArena>(msg, table,
+                                                                    input);
 }
 
 }  // namespace internal
diff --git a/src/google/protobuf/generated_message_table_driven.h b/src/google/protobuf/generated_message_table_driven.h
index 557c57d..5eb63db 100644
--- a/src/google/protobuf/generated_message_table_driven.h
+++ b/src/google/protobuf/generated_message_table_driven.h
@@ -31,7 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
 
+#include <google/protobuf/map.h>
+#include <google/protobuf/map_entry_lite.h>
 #include <google/protobuf/message_lite.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 
 #if LANG_CXX11
 #define PROTOBUF_CONSTEXPR constexpr
@@ -54,10 +58,14 @@
 namespace protobuf {
 namespace internal {
 
+// Processing-type masks.
 static PROTOBUF_CONSTEXPR const unsigned char kOneofMask = 0x40;
 static PROTOBUF_CONSTEXPR const unsigned char kRepeatedMask = 0x20;
-// Check this against types.
+// Mask for the raw type: either a WireFormatLite::FieldType or one of the
+// ProcessingTypes below, without the oneof or repeated flag.
+static PROTOBUF_CONSTEXPR const unsigned char kTypeMask = 0x1f;
 
+// Wire type masks.
 static PROTOBUF_CONSTEXPR const unsigned char kNotPackedMask = 0x10;
 static PROTOBUF_CONSTEXPR const unsigned char kInvalidMask = 0x20;
 
@@ -66,10 +74,11 @@
   TYPE_STRING_STRING_PIECE = 20,
   TYPE_BYTES_CORD = 21,
   TYPE_BYTES_STRING_PIECE = 22,
+  TYPE_MAP = 23,
 };
 
 #if LANG_CXX11
-static_assert(TYPE_BYTES_STRING_PIECE < kRepeatedMask, "Invalid enum");
+static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
 #endif
 
 // TODO(ckennelly):  Add a static assertion to ensure that these masks do not
@@ -81,7 +90,9 @@
 // AuxillaryParseTableField.
 struct ParseTableField {
   uint32 offset;
-  uint32 has_bit_index;
+  // The presence_index ordinarily represents a has_bit index, but for fields
+  // inside a oneof it represents the index in _oneof_case_.
+  uint32 presence_index;
   unsigned char normal_wiretype;
   unsigned char packed_wiretype;
 
@@ -100,7 +111,6 @@
   // Enums
   struct enum_aux {
     EnumValidator validator;
-    const char* name;
   };
   enum_aux enums;
   // Group, messages
@@ -119,11 +129,14 @@
   struct string_aux {
     const void* default_ptr;
     const char* field_name;
-    bool strict_utf8;
-    const char* name;
   };
   string_aux strings;
 
+  struct map_aux {
+    bool (*parse_map)(io::CodedInputStream*, void*);
+  };
+  map_aux maps;
+
 #if LANG_CXX11
   AuxillaryParseTableField() = default;
 #else
@@ -135,6 +148,9 @@
       AuxillaryParseTableField::message_aux m) : messages(m) {}
   PROTOBUF_CONSTEXPR AuxillaryParseTableField(
       AuxillaryParseTableField::string_aux s) : strings(s) {}
+  PROTOBUF_CONSTEXPR AuxillaryParseTableField(
+      AuxillaryParseTableField::map_aux m)
+      : maps(m) {}
 };
 
 struct ParseTable {
@@ -145,8 +161,19 @@
 
   // TODO(ckennelly): Vet these for sign extension.
   int64 has_bits_offset;
+  int64 oneof_case_offset;
+  int64 extension_offset;
   int64 arena_offset;
-  int  unknown_field_set;
+
+  // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
+  // the tables from being constructed as a constexpr.  We use void to avoid
+  // the cast.
+  const void* default_instance_void;
+  const MessageLite* default_instance() const {
+    return static_cast<const MessageLite*>(default_instance_void);
+  }
+
+  bool unknown_field_set;
 };
 
 // TODO(jhen): Remove the __NVCC__ check when we get a version of nvcc that
@@ -163,8 +190,39 @@
 static_assert(std::is_pod<ParseTable>::value, "");
 #endif
 
+// TODO(ckennelly): Consolidate these implementations into a single one, using
+// dynamic dispatch to the appropriate unknown field handler.
 bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
                                  io::CodedInputStream* input);
+bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table,
+                                 io::CodedInputStream* input);
+
+template <typename MEntry>
+struct MapEntryToMapField;
+
+template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+struct MapEntryToMapField<MapEntryLite<Key, Value, kKeyFieldType,
+                                       kValueFieldType, default_enum_value> > {
+  typedef MapFieldLite<MapEntryLite<Key, Value, kKeyFieldType, kValueFieldType,
+                                    default_enum_value>,
+                       Key, Value, kKeyFieldType, kValueFieldType,
+                       default_enum_value>
+      MapFieldType;
+};
+
+template <typename Entry>
+bool ParseMap(io::CodedInputStream* input, void* map_field) {
+  typedef typename MapEntryToMapField<Entry>::MapFieldType MapFieldType;
+  typedef google::protobuf::Map<typename Entry::EntryKeyType,
+                      typename Entry::EntryValueType>
+      MapType;
+  typedef typename Entry::template Parser<MapFieldType, MapType> ParserType;
+
+  ParserType parser(static_cast<MapFieldType*>(map_field));
+  return ::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(input,
+                                                                  &parser);
+}
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/generated_message_table_driven_lite.cc b/src/google/protobuf/generated_message_table_driven_lite.cc
new file mode 100644
index 0000000..90a5050
--- /dev/null
+++ b/src/google/protobuf/generated_message_table_driven_lite.cc
@@ -0,0 +1,109 @@
+// 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/generated_message_table_driven_lite.h>
+
+#include <google/protobuf/stubs/type_traits.h>
+
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+
+string* MutableUnknownFields(MessageLite* msg, int64 arena_offset) {
+  return Raw<InternalMetadataWithArenaLite>(msg, arena_offset)
+      ->mutable_unknown_fields();
+}
+
+struct UnknownFieldHandlerLite {
+  static bool Skip(MessageLite* msg, const ParseTable& table,
+                   io::CodedInputStream* input,
+                   int tag) {
+    GOOGLE_DCHECK(!table.unknown_field_set);
+    ::google::protobuf::io::StringOutputStream unknown_fields_string(
+        MutableUnknownFields(msg, table.arena_offset));
+    ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+        &unknown_fields_string, false);
+
+    return ::google::protobuf::internal::WireFormatLite::SkipField(
+        input, tag, &unknown_fields_stream);
+  }
+
+  static void Varint(MessageLite* msg, const ParseTable& table,
+                     int tag, int value) {
+    GOOGLE_DCHECK(!table.unknown_field_set);
+
+    ::google::protobuf::io::StringOutputStream unknown_fields_string(
+        MutableUnknownFields(msg, table.arena_offset));
+    ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+        &unknown_fields_string, false);
+    unknown_fields_stream.WriteVarint32(tag);
+    unknown_fields_stream.WriteVarint32(value);
+  }
+
+  static bool ParseExtension(
+      MessageLite* msg, const ParseTable& table,
+      io::CodedInputStream* input, int tag) {
+    ExtensionSet* extensions = GetExtensionSet(msg, table.extension_offset);
+    if (extensions == NULL) {
+      return false;
+    }
+
+    const MessageLite* prototype = table.default_instance();
+
+    GOOGLE_DCHECK(!table.unknown_field_set);
+    ::google::protobuf::io::StringOutputStream unknown_fields_string(
+        MutableUnknownFields(msg, table.arena_offset));
+    ::google::protobuf::io::CodedOutputStream unknown_fields_stream(
+        &unknown_fields_string, false);
+    return extensions->ParseField(
+        tag, input, prototype, &unknown_fields_stream);
+  }
+};
+
+}  // namespace
+
+bool MergePartialFromCodedStreamLite(
+    MessageLite* msg, const ParseTable& table, io::CodedInputStream* input) {
+  return MergePartialFromCodedStreamImpl<UnknownFieldHandlerLite,
+                                         InternalMetadataWithArenaLite>(
+      msg, table, input);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h
new file mode 100644
index 0000000..20b4da2
--- /dev/null
+++ b/src/google/protobuf/generated_message_table_driven_lite.h
@@ -0,0 +1,823 @@
+// 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_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
+
+#include <google/protobuf/generated_message_table_driven.h>
+
+#include <google/protobuf/stubs/type_traits.h>
+
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+
+enum StringType {
+  StringType_STRING = 0,
+  StringType_CORD = 1,
+  StringType_STRING_PIECE = 2
+};
+
+// Logically a superset of StringType, consisting of all field types that
+// require special initialization.
+enum ProcessingType {
+  ProcessingType_STRING = 0,
+  ProcessingType_CORD = 1,
+  ProcessingType_STRING_PIECE = 2,
+  ProcessingType_MESSAGE = 3
+};
+
+enum Cardinality {
+  Cardinality_SINGULAR = 0,
+  Cardinality_REPEATED = 1,
+  Cardinality_ONEOF = 3
+};
+
+template <typename Type>
+inline Type* Raw(MessageLite* msg, int64 offset) {
+  return reinterpret_cast<Type*>(reinterpret_cast<uint8*>(msg) + offset);
+}
+
+template <typename Type>
+inline const Type* Raw(const MessageLite* msg, int64 offset) {
+  return reinterpret_cast<const Type*>(reinterpret_cast<const uint8*>(msg) +
+                                       offset);
+}
+
+template <typename InternalMetadata>
+inline Arena* GetArena(MessageLite* msg, int64 arena_offset) {
+  if (GOOGLE_PREDICT_FALSE(arena_offset == -1)) {
+    return NULL;
+  }
+
+  return Raw<InternalMetadata>(msg, arena_offset)->arena();
+}
+
+inline ExtensionSet* GetExtensionSet(MessageLite* msg, int64 extension_offset) {
+  if (extension_offset == -1) {
+    return NULL;
+  }
+
+  return Raw<ExtensionSet>(msg, extension_offset);
+}
+
+template <typename Type>
+inline Type* AddField(MessageLite* msg, int64 offset) {
+#if LANG_CXX11
+  static_assert(has_trivial_copy<Type>::value,
+                "Do not assign");
+#endif
+
+  google::protobuf::RepeatedField<Type>* repeated =
+      Raw<google::protobuf::RepeatedField<Type> >(msg, offset);
+  return repeated->Add();
+}
+
+template <>
+inline string* AddField<string>(MessageLite* msg, int64 offset) {
+  google::protobuf::RepeatedPtrField<string>* repeated =
+      Raw<google::protobuf::RepeatedPtrField<string> >(msg, offset);
+  return repeated->Add();
+}
+
+
+template <typename Type>
+inline void AddField(MessageLite* msg, int64 offset, Type value) {
+#if LANG_CXX11
+  static_assert(has_trivial_copy<Type>::value,
+                "Do not assign");
+#endif
+  *AddField<Type>(msg, offset) = value;
+}
+
+inline void SetBit(uint32* has_bits, uint32 has_bit_index) {
+  GOOGLE_DCHECK(has_bits != NULL);
+
+  uint32 mask = static_cast<uint32>(1u) << (has_bit_index % 32);
+  has_bits[has_bit_index / 32u] |= mask;
+}
+
+template <typename Type>
+inline Type* MutableField(MessageLite* msg, uint32* has_bits,
+                          uint32 has_bit_index, int64 offset) {
+  SetBit(has_bits, has_bit_index);
+  return Raw<Type>(msg, offset);
+}
+
+template <typename Type>
+inline void SetField(MessageLite* msg, uint32* has_bits, uint32 has_bit_index,
+                     int64 offset, Type value) {
+#if LANG_CXX11
+  static_assert(has_trivial_copy<Type>::value,
+                "Do not assign");
+#endif
+  *MutableField<Type>(msg, has_bits, has_bit_index, offset) = value;
+}
+
+template <typename Type>
+inline void SetOneofField(MessageLite* msg, uint32* oneof_case,
+                          uint32 oneof_case_index, int64 offset,
+                          int field_number, Type value) {
+  oneof_case[oneof_case_index] = field_number;
+  *Raw<Type>(msg, offset) = value;
+}
+
+// Clears a oneof field. The field argument should correspond to the particular
+// field that is currently set in the oneof.
+inline void ClearOneofField(const ParseTableField& field, Arena* arena,
+                     MessageLite* msg) {
+  switch (field.processing_type & kTypeMask) {
+    case WireFormatLite::TYPE_MESSAGE:
+      if (arena == NULL) {
+        delete *Raw<MessageLite*>(msg, field.offset);
+      }
+      break;
+
+    case WireFormatLite::TYPE_STRING:
+    case WireFormatLite::TYPE_BYTES:
+      Raw<ArenaStringPtr>(msg, field.offset)
+          ->Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
+      break;
+
+    default:
+      // No cleanup needed.
+      break;
+  }
+}
+
+// Clears and reinitializes a oneof field as necessary, in preparation for
+// parsing a new value with type field_type and field number field_number.
+//
+// Note: the oneof_case argument should point directly to the _oneof_case_
+// element corresponding to this particular oneof, not to the beginning of the
+// _oneof_case_ array.
+template <ProcessingType field_type>
+inline void ResetOneofField(const ParseTable& table, int field_number,
+                            Arena* arena, MessageLite* msg, uint32* oneof_case,
+                            int64 offset, const void* default_ptr) {
+  if (*oneof_case == field_number) {
+    // The oneof is already set to the right type, so there is no need to clear
+    // it.
+    return;
+  }
+
+  if (*oneof_case != 0) {
+    ClearOneofField(table.fields[*oneof_case], arena, msg);
+  }
+  *oneof_case = field_number;
+
+  switch (field_type) {
+    case ProcessingType_STRING:
+      Raw<ArenaStringPtr>(msg, offset)
+          ->UnsafeSetDefault(static_cast<const string*>(default_ptr));
+      break;
+    case ProcessingType_MESSAGE:
+      MessageLite** submessage = Raw<MessageLite*>(msg, offset);
+      const MessageLite* prototype =
+          table.aux[field_number].messages.default_message();
+      *submessage = prototype->New(arena);
+      break;
+  }
+}
+
+template <Cardinality cardinality, bool validate, StringType ctype>
+static inline bool HandleString(io::CodedInputStream* input, MessageLite* msg,
+                                Arena* arena, uint32* has_bits,
+                                uint32 has_bit_index, int64 offset,
+                                const void* default_ptr,
+                                const char* field_name) {
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  const char* sdata;
+  size_t size;
+#endif
+
+    string* value;
+    switch (cardinality) {
+      case Cardinality_SINGULAR:
+        // TODO(ckennelly): Is this optimal?
+        value =
+            MutableField<ArenaStringPtr>(msg, has_bits, has_bit_index, offset)
+                ->Mutable(static_cast<const string*>(default_ptr), arena);
+        break;
+      case Cardinality_REPEATED:
+        value = AddField<string>(msg, offset);
+        break;
+      case Cardinality_ONEOF:
+        value = Raw<ArenaStringPtr>(msg, offset)
+                    ->Mutable(static_cast<const string*>(default_ptr), arena);
+        break;
+    }
+    GOOGLE_DCHECK(value != NULL);
+
+    if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadString(input, value))) {
+      return false;
+    }
+
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+    sdata = value->data();
+    size = value->size();
+#endif
+
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+  if (validate) {
+    WireFormatLite::VerifyUtf8String(sdata, size, WireFormatLite::PARSE,
+                                     field_name);
+  }
+#endif
+
+  return true;
+}
+
+template <typename UnknownFieldHandler, typename InternalMetadata,
+          Cardinality cardinality>
+inline bool HandleEnum(const ParseTable& table, io::CodedInputStream* input,
+                       MessageLite* msg, uint32* presence,
+                       uint32 presence_index, int64 offset, uint32 tag,
+                       int field_number) {
+  int value;
+  if (GOOGLE_PREDICT_FALSE(
+          (!WireFormatLite::ReadPrimitive<int, WireFormatLite::TYPE_ENUM>(
+              input, &value)))) {
+    return false;
+  }
+
+  AuxillaryParseTableField::EnumValidator validator =
+      table.aux[field_number].enums.validator;
+  if (validator(value)) {
+    switch (cardinality) {
+      case Cardinality_SINGULAR:
+        SetField(msg, presence, presence_index, offset, value);
+        break;
+      case Cardinality_REPEATED:
+        AddField(msg, offset, value);
+        break;
+      case Cardinality_ONEOF:
+        ClearOneofField(table.fields[presence[presence_index]],
+                        GetArena<InternalMetadata>(msg, table.arena_offset),
+                        msg);
+        SetOneofField(msg, presence, presence_index, offset, field_number,
+                      value);
+        break;
+    }
+  } else {
+    UnknownFieldHandler::Varint(msg, table, tag, value);
+  }
+
+  return true;
+}
+
+// RepeatedMessageTypeHandler allows us to operate on RepeatedPtrField fields
+// without instantiating the specific template.
+class RepeatedMessageTypeHandler {
+ public:
+  typedef MessageLite Type;
+  static Arena* GetArena(Type* t) { return t->GetArena(); }
+  static void* GetMaybeArenaPointer(Type* t) {
+    return t->GetMaybeArenaPointer();
+  }
+  static inline Type* NewFromPrototype(const Type* prototype,
+                                       Arena* arena = NULL) {
+    return prototype->New(arena);
+  }
+  static void Delete(Type* t, Arena* arena = NULL) {
+    if (arena == NULL) {
+      delete t;
+    }
+  }
+};
+
+inline bool ReadGroup(int field_number, io::CodedInputStream* input,
+                      MessageLite* value) {
+  if (GOOGLE_PREDICT_FALSE(!input->IncrementRecursionDepth())) {
+    return false;
+  }
+
+  if (GOOGLE_PREDICT_FALSE(!value->MergePartialFromCodedStream(input))) {
+    return false;
+  }
+
+  input->DecrementRecursionDepth();
+  // Make sure the last thing read was an end tag for this group.
+  if (GOOGLE_PREDICT_FALSE(!input->LastTagWas(WireFormatLite::MakeTag(
+          field_number, WireFormatLite::WIRETYPE_END_GROUP)))) {
+    return false;
+  }
+
+  return true;
+}
+
+inline bool ReadMessage(io::CodedInputStream* input, MessageLite* value) {
+  int length;
+  if (GOOGLE_PREDICT_FALSE(!input->ReadVarintSizeAsInt(&length))) {
+    return false;
+  }
+
+  std::pair<io::CodedInputStream::Limit, int> p =
+      input->IncrementRecursionDepthAndPushLimit(length);
+  if (GOOGLE_PREDICT_FALSE(p.second < 0 ||
+                    !value->MergePartialFromCodedStream(input))) {
+    return false;
+  }
+
+  // Make sure that parsing stopped when the limit was hit, not at an endgroup
+  // tag.
+  return input->DecrementRecursionDepthAndPopLimit(p.first);
+}
+
+class MergePartialFromCodedStreamHelper {
+ public:
+  static MessageLite* Add(RepeatedPtrFieldBase* field,
+                          const MessageLite* prototype) {
+    return field->Add<RepeatedMessageTypeHandler>(
+        const_cast<MessageLite*>(prototype));
+  }
+};
+
+template <typename UnknownFieldHandler, typename InternalMetadata>
+bool MergePartialFromCodedStreamImpl(MessageLite* msg, const ParseTable& table,
+                                     io::CodedInputStream* input) {
+  // We require that has_bits are present, as to avoid having to check for them
+  // for every field.
+  //
+  // TODO(ckennelly):  Make this a compile-time parameter with templates.
+  GOOGLE_DCHECK_GE(table.has_bits_offset, 0);
+  uint32* has_bits = Raw<uint32>(msg, table.has_bits_offset);
+  GOOGLE_DCHECK(has_bits != NULL);
+
+  while (true) {
+    uint32 tag = input->ReadTag();
+
+    const WireFormatLite::WireType wire_type =
+        WireFormatLite::GetTagWireType(tag);
+    const int field_number = WireFormatLite::GetTagFieldNumber(tag);
+
+    if (field_number > table.max_field_number) {
+      // check for possible extensions
+      if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) {
+        // successfully parsed
+        continue;
+      }
+
+      if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) {
+        return false;
+      }
+
+      continue;
+    }
+
+    // We implicitly verify that data points to a valid field as we check the
+    // wire types.  Entries in table.fields[i] that do not correspond to valid
+    // field numbers have their normal_wiretype and packed_wiretype fields set
+    // with the kInvalidMask value.  As wire_type cannot take on that value, we
+    // will never match.
+    const ParseTableField* data = table.fields + field_number;
+
+    // TODO(ckennelly): Avoid sign extension
+    const int64 presence_index = data->presence_index;
+    const int64 offset = data->offset;
+    const unsigned char processing_type = data->processing_type;
+
+    if (data->normal_wiretype == static_cast<unsigned char>(wire_type)) {
+      // TODO(ckennelly): Use a computed goto on GCC/LLVM or otherwise eliminate
+      // the bounds check on processing_type.
+
+      switch (processing_type) {
+#define HANDLE_TYPE(TYPE, CPPTYPE)                                             \
+  case (WireFormatLite::TYPE_##TYPE): {                                        \
+    CPPTYPE value;                                                             \
+    if (GOOGLE_PREDICT_FALSE(                                                         \
+            (!WireFormatLite::ReadPrimitive<                                   \
+                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) {      \
+      return false;                                                            \
+    }                                                                          \
+    SetField(msg, has_bits, presence_index, offset, value);                    \
+    break;                                                                     \
+  }                                                                            \
+  case (WireFormatLite::TYPE_##TYPE) | kRepeatedMask: {                        \
+    google::protobuf::RepeatedField<CPPTYPE>* values =                                   \
+        Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset);                     \
+    if (GOOGLE_PREDICT_FALSE((!WireFormatLite::ReadRepeatedPrimitive<                 \
+                       CPPTYPE, WireFormatLite::TYPE_##TYPE>(                  \
+            data->tag_size, tag, input, values)))) {                           \
+      return false;                                                            \
+    }                                                                          \
+    break;                                                                     \
+  }                                                                            \
+  case (WireFormatLite::TYPE_##TYPE) | kOneofMask: {                           \
+    uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);            \
+    CPPTYPE value;                                                             \
+    if (GOOGLE_PREDICT_FALSE(                                                         \
+            (!WireFormatLite::ReadPrimitive<                                   \
+                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, &value)))) {      \
+      return false;                                                            \
+    }                                                                          \
+    ClearOneofField(table.fields[oneof_case[presence_index]],                  \
+                    GetArena<InternalMetadata>(msg, table.arena_offset), msg); \
+    SetOneofField(msg, oneof_case, presence_index, offset, field_number,       \
+                  value);                                                      \
+    break;                                                                     \
+  }
+
+        HANDLE_TYPE(INT32, int32)
+        HANDLE_TYPE(INT64, int64)
+        HANDLE_TYPE(SINT32, int32)
+        HANDLE_TYPE(SINT64, int64)
+        HANDLE_TYPE(UINT32, uint32)
+        HANDLE_TYPE(UINT64, uint64)
+
+        HANDLE_TYPE(FIXED32, uint32)
+        HANDLE_TYPE(FIXED64, uint64)
+        HANDLE_TYPE(SFIXED32, int32)
+        HANDLE_TYPE(SFIXED64, int64)
+
+        HANDLE_TYPE(FLOAT, float)
+        HANDLE_TYPE(DOUBLE, double)
+
+        HANDLE_TYPE(BOOL, bool)
+#undef HANDLE_TYPE
+        case WireFormatLite::TYPE_BYTES:
+#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+        case WireFormatLite::TYPE_STRING:
+#endif
+        {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          const void* default_ptr = table.aux[field_number].strings.default_ptr;
+
+          if (GOOGLE_PREDICT_FALSE((
+                  !HandleString<Cardinality_SINGULAR, false, StringType_STRING>(
+                      input, msg, arena, has_bits, presence_index, offset,
+                      default_ptr, NULL)))) {
+            return false;
+          }
+          break;
+        }
+        case WireFormatLite::TYPE_BYTES | kOneofMask:
+#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+        case WireFormatLite::TYPE_STRING | kOneofMask:
+#endif
+        {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
+          const void* default_ptr = table.aux[field_number].strings.default_ptr;
+
+          ResetOneofField<ProcessingType_STRING>(
+              table, field_number, arena, msg, oneof_case + presence_index,
+              offset, default_ptr);
+
+          if (GOOGLE_PREDICT_FALSE(
+                  (!HandleString<Cardinality_ONEOF, false, StringType_STRING>(
+                      input, msg, arena, has_bits, presence_index, offset,
+                      default_ptr, NULL)))) {
+            return false;
+          }
+          break;
+        }
+        case (WireFormatLite::TYPE_BYTES) | kRepeatedMask:
+#ifndef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+        case (WireFormatLite::TYPE_STRING) | kRepeatedMask:
+#endif
+        {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          const void* default_ptr =
+              table.aux[field_number].strings.default_ptr;
+
+          if (GOOGLE_PREDICT_FALSE((
+                  !HandleString<Cardinality_REPEATED, false, StringType_STRING>(
+                      input, msg, arena, has_bits, presence_index, offset,
+                      default_ptr, NULL)))) {
+            return false;
+          }
+          break;
+        }
+#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+        case (WireFormatLite::TYPE_STRING): {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          const void* default_ptr = table.aux[field_number].strings.default_ptr;
+          const char* field_name = table.aux[field_number].strings.field_name;
+
+          if (GOOGLE_PREDICT_FALSE(
+                  (!HandleString<Cardinality_SINGULAR, true, StringType_STRING>(
+                      input, msg, arena, has_bits, presence_index, offset,
+                      default_ptr, field_name)))) {
+            return false;
+          }
+          break;
+        }
+        case (WireFormatLite::TYPE_STRING) | kRepeatedMask: {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          const void* default_ptr = table.aux[field_number].strings.default_ptr;
+          const char* field_name = table.aux[field_number].strings.field_name;
+
+          if (GOOGLE_PREDICT_FALSE(
+                  (!HandleString<Cardinality_REPEATED, true, StringType_STRING>(
+                      input, msg, arena, has_bits, presence_index, offset,
+                      default_ptr, field_name)))) {
+            return false;
+          }
+          break;
+        }
+        case (WireFormatLite::TYPE_STRING) | kOneofMask: {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
+          const void* default_ptr = table.aux[field_number].strings.default_ptr;
+          const char* field_name = table.aux[field_number].strings.field_name;
+
+          ResetOneofField<ProcessingType_STRING>(
+              table, field_number, arena, msg, oneof_case + presence_index,
+              offset, default_ptr);
+
+          if (GOOGLE_PREDICT_FALSE(
+                  (!HandleString<Cardinality_ONEOF, true, StringType_STRING>(
+                      input, msg, arena, has_bits, presence_index, offset,
+                      default_ptr, field_name)))) {
+            return false;
+          }
+          break;
+        }
+#endif
+        case WireFormatLite::TYPE_ENUM: {
+          if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
+                                         Cardinality_SINGULAR>(
+                  table, input, msg, has_bits, presence_index, offset, tag,
+                  field_number)))) {
+            return false;
+          }
+          break;
+        }
+        case WireFormatLite::TYPE_ENUM | kRepeatedMask: {
+          if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
+                                         Cardinality_REPEATED>(
+                  table, input, msg, has_bits, presence_index, offset, tag,
+                  field_number)))) {
+            return false;
+          }
+          break;
+        }
+        case WireFormatLite::TYPE_ENUM | kOneofMask: {
+          uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
+          if (GOOGLE_PREDICT_FALSE((!HandleEnum<UnknownFieldHandler, InternalMetadata,
+                                         Cardinality_ONEOF>(
+                  table, input, msg, oneof_case, presence_index, offset, tag,
+                  field_number)))) {
+            return false;
+          }
+          break;
+        }
+        case WireFormatLite::TYPE_GROUP: {
+          MessageLite** submsg_holder =
+              MutableField<MessageLite*>(msg, has_bits, presence_index, offset);
+          MessageLite* submsg = *submsg_holder;
+
+          if (submsg == NULL) {
+            Arena* const arena =
+                GetArena<InternalMetadata>(msg, table.arena_offset);
+            const MessageLite* prototype =
+                table.aux[field_number].messages.default_message();
+            submsg = prototype->New(arena);
+            *submsg_holder = submsg;
+          }
+
+          if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup(
+              field_number, input, submsg))) {
+            return false;
+          }
+
+          break;
+        }
+        case WireFormatLite::TYPE_GROUP | kRepeatedMask: {
+          RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
+          const MessageLite* prototype =
+              table.aux[field_number].messages.default_message();
+          GOOGLE_DCHECK(prototype != NULL);
+
+          MessageLite* submsg =
+              MergePartialFromCodedStreamHelper::Add(field, prototype);
+
+          if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadGroup(
+              field_number, input, submsg))) {
+            return false;
+          }
+
+          break;
+        }
+        case WireFormatLite::TYPE_MESSAGE: {
+          MessageLite** submsg_holder =
+              MutableField<MessageLite*>(msg, has_bits, presence_index, offset);
+          MessageLite* submsg = *submsg_holder;
+
+          if (submsg == NULL) {
+            Arena* const arena =
+                GetArena<InternalMetadata>(msg, table.arena_offset);
+            const MessageLite* prototype =
+                table.aux[field_number].messages.default_message();
+            submsg = prototype->New(arena);
+            *submsg_holder = submsg;
+          }
+
+          if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
+            return false;
+          }
+
+          break;
+        }
+        // TODO(ckennelly):  Adapt ReadMessageNoVirtualNoRecursionDepth and
+        // manage input->IncrementRecursionDepth() here.
+        case WireFormatLite::TYPE_MESSAGE | kRepeatedMask: {
+          RepeatedPtrFieldBase* field = Raw<RepeatedPtrFieldBase>(msg, offset);
+          const MessageLite* prototype =
+              table.aux[field_number].messages.default_message();
+          GOOGLE_DCHECK(prototype != NULL);
+
+          MessageLite* submsg =
+              MergePartialFromCodedStreamHelper::Add(field, prototype);
+
+          if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
+            return false;
+          }
+
+          break;
+        }
+        case WireFormatLite::TYPE_MESSAGE | kOneofMask: {
+          Arena* const arena =
+              GetArena<InternalMetadata>(msg, table.arena_offset);
+          uint32* oneof_case = Raw<uint32>(msg, table.oneof_case_offset);
+          MessageLite** submsg_holder = Raw<MessageLite*>(msg, offset);
+          ResetOneofField<ProcessingType_MESSAGE>(
+              table, field_number, arena, msg, oneof_case + presence_index,
+              offset, NULL);
+          MessageLite* submsg = *submsg_holder;
+
+          if (GOOGLE_PREDICT_FALSE(!WireFormatLite::ReadMessage(input, submsg))) {
+            return false;
+          }
+
+          break;
+        }
+        case TYPE_MAP: {
+          if (GOOGLE_PREDICT_FALSE(!(*table.aux[field_number].maps.parse_map)(
+                  input, Raw<void>(msg, offset)))) {
+            return false;
+          }
+          break;
+        }
+        case 0: {
+          // Done.
+          return true;
+        }
+        default:
+          break;
+      }
+    } else if (data->packed_wiretype == static_cast<unsigned char>(wire_type)) {
+      // Non-packable fields have their packed_wiretype masked with
+      // kNotPackedMask, which is impossible to match here.
+      GOOGLE_DCHECK(processing_type & kRepeatedMask);
+      GOOGLE_DCHECK_NE(processing_type, kRepeatedMask);
+      GOOGLE_DCHECK_EQ(0, processing_type & kOneofMask);
+
+
+
+      // TODO(ckennelly): Use a computed goto on GCC/LLVM.
+      //
+      // Mask out kRepeatedMask bit, allowing the jump table to be smaller.
+      switch (static_cast<WireFormatLite::FieldType>(
+          processing_type ^ kRepeatedMask)) {
+#define HANDLE_PACKED_TYPE(TYPE, CPPTYPE, CPPTYPE_METHOD)                 \
+  case WireFormatLite::TYPE_##TYPE: {                                     \
+    google::protobuf::RepeatedField<CPPTYPE>* values =                              \
+        Raw<google::protobuf::RepeatedField<CPPTYPE> >(msg, offset);                \
+    if (GOOGLE_PREDICT_FALSE(                                                    \
+            (!WireFormatLite::ReadPackedPrimitive<                        \
+                CPPTYPE, WireFormatLite::TYPE_##TYPE>(input, values)))) { \
+      return false;                                                       \
+    }                                                                     \
+    break;                                                                \
+  }
+
+        HANDLE_PACKED_TYPE(INT32, int32, Int32)
+        HANDLE_PACKED_TYPE(INT64, int64, Int64)
+        HANDLE_PACKED_TYPE(SINT32, int32, Int32)
+        HANDLE_PACKED_TYPE(SINT64, int64, Int64)
+        HANDLE_PACKED_TYPE(UINT32, uint32, UInt32)
+        HANDLE_PACKED_TYPE(UINT64, uint64, UInt64)
+
+        HANDLE_PACKED_TYPE(FIXED32, uint32, UInt32)
+        HANDLE_PACKED_TYPE(FIXED64, uint64, UInt64)
+        HANDLE_PACKED_TYPE(SFIXED32, int32, Int32)
+        HANDLE_PACKED_TYPE(SFIXED64, int64, Int64)
+
+        HANDLE_PACKED_TYPE(FLOAT, float, Float)
+        HANDLE_PACKED_TYPE(DOUBLE, double, Double)
+
+        HANDLE_PACKED_TYPE(BOOL, bool, Bool)
+#undef HANDLE_PACKED_TYPE
+        case WireFormatLite::TYPE_ENUM: {
+          // To avoid unnecessarily calling MutableUnknownFields (which mutates
+          // InternalMetadataWithArena) when all inputs in the repeated series
+          // are valid, we implement our own parser rather than call
+          // WireFormat::ReadPackedEnumPreserveUnknowns.
+          uint32 length;
+          if (GOOGLE_PREDICT_FALSE(!input->ReadVarint32(&length))) {
+            return false;
+          }
+
+          AuxillaryParseTableField::EnumValidator validator =
+              table.aux[field_number].enums.validator;
+          google::protobuf::RepeatedField<int>* values =
+              Raw<google::protobuf::RepeatedField<int> >(msg, offset);
+
+          io::CodedInputStream::Limit limit = input->PushLimit(length);
+          while (input->BytesUntilLimit() > 0) {
+            int value;
+            if (GOOGLE_PREDICT_FALSE(
+                    (!google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                        int, WireFormatLite::TYPE_ENUM>(input, &value)))) {
+              return false;
+            }
+
+            if (validator(value)) {
+              values->Add(value);
+            } else {
+              // TODO(ckennelly): Consider caching here.
+              UnknownFieldHandler::Varint(msg, table, tag, value);
+            }
+          }
+          input->PopLimit(limit);
+
+          break;
+        }
+        case WireFormatLite::TYPE_STRING:
+        case WireFormatLite::TYPE_GROUP:
+        case WireFormatLite::TYPE_MESSAGE:
+        case WireFormatLite::TYPE_BYTES:
+          GOOGLE_DCHECK(false);
+          return false;
+        default:
+          break;
+      }
+    } else {
+      if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
+        // Must be the end of the message.
+        return true;
+      }
+
+      // check for possible extensions
+      if (UnknownFieldHandler::ParseExtension(msg, table, input, tag)) {
+        // successfully parsed
+        continue;
+      }
+
+      // process unknown field.
+      if (GOOGLE_PREDICT_FALSE(!UnknownFieldHandler::Skip(msg, table, input, tag))) {
+        return false;
+      }
+    }
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_LITE_H__
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index 35d8156..c9dfe61 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -35,7 +35,17 @@
 #include <google/protobuf/generated_message_util.h>
 
 #include <limits>
+#include <vector>
 
+#include <google/protobuf/io/coded_stream_inl.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/wire_format_lite_inl.h>
 
 namespace google {
 namespace protobuf {
@@ -51,7 +61,7 @@
 ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
 GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_);
 
-void DeleteEmptyString() { fixed_address_empty_string.Shutdown(); }
+void DeleteEmptyString() { fixed_address_empty_string.Destruct(); }
 
 void InitEmptyString() {
   fixed_address_empty_string.DefaultConstruct();
@@ -75,6 +85,616 @@
   GetEmptyString();
 }
 
+template <typename T>
+const T& Get(const void* ptr) {
+  return *static_cast<const T*>(ptr);
+}
+
+// PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite.
+// WireFormatLite has a very inconvenient interface with respect to template
+// meta-programming. This class wraps the different named functions into
+// a single Serialize / SerializeToArray interface.
+template <int type>
+struct PrimitiveTypeHelper;
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_BOOL> {
+  typedef bool Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteBoolNoTag(Get<bool>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteBoolNoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {
+  typedef int32 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteInt32NoTag(Get<int32>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteInt32NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT32> {
+  typedef int32 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteSInt32NoTag(Get<int32>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteSInt32NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT32> {
+  typedef uint32 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteUInt32NoTag(Get<uint32>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteUInt32NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_INT64> {
+  typedef int64 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteInt64NoTag(Get<int64>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteInt64NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_SINT64> {
+  typedef int64 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteSInt64NoTag(Get<int64>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteSInt64NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_UINT64> {
+  typedef uint64 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteUInt64NoTag(Get<uint64>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteUInt64NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
+  typedef uint32 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteFixed32NoTag(Get<uint32>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteFixed32NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
+  typedef uint64 Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    WireFormatLite::WriteFixed64NoTag(Get<uint64>(ptr), output);
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    return WireFormatLite::WriteFixed64NoTagToArray(Get<Type>(ptr), buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_ENUM>
+    : PrimitiveTypeHelper<WireFormatLite::TYPE_INT32> {};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED32>
+    : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
+  typedef int32 Type;
+};
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_SFIXED64>
+    : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
+  typedef int64 Type;
+};
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_FLOAT>
+    : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED32> {
+  typedef float Type;
+};
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_DOUBLE>
+    : PrimitiveTypeHelper<WireFormatLite::TYPE_FIXED64> {
+  typedef double Type;
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {
+  typedef string Type;
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    const Type& value = *static_cast<const Type*>(ptr);
+    output->WriteVarint32(value.size());
+    output->WriteRawMaybeAliased(value.data(), value.size());
+  }
+  static uint8* SerializeToArray(const void* ptr, uint8* buffer) {
+    const Type& value = *static_cast<const Type*>(ptr);
+    return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer);
+  }
+};
+
+template <>
+struct PrimitiveTypeHelper<WireFormatLite::TYPE_BYTES>
+    : PrimitiveTypeHelper<WireFormatLite::TYPE_STRING> {};
+
+
+// We want to serialize to both CodedOutputStream and directly into byte arrays
+// without duplicating the code. In fact we might want extra output channels in
+// the future.
+template <typename O, int type>
+struct OutputHelper;
+
+template <int type, typename O>
+void SerializeTo(const void* ptr, O* output) {
+  OutputHelper<O, type>::Serialize(ptr, output);
+}
+
+template <typename O>
+void WriteTagTo(uint32 tag, O* output) {
+  SerializeTo<WireFormatLite::TYPE_UINT32>(&tag, output);
+}
+
+template <typename O>
+void WriteLengthTo(uint32 length, O* output) {
+  SerializeTo<WireFormatLite::TYPE_UINT32>(&length, output);
+}
+
+// Specialization for coded output stream
+template <int type>
+struct OutputHelper< ::google::protobuf::io::CodedOutputStream, type> {
+  static void Serialize(const void* ptr,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+    PrimitiveTypeHelper<type>::Serialize(ptr, output);
+  }
+};
+
+// Specialization for writing into a plain array
+struct ArrayOutput {
+  uint8* ptr;
+  bool is_deterministic;
+};
+
+template <int type>
+struct OutputHelper<ArrayOutput, type> {
+  static void Serialize(const void* ptr, ArrayOutput* output) {
+    output->ptr = PrimitiveTypeHelper<type>::SerializeToArray(ptr, output->ptr);
+  }
+};
+
+void SerializeMessageNoTable(const MessageLite* msg,
+                             ::google::protobuf::io::CodedOutputStream* output) {
+  msg->SerializeWithCachedSizes(output);
+}
+
+void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) {
+  output->ptr = msg->InternalSerializeWithCachedSizesToArray(
+      output->is_deterministic, output->ptr);
+}
+
+// Helper to branch to fast path if possible
+void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
+                              const FieldMetadata* field_table, int num_fields,
+                              int32 cached_size,
+                              ::google::protobuf::io::CodedOutputStream* output) {
+  const uint8* base = reinterpret_cast<const uint8*>(&msg);
+  // Try the fast path
+  uint8* ptr = output->GetDirectBufferForNBytesAndAdvance(cached_size);
+  if (ptr) {
+    // We use virtual dispatch to enable dedicated generated code for the
+    // fast path.
+    msg.InternalSerializeWithCachedSizesToArray(
+        output->IsSerializationDeterministic(), ptr);
+    return;
+  }
+  SerializeInternal(base, field_table, num_fields, output);
+}
+
+// Helper to branch to fast path if possible
+void SerializeMessageDispatch(const ::google::protobuf::MessageLite& msg,
+                              const FieldMetadata* field_table, int num_fields,
+                              int32 cached_size, ArrayOutput* output) {
+  const uint8* base = reinterpret_cast<const uint8*>(&msg);
+  output->ptr = SerializeInternalToArray(base, field_table, num_fields,
+                                         output->is_deterministic, output->ptr);
+}
+
+// Serializing messages is special as it's not a primitive type and needs an
+// explicit overload for each output type.
+template <typename O>
+void SerializeMessageTo(const MessageLite* msg, const void* table_ptr,
+                        O* output) {
+  const SerializationTable* table =
+      static_cast<const SerializationTable*>(table_ptr);
+  if (!table) {
+    // Proto1
+    WriteLengthTo(msg->GetCachedSize(), output);
+    SerializeMessageNoTable(msg, output);
+    return;
+  }
+  const FieldMetadata* field_table = table->field_table;
+  const uint8* base = reinterpret_cast<const uint8*>(msg);
+  int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
+  WriteLengthTo(cached_size, output);
+  int num_fields = table->num_fields - 1;
+  SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
+                           output);
+}
+
+// Almost the same as above only it doesn't output the length field.
+template <typename O>
+void SerializeGroupTo(const MessageLite* msg, const void* table_ptr,
+                      O* output) {
+  const SerializationTable* table =
+      static_cast<const SerializationTable*>(table_ptr);
+  if (!table) {
+    // Proto1
+    SerializeMessageNoTable(msg, output);
+    return;
+  }
+  const FieldMetadata* field_table = table->field_table;
+  const uint8* base = reinterpret_cast<const uint8*>(msg);
+  int cached_size = *reinterpret_cast<const int32*>(base + field_table->offset);
+  int num_fields = table->num_fields - 1;
+  SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size,
+                           output);
+}
+
+template <int type>
+struct SingularFieldHelper {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    WriteTagTo(md.tag, output);
+    SerializeTo<type>(field, output);
+  }
+};
+
+template <>
+struct SingularFieldHelper<WireFormatLite::TYPE_STRING> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    WriteTagTo(md.tag, output);
+    SerializeTo<WireFormatLite::TYPE_STRING>(&Get<ArenaStringPtr>(field).Get(),
+                                             output);
+  }
+};
+
+template <>
+struct SingularFieldHelper<WireFormatLite::TYPE_BYTES>
+    : SingularFieldHelper<WireFormatLite::TYPE_STRING> {};
+
+template <>
+struct SingularFieldHelper<WireFormatLite::TYPE_GROUP> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    WriteTagTo(md.tag, output);
+    SerializeGroupTo(Get<const MessageLite*>(field),
+                     static_cast<const SerializationTable*>(md.ptr), output);
+    WriteTagTo(md.tag + 1, output);
+  }
+};
+
+template <>
+struct SingularFieldHelper<WireFormatLite::TYPE_MESSAGE> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    WriteTagTo(md.tag, output);
+    SerializeMessageTo(Get<const MessageLite*>(field),
+                       static_cast<const SerializationTable*>(md.ptr), output);
+  }
+};
+
+template <int type>
+struct RepeatedFieldHelper {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    typedef typename PrimitiveTypeHelper<type>::Type T;
+    const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
+    for (int i = 0; i < array.size(); i++) {
+      WriteTagTo(md.tag, output);
+      SerializeTo<type>(&array[i], output);
+    }
+  }
+};
+
+// We need to use a helper class to get access to the private members
+class AccessorHelper {
+ public:
+  static int Size(const RepeatedPtrFieldBase& x) { return x.size(); }
+  static void const* Get(const RepeatedPtrFieldBase& x, int idx) {
+    return x.raw_data()[idx];
+  }
+};
+
+template <>
+struct RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    const internal::RepeatedPtrFieldBase& array =
+        Get<internal::RepeatedPtrFieldBase>(field);
+    for (int i = 0; i < AccessorHelper::Size(array); i++) {
+      WriteTagTo(md.tag, output);
+      SerializeTo<WireFormatLite::TYPE_STRING>(AccessorHelper::Get(array, i),
+                                               output);
+    }
+  }
+};
+
+template <>
+struct RepeatedFieldHelper<WireFormatLite::TYPE_BYTES>
+    : RepeatedFieldHelper<WireFormatLite::TYPE_STRING> {};
+
+template <>
+struct RepeatedFieldHelper<WireFormatLite::TYPE_GROUP> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    const internal::RepeatedPtrFieldBase& array =
+        Get<internal::RepeatedPtrFieldBase>(field);
+    for (int i = 0; i < AccessorHelper::Size(array); i++) {
+      WriteTagTo(md.tag, output);
+      SerializeGroupTo(
+          static_cast<const MessageLite*>(AccessorHelper::Get(array, i)),
+          static_cast<const SerializationTable*>(md.ptr), output);
+      WriteTagTo(md.tag + 1, output);
+    }
+  }
+};
+
+template <>
+struct RepeatedFieldHelper<WireFormatLite::TYPE_MESSAGE> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    const internal::RepeatedPtrFieldBase& array =
+        Get<internal::RepeatedPtrFieldBase>(field);
+    for (int i = 0; i < AccessorHelper::Size(array); i++) {
+      WriteTagTo(md.tag, output);
+      SerializeMessageTo(
+          static_cast<const MessageLite*>(AccessorHelper::Get(array, i)), md.ptr,
+          output);
+    }
+  }
+};
+
+
+template <int type>
+struct PackedFieldHelper {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    typedef typename PrimitiveTypeHelper<type>::Type T;
+    const RepeatedField<T>& array = Get<RepeatedField<T> >(field);
+    if (array.empty()) return;
+    WriteTagTo(md.tag, output);
+    int cached_size =
+        Get<int>(static_cast<const uint8*>(field) + sizeof(RepeatedField<T>));
+    WriteLengthTo(cached_size, output);
+    for (int i = 0; i < array.size(); i++) {
+      SerializeTo<type>(&array[i], output);
+    }
+  }
+};
+
+template <>
+struct PackedFieldHelper<WireFormatLite::TYPE_STRING> {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type "
+               << md.type;
+  }
+};
+
+template <>
+struct PackedFieldHelper<WireFormatLite::TYPE_BYTES>
+    : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
+template <>
+struct PackedFieldHelper<WireFormatLite::TYPE_GROUP>
+    : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
+template <>
+struct PackedFieldHelper<WireFormatLite::TYPE_MESSAGE>
+    : PackedFieldHelper<WireFormatLite::TYPE_STRING> {};
+
+template <int type>
+struct OneOfFieldHelper {
+  template <typename O>
+  static void Serialize(const void* field, const FieldMetadata& md, O* output) {
+    SingularFieldHelper<type>::Serialize(field, md, output);
+  }
+};
+
+
+void SerializeNotImplemented(int field) {
+  GOOGLE_LOG(FATAL) << "Not implemented field number " << field;
+}
+
+// When switching to c++11 we should make these constexpr functions
+#define SERIALIZE_TABLE_OP(type, type_class) \
+  ((type - 1) + static_cast<int>(type_class) * FieldMetadata::kNumTypes)
+
+int FieldMetadata::CalculateType(int type,
+                                 FieldMetadata::FieldTypeClass type_class) {
+  return SERIALIZE_TABLE_OP(type, type_class);
+}
+
+template <int type>
+bool IsNull(const void* ptr) {
+  return *static_cast<const typename PrimitiveTypeHelper<type>::Type*>(ptr) ==
+         0;
+}
+
+template <>
+bool IsNull<WireFormatLite::TYPE_STRING>(const void* ptr) {
+  return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
+}
+
+template <>
+bool IsNull<WireFormatLite::TYPE_BYTES>(const void* ptr) {
+  return static_cast<const ArenaStringPtr*>(ptr)->Get().size() == 0;
+}
+
+template <>
+bool IsNull<WireFormatLite::TYPE_GROUP>(const void* ptr) {
+  return Get<const MessageLite*>(ptr) == NULL;
+}
+
+template <>
+bool IsNull<WireFormatLite::TYPE_MESSAGE>(const void* ptr) {
+  return Get<const MessageLite*>(ptr) == NULL;
+}
+
+
+#define SERIALIZERS_FOR_TYPE(type)                                            \
+  case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence):                    \
+    if (!IsPresent(base, field_metadata.has_offset)) continue;                \
+    SingularFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
+    break;                                                                    \
+  case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence):                  \
+    if (IsNull<type>(ptr)) continue;                                          \
+    SingularFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
+    break;                                                                    \
+  case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated):                    \
+    RepeatedFieldHelper<type>::Serialize(ptr, field_metadata, output);        \
+    break;                                                                    \
+  case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked):                      \
+    PackedFieldHelper<type>::Serialize(ptr, field_metadata, output);          \
+    break;                                                                    \
+  case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf):                       \
+    if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \
+      continue;                                                               \
+    OneOfFieldHelper<type>::Serialize(ptr, field_metadata, output);           \
+    break
+
+void SerializeInternal(const uint8* base,
+                       const FieldMetadata* field_metadata_table,
+                       int32 num_fields,
+                       ::google::protobuf::io::CodedOutputStream* output) {
+  for (int i = 0; i < num_fields; i++) {
+    const FieldMetadata& field_metadata = field_metadata_table[i];
+    const uint8* ptr = base + field_metadata.offset;
+    switch (field_metadata.type) {
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
+
+      // Special cases
+      case FieldMetadata::kSpecial:
+        reinterpret_cast<SpecialSerializer>(
+            const_cast<void*>(field_metadata.ptr))(
+            base, field_metadata.offset, field_metadata.tag,
+            field_metadata.has_offset, output);
+        break;
+      default:
+        // __builtin_unreachable()
+        SerializeNotImplemented(field_metadata.type);
+    }
+  }
+}
+
+uint8* SerializeInternalToArray(const uint8* base,
+                                const FieldMetadata* field_metadata_table,
+                                int32 num_fields, bool is_deterministic,
+                                uint8* buffer) {
+  ArrayOutput array_output = {buffer, is_deterministic};
+  ArrayOutput* output = &array_output;
+  for (int i = 0; i < num_fields; i++) {
+    const FieldMetadata& field_metadata = field_metadata_table[i];
+    const uint8* ptr = base + field_metadata.offset;
+    switch (field_metadata.type) {
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32);
+      SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64);
+      // Special cases
+      case FieldMetadata::kSpecial: {
+        io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX);
+        io::CodedOutputStream output(&array_stream);
+        output.SetSerializationDeterministic(is_deterministic);
+        reinterpret_cast<SpecialSerializer>(
+            const_cast<void*>(field_metadata.ptr))(
+            base, field_metadata.offset, field_metadata.tag,
+            field_metadata.has_offset, &output);
+        array_output.ptr += output.ByteCount();
+      } break;
+      default:
+        // __builtin_unreachable()
+        SerializeNotImplemented(field_metadata.type);
+    }
+  }
+  return array_output.ptr;
+}
+#undef SERIALIZERS_FOR_TYPE
+
+void ExtensionSerializer(const uint8* ptr, uint32 offset, uint32 tag,
+                         uint32 has_offset,
+                         ::google::protobuf::io::CodedOutputStream* output) {
+  reinterpret_cast<const ExtensionSet*>(ptr + offset)
+      ->SerializeWithCachedSizes(tag, has_offset, output);
+}
+
+void UnknownFieldSerializerLite(const uint8* ptr, uint32 offset, uint32 tag,
+                                uint32 has_offset,
+                                ::google::protobuf::io::CodedOutputStream* output) {
+  output->WriteString(
+      reinterpret_cast<const InternalMetadataWithArenaLite*>(ptr + offset)
+          ->unknown_fields());
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
index 4417446..096a84c 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -41,25 +41,22 @@
 #include <assert.h>
 #include <climits>
 #include <string>
+#include <vector>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/has_bits.h>
-
-#ifndef PROTOBUF_FINAL
-#if LANG_CXX11 && !defined(__NVCC__)
-#define PROTOBUF_FINAL final
-#else
-#define PROTOBUF_FINAL
-#endif
-#endif  // !PROTOBUF_FINAL
+#include <google/protobuf/map_entry_lite.h>
+#include <google/protobuf/message_lite.h>
+#include <google/protobuf/wire_format_lite.h>
 
 namespace google {
 
 namespace protobuf {
 
 class Arena;
+
 namespace io { class CodedInputStream; }
 
 namespace internal {
@@ -100,86 +97,16 @@
 // choose 16 rather than some other number just in case the compiler would
 // be confused by an unaligned pointer.
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD)  \
-  static_cast<int>(                                                  \
+  static_cast< ::google::protobuf::uint32>(                           \
       reinterpret_cast<const char*>(                                 \
           &reinterpret_cast<const TYPE*>(16)->FIELD) -               \
       reinterpret_cast<const char*>(16))
 #endif
 
-#define GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD)  \
-  static_cast< ::google::protobuf::uint32>(                                                    \
-      reinterpret_cast<const char*>(&(ONEOF->FIELD))                        \
-      - reinterpret_cast<const char*>(ONEOF))
-// TODO(acozzette): remove this transitional macro after updating generated code
-#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD)
-
 // Constants for special floating point values.
 LIBPROTOBUF_EXPORT double Infinity();
 LIBPROTOBUF_EXPORT double NaN();
 
-// This type is used to define a global variable, without it's constructor
-// and destructor run on start and end of the program lifetime. This circumvents
-// the initial construction order fiasco, while keeping the address of the
-// empty string a compile time constant.
-template <typename T>
-class ExplicitlyConstructed {
- public:
-  void DefaultConstruct() {
-    new (&union_) T();
-    init_ = true;
-  }
-
-  bool IsInitialized() { return init_; }
-  void Shutdown() {
-    if (init_) {
-      init_ = false;
-      get_mutable()->~T();
-    }
-  }
-
-#if LANG_CXX11
-  constexpr
-#endif
-      const T&
-      get() const {
-    return reinterpret_cast<const T&>(union_);
-  }
-  T* get_mutable() { return reinterpret_cast<T*>(&union_); }
-
- private:
-  // Prefer c++14 aligned_storage, but for compatibility this will do.
-  union AlignedUnion {
-    char space[sizeof(T)];
-    int64 align_to_int64;
-    void* align_to_ptr;
-  } union_;
-  bool init_;  // false by linker
-};
-
-// TODO(jieluo): Change to template. We have tried to use template,
-// but it causes net/rpc/python:rpcutil_test fail (the empty string will
-// init twice). It may related to swig. Change to template after we
-// found the solution.
-
-// Default empty string object. Don't use this directly. Instead, call
-// GetEmptyString() to get the reference.
-extern ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
-LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_;
-LIBPROTOBUF_EXPORT void InitEmptyString();
-
-
-LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
-  return fixed_address_empty_string.get();
-}
-
-LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
-  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
-  return GetEmptyStringAlreadyInited();
-}
-
-LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str);
-
 
 // True if IsInitialized() is true for all elements of t.  Type is expected
 // to be a RepeatedPtrField<some message type>.  It's useful to have this
@@ -195,32 +122,156 @@
 
 LIBPROTOBUF_EXPORT void InitProtobufDefaults();
 
-// We compute sizes as size_t but cache them as int.  This function converts a
-// computed size to a cached size.  Since we don't proceed with serialization if
-// the total size was > INT_MAX, it is not important what this function returns
-// for inputs > INT_MAX.  However this case should not error or GOOGLE_CHECK-fail,
-// because the full size_t resolution is still returned from ByteSizeLong() and
-// checked against INT_MAX; we can catch the overflow there.
-inline int ToCachedSize(size_t size) {
-  return static_cast<int>(size);
+struct LIBPROTOBUF_EXPORT FieldMetadata {
+  uint32 offset;  // offset of this field in the struct
+  uint32 tag;     // field * 8 + wire_type
+  // byte offset * 8 + bit_offset;
+  // if the high bit is set then this is the byte offset of the oneof_case
+  // for this field.
+  uint32 has_offset;
+  uint32 type;      // the type of this field.
+  const void* ptr;  // auxiliary data
+
+  // From the serializer point of view each fundamental type can occur in
+  // 4 different ways. For simplicity we treat all combinations as a cartesion
+  // product although not all combinations are allowed.
+  enum FieldTypeClass {
+    kPresence,
+    kNoPresence,
+    kRepeated,
+    kPacked,
+    kOneOf,
+    kNumTypeClasses  // must be last enum
+  };
+  // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
+  // and also distinquish the same types if they have different wire format.
+  enum {
+    kCordType = 19,
+    kStringPieceType = 20,
+    kNumTypes = 20,
+    kSpecial = kNumTypes * kNumTypeClasses,
+  };
+
+  static int CalculateType(int fundamental_type, FieldTypeClass type_class);
+};
+
+inline bool IsPresent(const void* base, uint32 hasbit) {
+  const uint32* has_bits_array = static_cast<const uint32*>(base);
+  return has_bits_array[hasbit / 32] & (1u << (hasbit & 31));
 }
 
-// For cases where a legacy function returns an integer size.  We GOOGLE_DCHECK() that
-// the conversion will fit within an integer; if this is false then we are
-// losing information.
-inline int ToIntSize(size_t size) {
-  GOOGLE_DCHECK_LE(size, static_cast<size_t>(INT_MAX));
-  return static_cast<int>(size);
+inline bool IsOneofPresent(const void* base, uint32 offset, uint32 tag) {
+  const uint32* oneof =
+      reinterpret_cast<const uint32*>(static_cast<const uint8*>(base) + offset);
+  return *oneof == tag >> 3;
 }
 
-// We mainly calculate sizes in terms of size_t, but some functions that compute
-// sizes return "int".  These int sizes are expected to always be positive.
-// This function is more efficient than casting an int to size_t directly on
-// 64-bit platforms because it avoids making the compiler emit a sign extending
-// instruction, which we don't want and don't want to pay for.
-inline size_t FromIntSize(int size) {
-  // Convert to unsigned before widening so sign extension is not necessary.
-  return static_cast<unsigned int>(size);
+typedef void (*SpecialSerializer)(const uint8* base, uint32 offset, uint32 tag,
+                                  uint32 has_offset,
+                                  ::google::protobuf::io::CodedOutputStream* output);
+
+LIBPROTOBUF_EXPORT void ExtensionSerializer(const uint8* base, uint32 offset, uint32 tag,
+                         uint32 has_offset,
+                         ::google::protobuf::io::CodedOutputStream* output);
+LIBPROTOBUF_EXPORT void UnknownFieldSerializerLite(const uint8* base, uint32 offset, uint32 tag,
+                                uint32 has_offset,
+                                ::google::protobuf::io::CodedOutputStream* output);
+
+struct SerializationTable {
+  int num_fields;
+  const FieldMetadata* field_table;
+};
+
+LIBPROTOBUF_EXPORT void SerializeInternal(const uint8* base, const FieldMetadata* table,
+                       int num_fields, ::google::protobuf::io::CodedOutputStream* output);
+
+inline void TableSerialize(const ::google::protobuf::MessageLite& msg,
+                           const SerializationTable* table,
+                           ::google::protobuf::io::CodedOutputStream* output) {
+  const FieldMetadata* field_table = table->field_table;
+  int num_fields = table->num_fields - 1;
+  const uint8* base = reinterpret_cast<const uint8*>(&msg);
+  // TODO(gerbens) This skips the first test if we could use the fast
+  // array serialization path, we should make this
+  // int cached_size =
+  //    *reinterpret_cast<const int32*>(base + field_table->offset);
+  // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
+  // But we keep conformance with the old way for now.
+  SerializeInternal(base, field_table + 1, num_fields, output);
+}
+
+uint8* SerializeInternalToArray(const uint8* base, const FieldMetadata* table,
+                                int num_fields, bool is_deterministic,
+                                uint8* buffer);
+
+inline uint8* TableSerializeToArray(const ::google::protobuf::MessageLite& msg,
+                                    const SerializationTable* table,
+                                    bool is_deterministic, uint8* buffer) {
+  const uint8* base = reinterpret_cast<const uint8*>(&msg);
+  const FieldMetadata* field_table = table->field_table + 1;
+  int num_fields = table->num_fields - 1;
+  return SerializeInternalToArray(base, field_table, num_fields,
+                                  is_deterministic, buffer);
+}
+
+template <typename T>
+struct CompareHelper {
+  bool operator()(const T& a, const T& b) { return a < b; }
+};
+
+template <>
+struct CompareHelper<ArenaStringPtr> {
+  bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) {
+    return a.Get() < b.Get();
+  }
+};
+
+struct CompareMapKey {
+  template <typename T>
+  bool operator()(const MapEntryHelper<T>& a, const MapEntryHelper<T>& b) {
+    return Compare(a.key_, b.key_);
+  }
+  template <typename T>
+  bool Compare(const T& a, const T& b) {
+    return CompareHelper<T>()(a, b);
+  }
+};
+
+template <typename MapFieldType, const SerializationTable* table>
+void MapFieldSerializer(const uint8* base, uint32 offset, uint32 tag,
+                        uint32 has_offset,
+                        ::google::protobuf::io::CodedOutputStream* output) {
+  typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
+  typedef typename MapFieldType::MapType::const_iterator Iter;
+
+  const MapFieldType& map_field =
+      *reinterpret_cast<const MapFieldType*>(base + offset);
+  const SerializationTable* t =
+      table +
+      has_offset;  // has_offset is overloaded for maps to mean table offset
+  if (!output->IsSerializationDeterministic()) {
+    for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
+         ++it) {
+      Entry map_entry(*it);
+      output->WriteVarint32(tag);
+      output->WriteVarint32(map_entry._cached_size_);
+      SerializeInternal(reinterpret_cast<const uint8*>(&map_entry),
+                        t->field_table, t->num_fields, output);
+    }
+  } else {
+    std::vector<Entry> v;
+    for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
+         ++it) {
+      v.push_back(Entry(*it));
+    }
+    std::sort(v.begin(), v.end(), CompareMapKey());
+    for (int i = 0; i < v.size(); i++) {
+      output->WriteVarint32(tag);
+      output->WriteVarint32(v[i]._cached_size_);
+      SerializeInternal(reinterpret_cast<const uint8*>(&v[i]), t->field_table,
+                        t->num_fields, output);
+    }
+  }
 }
 
 }  // namespace internal
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index df4250e..17eb0ff 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -197,17 +197,7 @@
                 "in google/protobuf/io/coded_stream.h.";
 }
 
-bool CodedInputStream::Skip(int count) {
-  if (count < 0) return false;  // security: count is often user-supplied
-
-  const int original_buffer_size = BufferSize();
-
-  if (count <= original_buffer_size) {
-    // Just skipping within the current buffer.  Easy.
-    Advance(count);
-    return true;
-  }
-
+bool CodedInputStream::SkipFallback(int count, int original_buffer_size) {
   if (buffer_size_after_limit_ > 0) {
     // We hit a limit inside this buffer.  Advance to the limit and fail.
     Advance(original_buffer_size);
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 20d8614..6d2599f 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -184,7 +184,7 @@
 
   // Skips a number of bytes.  Returns false if an underlying read error
   // occurs.
-  bool Skip(int count);
+  inline bool Skip(int count);
 
   // Sets *data to point directly at the unread part of the CodedInputStream's
   // underlying buffer, and *size to the size of that buffer, but does not
@@ -261,7 +261,10 @@
   // Always inline because this is only called in one place per parse loop
   // but it is called for every iteration of said loop, so it should be fast.
   // GCC doesn't want to inline this by default.
-  GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag();
+  GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTag() {
+    return last_tag_ = ReadTagNoLastTag();
+  }
+
   GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTagNoLastTag();
 
 
@@ -274,7 +277,12 @@
   // because that can arise in several ways, and for best performance we want
   // to avoid an extra "is tag == 0?" check here.)
   GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair<uint32, bool> ReadTagWithCutoff(
-      uint32 cutoff);
+      uint32 cutoff) {
+    std::pair<uint32, bool> result = ReadTagWithCutoffNoLastTag(cutoff);
+    last_tag_ = result.first;
+    return result;
+  }
+
   GOOGLE_ATTRIBUTE_ALWAYS_INLINE std::pair<uint32, bool> ReadTagWithCutoffNoLastTag(
       uint32 cutoff);
 
@@ -316,6 +324,7 @@
   // tag to make sure it had the right number, so it calls LastTagWas() on
   // return from the embedded parser to check.
   bool LastTagWas(uint32 expected);
+  void SetLastTag(uint32 tag) { last_tag_ = tag; }
 
   // When parsing message (but NOT a group), this method must be called
   // immediately after MergeFromCodedStream() returns (if it returns true)
@@ -584,6 +593,9 @@
 
   // Private member functions.
 
+  // Fallback when Skip() goes past the end of the current buffer.
+  bool SkipFallback(int count, int original_buffer_size);
+
   // Advance the buffer by a given number of bytes.
   void Advance(int amount);
 
@@ -621,12 +633,6 @@
   bool ReadLittleEndian32Fallback(uint32* value);
   bool ReadLittleEndian64Fallback(uint64* value);
 
-  template<bool update_last_tag>
-  GOOGLE_ATTRIBUTE_ALWAYS_INLINE uint32 ReadTagImplementation();
-  template<bool update_last_tag>
-  GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-  std::pair<uint32, bool> ReadTagWithCutoffImplementation(uint32 cutoff);
-
   // Fallback/slow methods for reading tags. These do not update last_tag_,
   // but will set legitimate_message_end_ if we are at the end of the input
   // stream.
@@ -1018,48 +1024,21 @@
 #endif
 }
 
-inline uint32 CodedInputStream::ReadTag() {
-  return ReadTagImplementation<true>();
-}
-
 inline uint32 CodedInputStream::ReadTagNoLastTag() {
-  return ReadTagImplementation<false>();
-}
-
-template<bool update_last_tag>
-inline uint32 CodedInputStream::ReadTagImplementation() {
   uint32 v = 0;
   if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) {
     v = *buffer_;
     if (v < 0x80) {
-      if (update_last_tag) {
-        last_tag_ = v;
-      }
       Advance(1);
       return v;
     }
   }
   v = ReadTagFallback(v);
-  if (update_last_tag) {
-    last_tag_ = v;
-  }
   return v;
 }
 
-inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoff(
-    uint32 cutoff) {
-  return ReadTagWithCutoffImplementation<true>(cutoff);
-}
-
 inline std::pair<uint32, bool> CodedInputStream::ReadTagWithCutoffNoLastTag(
     uint32 cutoff) {
-  return ReadTagWithCutoffImplementation<false>(cutoff);
-}
-
-template<bool update_last_tag>
-inline std::pair<uint32, bool>
-CodedInputStream::ReadTagWithCutoffImplementation(
-    uint32 cutoff) {
   // In performance-sensitive code we can expect cutoff to be a compile-time
   // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at
   // compile time.
@@ -1072,9 +1051,6 @@
     if (static_cast<int8>(buffer_[0]) > 0) {
       const uint32 kMax1ByteVarint = 0x7f;
       uint32 tag = buffer_[0];
-      if (update_last_tag) {
-        last_tag_ = tag;
-      }
       Advance(1);
       return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff);
     }
@@ -1086,9 +1062,6 @@
         GOOGLE_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) {
       const uint32 kMax2ByteVarint = (0x7f << 7) + 0x7f;
       uint32 tag = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80);
-      if (update_last_tag) {
-        last_tag_ = tag;
-      }
       Advance(2);
       // It might make sense to test for tag == 0 now, but it is so rare that
       // that we don't bother.  A varint-encoded 0 should be one byte unless
@@ -1102,9 +1075,6 @@
   }
   // Slow path
   const uint32 tag = ReadTagFallback(first_byte_or_zero);
-  if (update_last_tag) {
-    last_tag_ = tag;
-  }
   return std::make_pair(tag, static_cast<uint32>(tag - 1) < cutoff);
 }
 
@@ -1430,11 +1400,25 @@
   return input_ == NULL;
 }
 
+inline bool CodedInputStream::Skip(int count) {
+  if (count < 0) return false;  // security: count is often user-supplied
+
+  const int original_buffer_size = BufferSize();
+
+  if (count <= original_buffer_size) {
+    // Just skipping within the current buffer.  Easy.
+    Advance(count);
+    return true;
+  }
+
+  return SkipFallback(count, original_buffer_size);
+}
+
 }  // namespace io
 }  // namespace protobuf
 
 
-#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+#if defined(_MSC_VER) && _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
   #pragma runtime_checks("c", restore)
 #endif  // _MSC_VER && !defined(__INTEL_COMPILER)
 
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 99e895f..8493268 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -111,6 +111,7 @@
   int size = strlen(text);
   int pos = 0;  // The number of bytes we've written so far.
   substitutions_.clear();
+  line_start_variables_.clear();
 
   for (int i = 0; i < size; i++) {
     if (text[i] == '\n') {
@@ -122,6 +123,7 @@
       // Setting this true will cause the next WriteRaw() to insert an indent
       // first.
       at_start_of_line_ = true;
+      line_start_variables_.clear();
 
     } else if (text[i] == variable_delimiter_) {
       // Saw the start of a variable name.
@@ -148,12 +150,15 @@
         if (iter == variables.end()) {
           GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
         } else {
-          size_t begin = offset_;
+          if (at_start_of_line_ && iter->second.empty()) {
+            line_start_variables_.push_back(varname);
+          }
           WriteRaw(iter->second.data(), iter->second.size());
           std::pair<std::map<string, std::pair<size_t, size_t> >::iterator,
                     bool>
-              inserted = substitutions_.insert(
-                  std::make_pair(varname, std::make_pair(begin, offset_)));
+              inserted = substitutions_.insert(std::make_pair(
+                  varname,
+                  std::make_pair(offset_ - iter->second.size(), offset_)));
           if (!inserted.second) {
             // This variable was used multiple times.  Make its span have
             // negative length so we can detect it if it gets used in an
@@ -319,10 +324,29 @@
   if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
     // Insert an indent.
     at_start_of_line_ = false;
-    WriteRaw(indent_.data(), indent_.size());
+    CopyToBuffer(indent_.data(), indent_.size());
     if (failed_) return;
+    // Fix up empty variables (e.g., "{") that should be annotated as
+    // coming after the indent.
+    for (std::vector<string>::iterator i = line_start_variables_.begin();
+         i != line_start_variables_.end(); ++i) {
+      substitutions_[*i].first += indent_.size();
+      substitutions_[*i].second += indent_.size();
+    }
   }
 
+  // If we're going to write any data, clear line_start_variables_, since
+  // we've either updated them in the block above or they no longer refer to
+  // the current line.
+  line_start_variables_.clear();
+
+  CopyToBuffer(data, size);
+}
+
+void Printer::CopyToBuffer(const char* data, int size) {
+  if (failed_) return;
+  if (size == 0) return;
+
   while (size > buffer_size_) {
     // Data exceeds space in the buffer.  Copy what we can and request a
     // new buffer.
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index e666445..d11745c 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -157,7 +157,7 @@
 //   vars["function"] = "call";
 //   vars["mark"] = "";
 //   printer.Print(vars, "$function$($foo$,$foo$)$mark$");
-//   printer.Annotate("function", "rmark", call_);
+//   printer.Annotate("function", "mark", call_);
 //
 // This code associates the span covering "call(bar,bar)" in the output with the
 // call_ descriptor.
@@ -311,6 +311,9 @@
   void Annotate(const char* begin_varname, const char* end_varname,
                 const string& file_path, const std::vector<int>& path);
 
+  // Copy size worth of bytes from data to buffer_.
+  void CopyToBuffer(const char* data, int size);
+
   const char variable_delimiter_;
 
   ZeroCopyOutputStream* const output_;
@@ -334,6 +337,11 @@
   // length of the substituted string).
   std::map<string, std::pair<size_t, size_t> > substitutions_;
 
+  // Keeps track of the keys in substitutions_ that need to be updated when
+  // indents are inserted. These are keys that refer to the beginning of the
+  // current line.
+  std::vector<string> line_start_variables_;
+
   // Returns true and sets range to the substitution range in the output for
   // varname if varname was used once in the last call to Print. If varname
   // was not used, or if it was used multiple times, returns false (and
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index 0435228..d0a0ebe 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -360,6 +360,83 @@
   EXPECT_EQ(7, bar->end());
 }
 
+TEST(Printer, AnnotateIndent) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Print("0\n");
+    printer.Indent();
+    printer.Print("$foo$", "foo", "4");
+    std::vector<int> path;
+    path.push_back(44);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("foo", &descriptor);
+    printer.Print(",\n");
+    printer.Print("$bar$", "bar", "9");
+    path[0] = 99;
+    MockDescriptor descriptor_two("path", path);
+    printer.Annotate("bar", &descriptor_two);
+    printer.Print("\n${$$D$$}$\n", "{", "", "}", "", "D", "d");
+    path[0] = 1313;
+    MockDescriptor descriptor_three("path", path);
+    printer.Annotate("{", "}", &descriptor_three);
+    printer.Outdent();
+    printer.Print("\n");
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("0\n  4,\n  9\n  d\n\n", buffer);
+  ASSERT_EQ(3, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* foo = &info.annotation(0);
+  ASSERT_EQ(1, foo->path_size());
+  EXPECT_EQ(44, foo->path(0));
+  EXPECT_EQ("path", foo->source_file());
+  EXPECT_EQ(4, foo->begin());
+  EXPECT_EQ(5, foo->end());
+  const GeneratedCodeInfo::Annotation* bar = &info.annotation(1);
+  ASSERT_EQ(1, bar->path_size());
+  EXPECT_EQ(99, bar->path(0));
+  EXPECT_EQ("path", bar->source_file());
+  EXPECT_EQ(9, bar->begin());
+  EXPECT_EQ(10, bar->end());
+  const GeneratedCodeInfo::Annotation* braces = &info.annotation(2);
+  ASSERT_EQ(1, braces->path_size());
+  EXPECT_EQ(1313, braces->path(0));
+  EXPECT_EQ("path", braces->source_file());
+  EXPECT_EQ(13, braces->begin());
+  EXPECT_EQ(14, braces->end());
+}
+
+TEST(Printer, AnnotateIndentNewline) {
+  char buffer[8192];
+  ArrayOutputStream output(buffer, sizeof(buffer));
+  GeneratedCodeInfo info;
+  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+  {
+    Printer printer(&output, '$', &info_collector);
+    printer.Indent();
+    printer.Print("$A$$N$$B$C\n", "A", "", "N", "\nz", "B", "");
+    std::vector<int> path;
+    path.push_back(0);
+    MockDescriptor descriptor("path", path);
+    printer.Annotate("A", "B", &descriptor);
+    printer.Outdent();
+    printer.Print("\n");
+  }
+  buffer[output.ByteCount()] = '\0';
+  EXPECT_STREQ("\nz  C\n\n", buffer);
+  ASSERT_EQ(1, info.annotation_size());
+  const GeneratedCodeInfo::Annotation* ab = &info.annotation(0);
+  ASSERT_EQ(1, ab->path_size());
+  EXPECT_EQ(0, ab->path(0));
+  EXPECT_EQ("path", ab->source_file());
+  EXPECT_EQ(0, ab->begin());
+  EXPECT_EQ(4, ab->end());
+}
+
+
 TEST(Printer, Indenting) {
   char buffer[8192];
 
diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc
index 186de00..f81555e 100644
--- a/src/google/protobuf/io/zero_copy_stream.cc
+++ b/src/google/protobuf/io/zero_copy_stream.cc
@@ -41,9 +41,6 @@
 namespace protobuf {
 namespace io {
 
-ZeroCopyInputStream::~ZeroCopyInputStream() {}
-ZeroCopyOutputStream::~ZeroCopyOutputStream() {}
-
 
 bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */,
                                            int /* size */) {
diff --git a/src/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h
index 52650fc..62ace7a 100644
--- a/src/google/protobuf/io/zero_copy_stream.h
+++ b/src/google/protobuf/io/zero_copy_stream.h
@@ -123,8 +123,8 @@
 // copying.
 class LIBPROTOBUF_EXPORT ZeroCopyInputStream {
  public:
-  inline ZeroCopyInputStream() {}
-  virtual ~ZeroCopyInputStream();
+  ZeroCopyInputStream() {}
+  virtual ~ZeroCopyInputStream() {}
 
   // Obtains a chunk of data from the stream.
   //
@@ -180,8 +180,8 @@
 // copying.
 class LIBPROTOBUF_EXPORT ZeroCopyOutputStream {
  public:
-  inline ZeroCopyOutputStream() {}
-  virtual ~ZeroCopyOutputStream();
+  ZeroCopyOutputStream() {}
+  virtual ~ZeroCopyOutputStream() {}
 
   // Obtains a buffer into which data can be written.  Any data written
   // into this buffer will eventually (maybe instantly, maybe later on)
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index 109c55c..81fb503 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -32,9 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -43,9 +41,9 @@
 #include <errno.h>
 #include <iostream>
 #include <algorithm>
-
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/stl_util.h>
 
@@ -60,6 +58,16 @@
 #define lseek(fd, offset, origin) ((off_t)-1)
 #endif
 
+#ifdef _MSC_VER
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::open;
+using google::protobuf::internal::win32::read;
+using google::protobuf::internal::win32::write;
+#endif
+
 namespace {
 
 // EINTR sucks.
@@ -81,8 +89,6 @@
     impl_(&copying_input_, block_size) {
 }
 
-FileInputStream::~FileInputStream() {}
-
 bool FileInputStream::Close() {
   return copying_input_.Close();
 }
@@ -273,8 +279,6 @@
 IstreamInputStream::IstreamInputStream(std::istream* input, int block_size)
     : copying_input_(input), impl_(&copying_input_, block_size) {}
 
-IstreamInputStream::~IstreamInputStream() {}
-
 bool IstreamInputStream::Next(const void** data, int* size) {
   return impl_.Next(data, size);
 }
@@ -348,9 +352,6 @@
   : streams_(streams), stream_count_(count), bytes_retired_(0) {
 }
 
-ConcatenatingInputStream::~ConcatenatingInputStream() {
-}
-
 bool ConcatenatingInputStream::Next(const void** data, int* size) {
   while (stream_count_ > 0) {
     if (streams_[0]->Next(data, size)) return true;
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
index 3365790..ea978bf 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -67,7 +67,6 @@
   // should be read and returned with each call to Next().  Otherwise,
   // a reasonable default is used.
   explicit FileInputStream(int file_descriptor, int block_size = -1);
-  ~FileInputStream();
 
   // Flushes any buffers and closes the underlying file.  Returns false if
   // an error occurs during the process; use GetErrno() to examine the error.
@@ -219,7 +218,6 @@
   // should be read and returned with each call to Next().  Otherwise,
   // a reasonable default is used.
   explicit IstreamInputStream(std::istream* stream, int block_size = -1);
-  ~IstreamInputStream();
 
   // implements ZeroCopyInputStream ----------------------------------
   bool Next(const void** data, int* size);
@@ -306,7 +304,6 @@
   // All streams passed in as well as the array itself must remain valid
   // until the ConcatenatingInputStream is destroyed.
   ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
-  ~ConcatenatingInputStream();
 
   // implements ZeroCopyInputStream ----------------------------------
   bool Next(const void** data, int* size);
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
index e6ca88c..60c71c8 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -64,9 +64,6 @@
     last_returned_size_(0) {
 }
 
-ArrayInputStream::~ArrayInputStream() {
-}
-
 bool ArrayInputStream::Next(const void** data, int* size) {
   if (position_ < size_) {
     last_returned_size_ = std::min(block_size_, size_ - position_);
@@ -117,9 +114,6 @@
     last_returned_size_(0) {
 }
 
-ArrayOutputStream::~ArrayOutputStream() {
-}
-
 bool ArrayOutputStream::Next(void** data, int* size) {
   if (position_ < size_) {
     last_returned_size_ = std::min(block_size_, size_ - position_);
@@ -153,9 +147,6 @@
   : target_(target) {
 }
 
-StringOutputStream::~StringOutputStream() {
-}
-
 bool StringOutputStream::Next(void** data, int* size) {
   GOOGLE_CHECK(target_ != NULL);
   int old_size = target_->size();
@@ -212,9 +203,6 @@
       string_is_set_(false) {
 }
 
-LazyStringOutputStream::~LazyStringOutputStream() {
-}
-
 bool LazyStringOutputStream::Next(void** data, int* size) {
   if (!string_is_set_) {
     SetString(callback_->Run());
@@ -229,8 +217,6 @@
 
 // ===================================================================
 
-CopyingInputStream::~CopyingInputStream() {}
-
 int CopyingInputStream::Skip(int count) {
   char junk[4096];
   int skipped = 0;
@@ -350,8 +336,6 @@
 
 // ===================================================================
 
-CopyingOutputStream::~CopyingOutputStream() {}
-
 CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
     CopyingOutputStream* copying_stream, int block_size)
   : copying_stream_(copying_stream),
diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
index 6db1d69..a7bbc62 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -73,7 +73,6 @@
   // useful for testing; in production you would probably never want to set
   // it.
   ArrayInputStream(const void* data, int size, int block_size = -1);
-  ~ArrayInputStream();
 
   // implements ZeroCopyInputStream ----------------------------------
   bool Next(const void** data, int* size);
@@ -107,7 +106,6 @@
   // useful for testing; in production you would probably never want to set
   // it.
   ArrayOutputStream(void* data, int size, int block_size = -1);
-  ~ArrayOutputStream();
 
   // implements ZeroCopyOutputStream ---------------------------------
   bool Next(void** data, int* size);
@@ -141,7 +139,6 @@
   //   the first call to Next() will return at least n bytes of buffer
   //   space.
   explicit StringOutputStream(string* target);
-  ~StringOutputStream();
 
   // implements ZeroCopyOutputStream ---------------------------------
   bool Next(void** data, int* size);
@@ -167,7 +164,6 @@
   // Callback should be permanent (non-self-deleting). Ownership is transferred
   // to the LazyStringOutputStream.
   explicit LazyStringOutputStream(ResultCallback<string*>* callback);
-  ~LazyStringOutputStream();
 
   // implements ZeroCopyOutputStream, overriding StringOutputStream -----------
   bool Next(void** data, int* size);
@@ -199,7 +195,7 @@
 // in large blocks.
 class LIBPROTOBUF_EXPORT CopyingInputStream {
  public:
-  virtual ~CopyingInputStream();
+  virtual ~CopyingInputStream() {}
 
   // Reads up to "size" bytes into the given buffer.  Returns the number of
   // bytes read.  Read() waits until at least one byte is available, or
@@ -293,7 +289,7 @@
 // in large blocks.
 class LIBPROTOBUF_EXPORT CopyingOutputStream {
  public:
-  virtual ~CopyingOutputStream();
+  virtual ~CopyingOutputStream() {}
 
   // Writes "size" bytes from the given buffer to the output.  Returns true
   // if successful, false on a write error.
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index 235cbca..2bca6a9 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -47,9 +47,7 @@
 //   implementations.
 
 
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <stdlib.h>
@@ -72,6 +70,7 @@
 #endif
 
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/testing/googletest.h>
 #include <google/protobuf/testing/file.h>
@@ -86,6 +85,15 @@
 #define pipe(fds) _pipe(fds, 4096, O_BINARY)
 #endif
 
+#ifdef _MSC_VER
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::mkdir;
+using google::protobuf::internal::win32::open;
+using google::protobuf::internal::win32::close;
+#endif
+
 #ifndef O_BINARY
 #ifdef _O_BINARY
 #define O_BINARY _O_BINARY
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index 2f5268a..6cf1662 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -48,6 +48,8 @@
 
 #include <google/protobuf/stubs/strutil.h>
 
+using std::string;
+
 namespace {
 // Helper methods to test parsing merge behavior.
 void ExpectMessageMerged(const google::protobuf::unittest::TestAllTypesLite& message) {
@@ -71,7 +73,7 @@
   protobuf_unittest::TestAllTypesLite message;
   google::protobuf::TestUtilLite::ExpectClear(message);
   google::protobuf::TestUtilLite::SetAllFields(&message);
-  std::string data = message.SerializeAsString();
+  string data = message.SerializeAsString();
   empty_message->ParseFromString(data);
 }
 
@@ -83,14 +85,14 @@
   message.set_optional_int64(102);
   message.set_optional_uint32(103);
   message.set_optional_uint64(104);
-  std::string data = message.SerializeAsString();
+  string data = message.SerializeAsString();
   empty_message->ParseFromString(data);
 }
 
 }  // namespace
 
 TEST(Lite, AllLite1) {
-  std::string data;
+  string data;
 
   {
     protobuf_unittest::TestAllTypesLite message, message2, message3;
@@ -110,13 +112,13 @@
 }
 
 TEST(Lite, AllLite2) {
-  std::string data;
+  string data;
   {
     protobuf_unittest::TestAllExtensionsLite message, message2, message3;
     google::protobuf::TestUtilLite::ExpectExtensionsClear(message);
     google::protobuf::TestUtilLite::SetAllExtensions(&message);
     message2.CopyFrom(message);
-    std::string extensions_data = message.SerializeAsString();
+    string extensions_data = message.SerializeAsString();
     message3.ParseFromString(extensions_data);
     google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message);
     google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2);
@@ -129,7 +131,7 @@
 }
 
 TEST(Lite, AllLite3) {
-  std::string data, packed_data;
+  string data, packed_data;
 
   {
     protobuf_unittest::TestPackedTypesLite message, message2, message3;
@@ -152,7 +154,7 @@
     google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message);
     google::protobuf::TestUtilLite::SetPackedExtensions(&message);
     message2.CopyFrom(message);
-    std::string packed_extensions_data = message.SerializeAsString();
+    string packed_extensions_data = message.SerializeAsString();
     EXPECT_EQ(packed_extensions_data, packed_data);
     message3.ParseFromString(packed_extensions_data);
     google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message);
@@ -166,7 +168,7 @@
 }
 
 TEST(Lite, AllLite5) {
-  std::string data;
+  string data;
 
   {
     // Test that if an optional or required message/group field appears multiple
@@ -200,7 +202,7 @@
 
 #undef ASSIGN_REPEATED_GROUP
 
-    std::string buffer;
+    string buffer;
     generator.SerializeToString(&buffer);
     google::protobuf::unittest::TestParsingMergeLite parsing_merge;
     parsing_merge.ParseFromString(buffer);
@@ -223,7 +225,7 @@
 }
 
 TEST(Lite, AllLite6) {
-  std::string data;
+  string data;
 
   // Test unknown fields support for lite messages.
   {
@@ -244,7 +246,7 @@
 }
 
 TEST(Lite, AllLite7) {
-  std::string data;
+  string data;
 
   {
     protobuf_unittest::TestAllExtensionsLite message, message2;
@@ -264,7 +266,7 @@
 }
 
 TEST(Lite, AllLite8) {
-  std::string data;
+  string data;
 
   {
     protobuf_unittest::TestPackedTypesLite message, message2;
@@ -284,7 +286,7 @@
 }
 
 TEST(Lite, AllLite9) {
-  std::string data;
+  string data;
 
   {
     protobuf_unittest::TestPackedExtensionsLite message, message2;
@@ -304,7 +306,7 @@
 }
 
 TEST(Lite, AllLite10) {
-  std::string data;
+  string data;
 
   {
     // Test Unknown fields swap
@@ -312,7 +314,7 @@
     SetAllTypesInEmptyMessageUnknownFields(&empty_message);
     SetSomeTypesInEmptyMessageUnknownFields(&empty_message2);
     data = empty_message.SerializeAsString();
-    std::string data2 = empty_message2.SerializeAsString();
+    string data2 = empty_message2.SerializeAsString();
     empty_message.Swap(&empty_message2);
     EXPECT_EQ(data, empty_message2.SerializeAsString());
     EXPECT_EQ(data2, empty_message.SerializeAsString());
@@ -320,7 +322,7 @@
 }
 
 TEST(Lite, AllLite11) {
-  std::string data;
+  string data;
 
   {
     // Test unknown fields swap with self
@@ -333,7 +335,7 @@
 }
 
 TEST(Lite, AllLite12) {
-  std::string data;
+  string data;
 
   {
     // Test MergeFrom with unknown fields
@@ -363,12 +365,12 @@
 }
 
 TEST(Lite, AllLite13) {
-  std::string data;
+  string data;
 
   {
     // Test unknown enum value
     protobuf_unittest::TestAllTypesLite message;
-    std::string buffer;
+    string buffer;
     {
       google::protobuf::io::StringOutputStream output_stream(&buffer);
       google::protobuf::io::CodedOutputStream coded_output(&output_stream);
@@ -388,7 +390,7 @@
 }
 
 TEST(Lite, AllLite14) {
-  std::string data;
+  string data;
 
   {
     // Test Clear with unknown fields
@@ -402,7 +404,7 @@
 // Tests for map lite =============================================
 
 TEST(Lite, AllLite15) {
-  std::string data;
+  string data;
 
   {
     // Accessors
@@ -417,7 +419,7 @@
 }
 
 TEST(Lite, AllLite16) {
-  std::string data;
+  string data;
 
   {
     // SetMapFieldsInitialized
@@ -429,7 +431,7 @@
 }
 
 TEST(Lite, AllLite17) {
-  std::string data;
+  string data;
 
   {
     // Clear
@@ -442,7 +444,7 @@
 }
 
 TEST(Lite, AllLite18) {
-  std::string data;
+  string data;
 
   {
     // ClearMessageMap
@@ -455,7 +457,7 @@
 }
 
 TEST(Lite, AllLite19) {
-  std::string data;
+  string data;
 
   {
     // CopyFrom
@@ -472,7 +474,7 @@
 }
 
 TEST(Lite, AllLite20) {
-  std::string data;
+  string data;
 
   {
     // CopyFromMessageMap
@@ -490,7 +492,7 @@
 }
 
 TEST(Lite, AllLite21) {
-  std::string data;
+  string data;
 
   {
     // SwapWithEmpty
@@ -507,7 +509,7 @@
 }
 
 TEST(Lite, AllLite22) {
-  std::string data;
+  string data;
 
   {
     // SwapWithSelf
@@ -522,7 +524,7 @@
 }
 
 TEST(Lite, AllLite23) {
-  std::string data;
+  string data;
 
   {
     // SwapWithOther
@@ -539,7 +541,7 @@
 }
 
 TEST(Lite, AllLite24) {
-  std::string data;
+  string data;
 
   {
     // CopyConstructor
@@ -552,7 +554,7 @@
 }
 
 TEST(Lite, AllLite25) {
-  std::string data;
+  string data;
 
   {
     // CopyAssignmentOperator
@@ -570,7 +572,7 @@
 }
 
 TEST(Lite, AllLite26) {
-  std::string data;
+  string data;
 
   {
     // NonEmptyMergeFrom
@@ -592,7 +594,7 @@
 }
 
 TEST(Lite, AllLite27) {
-  std::string data;
+  string data;
 
   {
     // MergeFromMessageMap
@@ -610,12 +612,12 @@
 }
 
 TEST(Lite, AllLite28) {
-  std::string data;
+  string data;
 
   {
     // Test the generated SerializeWithCachedSizesToArray()
     protobuf_unittest::TestMapLite message1, message2;
-    std::string data;
+    string data;
     google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
     int size = message1.ByteSize();
     data.resize(size);
@@ -628,14 +630,14 @@
 }
 
 TEST(Lite, AllLite29) {
-  std::string data;
+  string data;
 
   {
     // Test the generated SerializeWithCachedSizes()
     protobuf_unittest::TestMapLite message1, message2;
     google::protobuf::MapLiteTestUtil::SetMapFields(&message1);
     int size = message1.ByteSize();
-    std::string data;
+    string data;
     data.resize(size);
     {
       // Allow the output stream to buffer only one byte at a time.
@@ -653,7 +655,7 @@
 
 
 TEST(Lite, AllLite32) {
-  std::string data;
+  string data;
 
   {
     // Proto2UnknownEnum
@@ -662,7 +664,7 @@
         protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE;
     (*from.mutable_unknown_map_field())[0] =
         protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE;
-    std::string data;
+    string data;
     from.SerializeToString(&data);
 
     protobuf_unittest::TestEnumMapLite to;
@@ -687,12 +689,12 @@
 }
 
 TEST(Lite, AllLite33) {
-  std::string data;
+  string data;
 
   {
     // StandardWireFormat
     protobuf_unittest::TestMapLite message;
-    std::string data = "\x0A\x04\x08\x01\x10\x01";
+    string data = "\x0A\x04\x08\x01\x10\x01";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -701,14 +703,14 @@
 }
 
 TEST(Lite, AllLite34) {
-  std::string data;
+  string data;
 
   {
     // UnorderedWireFormat
     protobuf_unittest::TestMapLite message;
 
     // put value before key in wire format
-    std::string data = "\x0A\x04\x10\x01\x08\x02";
+    string data = "\x0A\x04\x10\x01\x08\x02";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -717,14 +719,14 @@
 }
 
 TEST(Lite, AllLite35) {
-  std::string data;
+  string data;
 
   {
     // DuplicatedKeyWireFormat
     protobuf_unittest::TestMapLite message;
 
     // Two key fields in wire format
-    std::string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
+    string data = "\x0A\x06\x08\x01\x08\x02\x10\x01";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -733,14 +735,14 @@
 }
 
 TEST(Lite, AllLite36) {
-  std::string data;
+  string data;
 
   {
     // DuplicatedValueWireFormat
     protobuf_unittest::TestMapLite message;
 
     // Two value fields in wire format
-    std::string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
+    string data = "\x0A\x06\x08\x01\x10\x01\x10\x02";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -749,14 +751,14 @@
 }
 
 TEST(Lite, AllLite37) {
-  std::string data;
+  string data;
 
   {
     // MissedKeyWireFormat
     protobuf_unittest::TestMapLite message;
 
     // No key field in wire format
-    std::string data = "\x0A\x02\x10\x01";
+    string data = "\x0A\x02\x10\x01";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -765,14 +767,14 @@
 }
 
 TEST(Lite, AllLite38) {
-  std::string data;
+  string data;
 
   {
     // MissedValueWireFormat
     protobuf_unittest::TestMapLite message;
 
     // No value field in wire format
-    std::string data = "\x0A\x02\x08\x01";
+    string data = "\x0A\x02\x08\x01";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -781,14 +783,14 @@
 }
 
 TEST(Lite, AllLite39) {
-  std::string data;
+  string data;
 
   {
     // UnknownFieldWireFormat
     protobuf_unittest::TestMapLite message;
 
     // Unknown field in wire format
-    std::string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
+    string data = "\x0A\x06\x08\x02\x10\x03\x18\x01";
 
     EXPECT_TRUE(message.ParseFromString(data));
     EXPECT_EQ(1, message.map_int32_int32().size());
@@ -797,21 +799,21 @@
 }
 
 TEST(Lite, AllLite40) {
-  std::string data;
+  string data;
 
   {
     // CorruptedWireFormat
     protobuf_unittest::TestMapLite message;
 
     // corrupted data in wire format
-    std::string data = "\x0A\x06\x08\x02\x11\x03";
+    string data = "\x0A\x06\x08\x02\x11\x03";
 
     EXPECT_FALSE(message.ParseFromString(data));
   }
 }
 
 TEST(Lite, AllLite41) {
-  std::string data;
+  string data;
 
   {
     // IsInitialized
@@ -830,7 +832,7 @@
 }
 
 TEST(Lite, AllLite42) {
-  std::string data;
+  string data;
 
   {
       // Check that adding more values to enum does not corrupt message
@@ -839,7 +841,7 @@
       v2_message.set_int_field(800);
       // Set enum field to the value not understood by the old client.
       v2_message.set_enum_field(protobuf_unittest::V2_SECOND);
-      std::string v2_bytes = v2_message.SerializeAsString();
+      string v2_bytes = v2_message.SerializeAsString();
 
       protobuf_unittest::V1MessageLite v1_message;
       v1_message.ParseFromString(v2_bytes);
@@ -850,7 +852,7 @@
       EXPECT_EQ(v1_message.enum_field(), protobuf_unittest::V1_FIRST);
 
       // However, when re-serialized, it should preserve enum value.
-      std::string v1_bytes = v1_message.SerializeAsString();
+      string v1_bytes = v1_message.SerializeAsString();
 
       protobuf_unittest::V2MessageLite same_v2_message;
       same_v2_message.ParseFromString(v1_bytes);
@@ -858,6 +860,131 @@
       EXPECT_EQ(v2_message.int_field(), same_v2_message.int_field());
       EXPECT_EQ(v2_message.enum_field(), same_v2_message.enum_field());
   }
+}
+
+// Test that when parsing a oneof, we can successfully clear whatever already
+// happened to be stored in the oneof.
+TEST(Lite, AllLite43) {
+  protobuf_unittest::TestOneofParsingLite message1;
+
+  message1.set_oneof_int32(17);
+  string serialized;
+  EXPECT_TRUE(message1.SerializeToString(&serialized));
+
+  // Submessage
+  {
+    protobuf_unittest::TestOneofParsingLite message2;
+    message2.mutable_oneof_submessage();
+    google::protobuf::io::CodedInputStream input_stream(
+        reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()), serialized.size());
+    EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream));
+    EXPECT_EQ(17, message2.oneof_int32());
+  }
+
+  // String
+  {
+    protobuf_unittest::TestOneofParsingLite message2;
+    message2.set_oneof_string("string");
+    google::protobuf::io::CodedInputStream input_stream(
+        reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()), serialized.size());
+    EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream));
+    EXPECT_EQ(17, message2.oneof_int32());
+  }
+
+  // Bytes
+  {
+    protobuf_unittest::TestOneofParsingLite message2;
+    message2.set_oneof_bytes("bytes");
+    google::protobuf::io::CodedInputStream input_stream(
+        reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()), serialized.size());
+    EXPECT_TRUE(message2.MergeFromCodedStream(&input_stream));
+    EXPECT_EQ(17, message2.oneof_int32());
+  }
+}
+
+// Verify that we can successfully parse fields of various types within oneof
+// fields. We also verify that we can parse the same data twice into the same
+// message.
+TEST(Lite, AllLite44) {
+  // Int32
+  {
+    protobuf_unittest::TestOneofParsingLite original;
+    original.set_oneof_int32(17);
+    string serialized;
+    EXPECT_TRUE(original.SerializeToString(&serialized));
+    protobuf_unittest::TestOneofParsingLite parsed;
+    for (int i = 0; i < 2; ++i) {
+      google::protobuf::io::CodedInputStream input_stream(
+          reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()),
+          serialized.size());
+      EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream));
+      EXPECT_EQ(17, parsed.oneof_int32());
+    }
+  }
+
+  // Submessage
+  {
+    protobuf_unittest::TestOneofParsingLite original;
+    original.mutable_oneof_submessage()->set_optional_int32(5);
+    string serialized;
+    EXPECT_TRUE(original.SerializeToString(&serialized));
+    protobuf_unittest::TestOneofParsingLite parsed;
+    for (int i = 0; i < 2; ++i) {
+      google::protobuf::io::CodedInputStream input_stream(
+          reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()),
+          serialized.size());
+      EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream));
+      EXPECT_EQ(5, parsed.oneof_submessage().optional_int32());
+    }
+  }
+
+  // String
+  {
+    protobuf_unittest::TestOneofParsingLite original;
+    original.set_oneof_string("string");
+    string serialized;
+    EXPECT_TRUE(original.SerializeToString(&serialized));
+    protobuf_unittest::TestOneofParsingLite parsed;
+    for (int i = 0; i < 2; ++i) {
+      google::protobuf::io::CodedInputStream input_stream(
+          reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()),
+          serialized.size());
+      EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream));
+      EXPECT_EQ("string", parsed.oneof_string());
+    }
+  }
+
+  // Bytes
+  {
+    protobuf_unittest::TestOneofParsingLite original;
+    original.set_oneof_bytes("bytes");
+    string serialized;
+    EXPECT_TRUE(original.SerializeToString(&serialized));
+    protobuf_unittest::TestOneofParsingLite parsed;
+    for (int i = 0; i < 2; ++i) {
+      google::protobuf::io::CodedInputStream input_stream(
+          reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()),
+          serialized.size());
+      EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream));
+      EXPECT_EQ("bytes", parsed.oneof_bytes());
+    }
+  }
+
+  // Enum
+  {
+    protobuf_unittest::TestOneofParsingLite original;
+    original.set_oneof_enum(protobuf_unittest::V2_SECOND);
+    string serialized;
+    EXPECT_TRUE(original.SerializeToString(&serialized));
+    protobuf_unittest::TestOneofParsingLite parsed;
+    for (int i = 0; i < 2; ++i) {
+      google::protobuf::io::CodedInputStream input_stream(
+          reinterpret_cast<const ::google::protobuf::uint8*>(serialized.data()),
+          serialized.size());
+      EXPECT_TRUE(parsed.MergeFromCodedStream(&input_stream));
+      EXPECT_EQ(protobuf_unittest::V2_SECOND, parsed.oneof_enum());
+    }
+  }
 
   std::cout << "PASS" << std::endl;
 }
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index e5a32c5..883556a 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -158,7 +158,7 @@
 
  private:
   void Init() {
-    elements_ = Arena::Create<InnerMap>(arena_, 0, hasher(), Allocator(arena_));
+    elements_ = Arena::Create<InnerMap>(arena_, 0u, hasher(), Allocator(arena_));
   }
 
   // re-implement std::allocator to use arena allocator for memory allocation.
@@ -181,7 +181,7 @@
     MapAllocator(const MapAllocator<X>& allocator)
         : arena_(allocator.arena()) {}
 
-    pointer allocate(size_type n, const void* hint = 0) {
+    pointer allocate(size_type n, const void* /* hint */ = 0) {
       // If arena is not given, malloc needs to be called which doesn't
       // construct element object.
       if (arena_ == NULL) {
@@ -197,6 +197,7 @@
 #if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation)
         ::operator delete(p, n * sizeof(value_type));
 #else
+        (void)n;
         ::operator delete(p);
 #endif
       }
@@ -862,14 +863,7 @@
     size_type BucketNumber(const Key& k) const {
       // We inherit from hasher, so one-arg operator() provides a hash function.
       size_type h = (*const_cast<InnerMap*>(this))(k);
-      // To help prevent people from making assumptions about the hash function,
-      // we use the seed differently depending on NDEBUG.  The default hash
-      // function, the seeding, etc., are all likely to change in the future.
-#ifndef NDEBUG
-      return (h * (seed_ | 1)) & (num_buckets_ - 1);
-#else
       return (h + seed_) & (num_buckets_ - 1);
-#endif
     }
 
     bool IsMatch(const Key& k0, const Key& k1) const {
@@ -939,12 +933,16 @@
 
  public:
   // Iterators
-  class const_iterator
-      : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
-                             const value_type*, const value_type&> {
+  class const_iterator {
     typedef typename InnerMap::const_iterator InnerIt;
 
    public:
+    typedef std::forward_iterator_tag iterator_category;
+    typedef typename Map::value_type value_type;
+    typedef ptrdiff_t difference_type;
+    typedef const value_type* pointer;
+    typedef const value_type& reference;
+
     const_iterator() {}
     explicit const_iterator(const InnerIt& it) : it_(it) {}
 
@@ -970,10 +968,16 @@
     InnerIt it_;
   };
 
-  class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+  class iterator {
     typedef typename InnerMap::iterator InnerIt;
 
    public:
+    typedef std::forward_iterator_tag iterator_category;
+    typedef typename Map::value_type value_type;
+    typedef ptrdiff_t difference_type;
+    typedef value_type* pointer;
+    typedef value_type& reference;
+
     iterator() {}
     explicit iterator(const InnerIt& it) : it_(it) {}
 
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 7c67556..afe809b 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -98,11 +98,12 @@
         offsets_,
         has_bits_,
         GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_),
-        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry,
-                                                       _internal_metadata_),
+        GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _internal_metadata_),
         -1,
         -1,
-        sizeof(MapEntry)};
+        sizeof(MapEntry),
+        -1,
+    };
     const Reflection* reflection = new GeneratedMessageReflection(
         descriptor, schema, DescriptorPool::generated_pool(),
         MessageFactory::generated_factory());
@@ -147,6 +148,30 @@
 uint32 MapEntry<Derived, Key, Value, kKeyFieldType, kValueFieldType,
                 default_enum_value>::has_bits_[2] = {0, 1};
 
+// Specialization for the full runtime
+template <typename Derived, typename Key, typename Value,
+          WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+struct MapEntryHelper<MapEntry<Derived, Key, Value, kKeyFieldType,
+                               kValueFieldType, default_enum_value> >
+    : MapEntryHelper<MapEntryLite<Key, Value, kKeyFieldType, kValueFieldType,
+                                  default_enum_value> > {
+  explicit MapEntryHelper(const MapPair<Key, Value>& map_pair)
+      : MapEntryHelper<MapEntryLite<Key, Value, kKeyFieldType, kValueFieldType,
+                                    default_enum_value> >(map_pair) {}
+};
+
+template <typename Derived, typename K, typename V,
+          WireFormatLite::FieldType key, WireFormatLite::FieldType value,
+          int default_enum>
+struct DeconstructMapEntry<MapEntry<Derived, K, V, key, value, default_enum> > {
+  typedef K Key;
+  typedef V Value;
+  static const WireFormatLite::FieldType kKeyFieldType = key;
+  static const WireFormatLite::FieldType kValueFieldType = value;
+  static const int default_enum_value = default_enum;
+};
+
 }  // namespace internal
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index c466cc7..0bccf4d 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -34,6 +34,7 @@
 #include <assert.h>
 
 #include <google/protobuf/arena.h>
+#include <google/protobuf/map.h>
 #include <google/protobuf/map_type_handler.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 
@@ -226,8 +227,10 @@
 
   size_t ByteSizeLong() const {
     size_t size = 0;
-    size += has_key() ? kTagSize + KeyTypeHandler::ByteSize(key()) : 0;
-    size += has_value() ? kTagSize + ValueTypeHandler::ByteSize(value()) : 0;
+    size += has_key() ?
+        kTagSize + static_cast<size_t>(KeyTypeHandler::ByteSize(key())) : 0;
+    size += has_value() ?
+        kTagSize + static_cast<size_t>(ValueTypeHandler::ByteSize(value())) : 0;
     return size;
   }
 
@@ -250,11 +253,10 @@
   int GetCachedSize() const {
     int size = 0;
     size += has_key()
-        ? kTagSize + KeyTypeHandler::GetCachedSize(key())
+        ? static_cast<int>(kTagSize) + KeyTypeHandler::GetCachedSize(key())
         : 0;
     size += has_value()
-        ? kTagSize + ValueTypeHandler::GetCachedSize(
-            value())
+        ? static_cast<int>(kTagSize) + ValueTypeHandler::GetCachedSize(value())
         : 0;
     return size;
   }
@@ -552,6 +554,23 @@
                                     default_enum_value>& other) {
     MergeFromInternal(other);
   }
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
+};
+// The completely unprincipled and unwieldy use of template parameters in
+// the map code necessitates wrappers to make the code a little bit more
+// manageable.
+template <typename Derived>
+struct DeconstructMapEntry;
+
+template <typename K, typename V, WireFormatLite::FieldType key,
+          WireFormatLite::FieldType value, int default_enum>
+struct DeconstructMapEntry<MapEntryLite<K, V, key, value, default_enum> > {
+  typedef K Key;
+  typedef V Value;
+  static const WireFormatLite::FieldType kKeyFieldType = key;
+  static const WireFormatLite::FieldType kValueFieldType = value;
+  static const int default_enum_value = default_enum;
 };
 
 // Helpers for deterministic serialization =============================
@@ -580,6 +599,75 @@
   }
 };
 
+// Helper for table driven serialization
+
+template <WireFormatLite::FieldType FieldType>
+struct FromHelper {
+  template <typename T>
+  static const T& From(const T& x) {
+    return x;
+  }
+};
+
+template <>
+struct FromHelper<WireFormatLite::TYPE_STRING> {
+  static ArenaStringPtr From(const string& x) {
+    ArenaStringPtr res;
+    res.UnsafeArenaSetAllocated(NULL, const_cast<string*>(&x), NULL);
+    return res;
+  }
+};
+template <>
+struct FromHelper<WireFormatLite::TYPE_BYTES> {
+  static ArenaStringPtr From(const string& x) {
+    ArenaStringPtr res;
+    res.UnsafeArenaSetAllocated(NULL, const_cast<string*>(&x), NULL);
+    return res;
+  }
+};
+template <>
+struct FromHelper<WireFormatLite::TYPE_MESSAGE> {
+  template <typename T>
+  static T* From(const T& x) {
+    return const_cast<T*>(&x);
+  }
+};
+
+template <typename MapEntryType>
+struct MapEntryHelper;
+
+template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType,
+          WireFormatLite::FieldType kValueFieldType, int default_enum_value>
+struct MapEntryHelper<MapEntryLite<Key, Value, kKeyFieldType, kValueFieldType,
+                                   default_enum_value> > {
+  // Provide utilities to parse/serialize key/value.  Provide utilities to
+  // manipulate internal stored type.
+  typedef MapTypeHandler<kKeyFieldType, Key> KeyTypeHandler;
+  typedef MapTypeHandler<kValueFieldType, Value> ValueTypeHandler;
+
+  // Define internal memory layout. Strings and messages are stored as
+  // pointers, while other types are stored as values.
+  typedef typename KeyTypeHandler::TypeOnMemory KeyOnMemory;
+  typedef typename ValueTypeHandler::TypeOnMemory ValueOnMemory;
+
+  explicit MapEntryHelper(const MapPair<Key, Value>& map_pair)
+      : _has_bits_(3),
+        _cached_size_(2 + KeyTypeHandler::GetCachedSize(map_pair.first) +
+                      ValueTypeHandler::GetCachedSize(map_pair.second)),
+        key_(FromHelper<kKeyFieldType>::From(map_pair.first)),
+        value_(FromHelper<kValueFieldType>::From(map_pair.second)) {}
+
+  // Purposely not folowing the style guide naming. These are the names
+  // the proto compiler would generate given the map entry descriptor.
+  // The proto compiler generates the offsets in this struct as if this was
+  // a regular message. This way the table driven code barely notices it's
+  // dealing with a map field.
+  uint32 _has_bits_;     // NOLINT
+  uint32 _cached_size_;  // NOLINT
+  KeyOnMemory key_;      // NOLINT
+  ValueOnMemory value_;  // NOLINT
+};
+
 }  // namespace internal
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 9d5a328..bd47890 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -170,6 +170,7 @@
   // IncreaseIterator() is called by operator++() of MapIterator only.
   // It implements the ++ operator of MapIterator.
   virtual void IncreaseIterator(MapIterator* map_iter) const = 0;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldBase);
 };
 
 // This class provides common Map Reflection implementations for generated
@@ -199,6 +200,7 @@
   void IncreaseIterator(MapIterator* map_iter) const;
 
   virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase);
 };
 
 // This class provides access to map field using generated api. It is used for
@@ -231,6 +233,9 @@
   typedef typename MapIf<kIsValueEnum, T, const T&>::type CastValueType;
 
  public:
+  typedef typename Derived::SuperType EntryTypeTrait;
+  typedef Map<Key, T> MapType;
+
   MapField() {}
   explicit MapField(Arena* arena)
       : TypeDefinedMapFieldBase<Key, T>(arena), impl_(arena) {}
@@ -287,6 +292,15 @@
 
   friend class ::google::protobuf::Arena;
   friend class MapFieldStateTest;  // For testing, it needs raw access to impl_
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField);
+};
+
+template <typename MEntry>
+struct MapEntryToMapField {
+  typedef DeconstructMapEntry<typename MEntry::SuperType> T;
+  typedef MapField<MEntry, typename T::Key, typename T::Value, T::kKeyFieldType,
+                   T::kValueFieldType, T::default_enum_value>
+      MapFieldType;
 };
 
 class LIBPROTOBUF_EXPORT DynamicMapField: public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
@@ -314,6 +328,7 @@
   void SyncMapWithRepeatedFieldNoLock() const;
   size_t SpaceUsedExcludingSelfNoLock() const;
   void SetMapIteratorValue(MapIterator* map_iter) const;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField);
 };
 
 }  // namespace internal
@@ -338,6 +353,10 @@
   MapKey(const MapKey& other) : type_(0) {
     CopyFrom(other);
   }
+  MapKey& operator=(const MapKey& other) {
+    CopyFrom(other);
+    return *this;
+  }
 
   ~MapKey() {
     if (type_ == FieldDescriptor::CPPTYPE_STRING) {
@@ -697,6 +716,7 @@
   void* data_;
   // type_ is 0 or a valid FieldDescriptor::CppType.
   int type_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapValueRef);
 };
 
 #undef TYPE_CHECK
@@ -718,6 +738,11 @@
   ~MapIterator() {
     map_->DeleteIterator(this);
   }
+  MapIterator& operator=(const MapIterator& other) {
+    map_ = other.map_;
+    map_->CopyIterator(this, other);
+    return *this;
+  }
   friend bool operator==(const MapIterator& a, const MapIterator& b) {
     return a.map_->EqualIterator(a, b);
   }
diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
index 8c5da3c..e317b5e 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -168,7 +168,7 @@
 int MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
              default_enum_value>::size() const {
   MapFieldBase::SyncMapWithRepeatedField();
-  return impl_.GetMap().size();
+  return static_cast<int>(impl_.GetMap().size());
 }
 
 template <typename Derived, typename Key, typename T,
@@ -252,9 +252,9 @@
           WireFormatLite::FieldType kValueFieldType, int default_enum_value>
 void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
               default_enum_value>::Swap(MapField* other) {
-  std::swap(MapFieldBase::repeated_field_, other->repeated_field_);
+  std::swap(this->MapFieldBase::repeated_field_, other->repeated_field_);
   impl_.Swap(&other->impl_);
-  std::swap(MapFieldBase::state_, other->state_);
+  std::swap(this->MapFieldBase::state_, other->state_);
 }
 
 template <typename Derived, typename Key, typename T,
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
index 2d10239..12d4e6b 100644
--- a/src/google/protobuf/map_field_lite.h
+++ b/src/google/protobuf/map_field_lite.h
@@ -33,6 +33,7 @@
 
 #include <google/protobuf/map.h>
 #include <google/protobuf/map_entry_lite.h>
+#include <google/protobuf/wire_format_lite.h>
 
 namespace google {
 namespace protobuf {
@@ -49,6 +50,9 @@
   typedef Derived EntryType;
 
  public:
+  typedef Map<Key, T> MapType;
+  typedef EntryType EntryTypeTrait;
+
   MapFieldLite() : arena_(NULL) { SetDefaultEnumValue(); }
 
   explicit MapFieldLite(Arena* arena) : arena_(arena), map_(arena) {
@@ -60,7 +64,7 @@
   Map<Key, T>* MutableMap() { return &map_; }
 
   // Convenient methods for generated message implementation.
-  int size() const { return map_.size(); }
+  int size() const { return static_cast<int>(map_.size()); }
   void Clear() { return map_.clear(); }
   void MergeFrom(const MapFieldLite& other) {
     for (typename Map<Key, T>::const_iterator it = other.map_.begin();
@@ -104,7 +108,6 @@
   friend class ::google::protobuf::Arena;
 };
 
-
 // True if IsInitialized() is true for value field in all elements of t. T is
 // expected to be message.  It's useful to have this helper here to keep the
 // protobuf compiler from ever having to emit loops in IsInitialized() methods.
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index a06b432..960589c 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -236,6 +236,13 @@
 
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
+TEST_F(MapImplTest, MapKeyAssignment) {
+  MapKey from, to;
+  from.SetStringValue("abc");
+  to = from;
+  EXPECT_EQ("abc", to.GetStringValue());
+}
+
 TEST_F(MapImplTest, CountNonExist) {
   EXPECT_EQ(0, map_.count(0));
 }
@@ -954,6 +961,17 @@
       testing::Pair(9398, 41999)));
 }
 
+TEST_F(MapImplTest, CopyAssignMapIterator) {
+  TestMap message;
+  MapReflectionTester reflection_tester(
+      unittest::TestMap::descriptor());
+  reflection_tester.SetMapFieldsViaMapReflection(&message);
+  MapIterator it1 = reflection_tester.MapBegin(&message, "map_int32_int32");
+  MapIterator it2 = reflection_tester.MapEnd(&message, "map_int32_int32");
+  it2 = it1;
+  EXPECT_EQ(it1.GetKey().GetInt32Value(), it2.GetKey().GetInt32Value());
+}
+
 // Map Field Reflection Test ========================================
 
 static int Func(int i, int j) {
diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
index 4d3ad60..31ac173 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -760,6 +760,18 @@
   return reflection->MutableRepeatedMessage(message, F(field_name), index);
 }
 
+MapIterator MapReflectionTester::MapBegin(Message* message,
+                                          const string& field_name) {
+  const Reflection* reflection = message->GetReflection();
+  return reflection->MapBegin(message, F(field_name));
+}
+
+MapIterator MapReflectionTester::MapEnd(Message* message,
+                                        const string& field_name) {
+  const Reflection* reflection = message->GetReflection();
+  return reflection->MapEnd(message, F(field_name));
+}
+
 void MapReflectionTester::ClearMapFieldsViaReflection(
     Message* message) {
   const Reflection* reflection = message->GetReflection();
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index 15c6c28..dd39761 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -111,6 +111,8 @@
                                    const MapKey& map_key, MapValueRef* map_val);
   Message* GetMapEntryViaReflection(Message* message, const string& field_name,
                                     int index);
+  MapIterator MapBegin(Message* message, const string& field_name);
+  MapIterator MapEnd(Message* message, const string& field_name);
 
  private:
   const FieldDescriptor* F(const string& name);
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index 301b37f..7f7b1e0 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -32,7 +32,6 @@
 #define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
 
 #include <google/protobuf/arena.h>
-#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/wire_format_lite_inl.h>
 
 namespace google {
@@ -73,7 +72,7 @@
 template <typename Type>
 class MapValueInitializer<false, Type> {
  public:
-  static inline void Initialize(Type& value, int default_enum_value) {}
+  static inline void Initialize(Type& /* value */, int /* default_enum_value */) {}
 };
 
 template <typename Type, bool is_arena_constructable>
@@ -284,7 +283,7 @@
   template <typename Type>                                                     \
   inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
       const MapEntryAccessorType& value) {                                     \
-    return WireFormatLite::DeclaredType##Size(value);                          \
+    return static_cast<int>(WireFormatLite::DeclaredType##Size(value));        \
   }
 
 GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
@@ -302,7 +301,7 @@
 #define FIXED_BYTE_SIZE(FieldType, DeclaredType)                               \
   template <typename Type>                                                     \
   inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
-      const MapEntryAccessorType& value) {                                     \
+      const MapEntryAccessorType& /* value */) {                               \
     return WireFormatLite::k##DeclaredType##Size;                              \
   }
 
@@ -320,7 +319,9 @@
 inline int
 MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
     const MapEntryAccessorType& value) {
-  return WireFormatLite::LengthDelimitedSize(value.GetCachedSize());
+  return static_cast<int>(
+      WireFormatLite::LengthDelimitedSize(
+          static_cast<size_t>(value.GetCachedSize())));
 }
 
 #define GET_CACHED_SIZE(FieldType, DeclaredType)                         \
@@ -328,7 +329,7 @@
   inline int                                                             \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
       const MapEntryAccessorType& value) {                               \
-    return WireFormatLite::DeclaredType##Size(value);                    \
+    return static_cast<int>(WireFormatLite::DeclaredType##Size(value));  \
   }
 
 GET_CACHED_SIZE(STRING, String)
@@ -347,7 +348,7 @@
   template <typename Type>                                               \
   inline int                                                             \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
-      const MapEntryAccessorType& value) {                               \
+      const MapEntryAccessorType& /* value */) {                         \
     return WireFormatLite::k##DeclaredType##Size;                        \
   }
 
@@ -478,20 +479,20 @@
 
 template <typename Type>
 inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
-    Type** value, Arena* arena) {
+    Type** value, Arena* /* arena */) {
   if (*value != NULL) (*value)->Clear();
 }
 template <typename Type>
 inline void
 MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                         Type>::ClearMaybeByDefaultEnum(Type** value,
-                                                       Arena* arena,
-                                                       int default_enum_value) {
+                                                       Arena* /* arena */,
+                                                       int /* default_enum_value */) {
   if (*value != NULL) (*value)->Clear();
 }
 template <typename Type>
 inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
-    const Type& from, Type** to, Arena* arena) {
+    const Type& from, Type** to, Arena* /* arena */) {
   (*to)->MergeFrom(from);
 }
 
@@ -510,14 +511,14 @@
 template <typename Type>
 inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                                     Type>::Initialize(Type** x,
-                                                      Arena* arena) {
+                                                      Arena* /* arena */) {
   *x = NULL;
 }
 
 template <typename Type>
 inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
-    InitializeMaybeByDefaultEnum(Type** x, int default_enum_value,
-                                 Arena* arena) {
+    InitializeMaybeByDefaultEnum(Type** x, int /* default_enum_value */,
+                                 Arena* /* arena */) {
   *x = NULL;
 }
 
@@ -582,7 +583,7 @@
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
       ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena,               \
-                              int default_enum) {                              \
+                              int /* default_enum */) {                        \
     Clear(value, arena);                                                       \
   }                                                                            \
   template <typename Type>                                                     \
@@ -597,18 +598,19 @@
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
-                             Type>::AssignDefaultValue(TypeOnMemory* value) {} \
+                             Type>::AssignDefaultValue(TypeOnMemory* /* value */) {} \
   template <typename Type>                                                     \
   inline void                                                                  \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize(          \
-      TypeOnMemory* value, Arena* arena) {                                     \
+      TypeOnMemory* value, Arena* /* arena */) {                               \
     value->UnsafeSetDefault(                                                   \
         &::google::protobuf::internal::GetEmptyStringAlreadyInited());                   \
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
       InitializeMaybeByDefaultEnum(TypeOnMemory* value,                        \
-                                   int default_enum_value, Arena* arena) {     \
+                                   int /* default_enum_value */,               \
+                                   Arena* arena) {                             \
     Initialize(value, arena);                                                  \
   }                                                                            \
   template <typename Type>                                                     \
@@ -625,12 +627,12 @@
   MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                  Type>::DefaultIfNotInitialized(const TypeOnMemory& value,     \
                                                 const TypeOnMemory&            \
-                                                    default_value) {           \
+                                                    /* default_value */) {     \
     return value.Get();                                                        \
   }                                                                            \
   template <typename Type>                                                     \
   inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
-                             Type>::IsInitialized(const TypeOnMemory& value) { \
+                             Type>::IsInitialized(const TypeOnMemory& /* value */) { \
     return true;                                                               \
   }
 STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
@@ -648,54 +650,56 @@
   template <typename Type>                                                     \
   inline size_t                                                                \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
-                 Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& value) {   \
+                 Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) {   \
     return 0;                                                                  \
   }                                                                            \
   template <typename Type>                                                     \
   inline size_t                                                                \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong(  \
-      const TypeOnMemory& value) {                                             \
+      const TypeOnMemory& /* value */) {                                       \
     return sizeof(Type);                                                       \
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear(   \
-      TypeOnMemory* value, Arena* arena) {                                     \
+      TypeOnMemory* value, Arena* /* arena */) {                               \
     *value = 0;                                                                \
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
-      ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena,               \
+      ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* /* arena */,         \
                               int default_enum_value) {                        \
     *value = static_cast<TypeOnMemory>(default_enum_value);                    \
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge(   \
-      const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) {      \
+      const MapEntryAccessorType& from, TypeOnMemory* to,                      \
+      Arena* /* arena */) {                                                    \
     *to = from;                                                                \
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
-                             Type>::DeleteNoArena(TypeOnMemory& x) {}          \
+                             Type>::DeleteNoArena(TypeOnMemory& /* x */) {}    \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
-                             Type>::AssignDefaultValue(TypeOnMemory* value) {} \
+                             Type>::AssignDefaultValue(TypeOnMemory* /* value */) {} \
   template <typename Type>                                                     \
   inline void                                                                  \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize(          \
-      TypeOnMemory* value, Arena* arena) {                                     \
+      TypeOnMemory* value, Arena* /* arena */) {                               \
     *value = 0;                                                                \
   }                                                                            \
   template <typename Type>                                                     \
   inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
       InitializeMaybeByDefaultEnum(TypeOnMemory* value,                        \
-                                   int default_enum_value, Arena* arena) {     \
+                                   int default_enum_value,                     \
+                                   Arena* /* arena */) {                       \
     *value = static_cast<TypeOnMemory>(default_enum_value);                    \
   }                                                                            \
   template <typename Type>                                                     \
   inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,             \
                                  Type>::MapEntryAccessorType*                  \
   MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable(       \
-      TypeOnMemory* value, Arena* arena) {                                     \
+      TypeOnMemory* value, Arena* /* arena */) {                               \
     return value;                                                              \
   }                                                                            \
   template <typename Type>                                                     \
@@ -704,12 +708,12 @@
   MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                  Type>::DefaultIfNotInitialized(const TypeOnMemory& value,     \
                                                 const TypeOnMemory&            \
-                                                    default_value) {           \
+                                                   /* default_value */) {      \
     return value;                                                              \
   }                                                                            \
   template <typename Type>                                                     \
   inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
-                             Type>::IsInitialized(const TypeOnMemory& value) { \
+                             Type>::IsInitialized(const TypeOnMemory& /* value */) { \
     return true;                                                               \
   }
 PRIMITIVE_HANDLER_FUNCTIONS(INT64)
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index c6154f0..836dc10 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -60,6 +60,7 @@
   map<int32   , MapEnum > map_int32_enum        = 16;
   map<int32   , ForeignMessage> map_int32_foreign_message = 17;
   map<string  , ForeignMessage> map_string_foreign_message = 18;
+  map<int32   , TestAllTypes> map_int32_all_types = 19;
 }
 
 message TestMapSubmessage {
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 2134f95..c01d197 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -143,7 +143,13 @@
 
 void Message::SerializeWithCachedSizes(
     io::CodedOutputStream* output) const {
-  WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
+  const internal::SerializationTable* table =
+      static_cast<const internal::SerializationTable*>(InternalGetTable());
+  if (table == 0) {
+    WireFormat::SerializeWithCachedSizes(*this, GetCachedSize(), output);
+  } else {
+    internal::TableSerialize(*this, table, output);
+  }
 }
 
 size_t Message::ByteSizeLong() const {
@@ -191,6 +197,10 @@
 
 Reflection::~Reflection() {}
 
+void Reflection::AddAllocatedMessage(Message* /* message */,
+                                     const FieldDescriptor* /*field */,
+                                     Message* /* new_entry */) const {}
+
 #define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE)                             \
 template<>                                                            \
 const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>(        \
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index c155cbd..44fe0fd 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -254,6 +254,7 @@
   // fields defined for the proto.
   virtual size_t SpaceUsedLong() const;
 
+  PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceUsedLong() instead")
   int SpaceUsed() const { return internal::ToIntSize(SpaceUsedLong()); }
 
   // Debugging & Testing----------------------------------------------
@@ -428,6 +429,7 @@
   // Estimate the amount of memory used by the message object.
   virtual size_t SpaceUsedLong(const Message& message) const = 0;
 
+  PROTOBUF_RUNTIME_DEPRECATED("Please use SpaceUsedLong() instead")
   int SpaceUsed(const Message& message) const {
     return internal::ToIntSize(SpaceUsedLong(message));
   }
@@ -752,9 +754,9 @@
   // specifyed by 'field' passing ownership to the message.
   // TODO(tmarek): Make virtual after all subclasses have been
   // updated.
-  virtual void AddAllocatedMessage(Message* /* message */,
-                                   const FieldDescriptor* /* field */,
-                                   Message* /* new_entry */) const {}
+  virtual void AddAllocatedMessage(Message* message,
+                                   const FieldDescriptor* field,
+                                   Message* new_entry) const;
 
 
   // Get a RepeatedFieldRef object that can be used to read the underlying
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index fda84b5..83a92d5 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -227,19 +227,6 @@
       io::CodedOutputStream::IsDefaultSerializationDeterministic(), target);
 }
 
-uint8* MessageLite::InternalSerializeWithCachedSizesToArray(
-    bool deterministic, uint8* target) const {
-  // We only optimize this when using optimize_for = SPEED.  In other cases
-  // we just use the CodedOutputStream path.
-  int size = GetCachedSize();
-  io::ArrayOutputStream out(target, size);
-  io::CodedOutputStream coded_out(&out);
-  coded_out.SetSerializationDeterministic(deterministic);
-  SerializeWithCachedSizes(&coded_out);
-  GOOGLE_CHECK(!coded_out.HadError());
-  return target + size;
-}
-
 bool MessageLite::SerializeToCodedStream(io::CodedOutputStream* output) const {
   GOOGLE_DCHECK(IsInitialized()) << InitializationErrorMessage("serialize", *this);
   return SerializePartialToCodedStream(output);
@@ -357,6 +344,36 @@
   return output;
 }
 
+void MessageLite::SerializeWithCachedSizes(io::CodedOutputStream* output) const
+    {
+  GOOGLE_DCHECK(InternalGetTable());
+  internal::TableSerialize(*this, static_cast<const internal::SerializationTable*>(InternalGetTable()), output);
+}
+
+// The table driven code optimizes the case that the CodedOutputStream buffer
+// is large enough to serialize into it directly.
+// If the proto is optimized for speed, this method will be overridden by
+// generated code for maximum speed. If the proto is optimized for size or
+// is lite, then we need to specialize this to avoid infinite recursion.
+uint8* MessageLite::InternalSerializeWithCachedSizesToArray(bool deterministic,
+                                               uint8* target) const {
+  const internal::SerializationTable* table =
+      static_cast<const internal::SerializationTable*>(InternalGetTable());
+  if (table == NULL) {
+    // We only optimize this when using optimize_for = SPEED.  In other cases
+  // we just use the CodedOutputStream path.
+  int size = GetCachedSize();
+  io::ArrayOutputStream out(target, size);
+  io::CodedOutputStream coded_out(&out);
+  coded_out.SetSerializationDeterministic(deterministic);
+  SerializeWithCachedSizes(&coded_out);
+  GOOGLE_CHECK(!coded_out.HadError());
+  return target + size;
+  } else {
+    return internal::TableSerializeToArray(*this, table, deterministic, target);
+  }
+}
+
 namespace internal {
 template<>
 MessageLite* GenericTypeHandler<MessageLite>::NewFromPrototype(
@@ -373,6 +390,13 @@
                                               string* to) {
   *to = from;
 }
+
+bool proto3_preserve_unknown_ = false;
+void SetProto3PreserveUnknownsDefault(bool preserve) {
+  proto3_preserve_unknown_ = preserve;
+}
+
+
 }  // namespace internal
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 046a736..2075f4b 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -42,22 +42,130 @@
 #include <climits>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/stubs/once.h>
 
 
+#if LANG_CXX11 && !defined(__NVCC__)
+#define PROTOBUF_CXX11 1
+#else
+#define PROTOBUF_CXX11 0
+#endif
+
+#if PROTOBUF_CXX11
+#define PROTOBUF_FINAL final
+#else
+#define PROTOBUF_FINAL
+#endif
+
+#ifndef LIBPROTOBUF_EXPORT
+#define LIBPROTOBUF_EXPORT
+#endif
+
+#define PROTOBUF_RUNTIME_DEPRECATED(message)
+
 namespace google {
 namespace protobuf {
-  class Arena;
+class Arena;
 namespace io {
-  class CodedInputStream;
-  class CodedOutputStream;
-  class ZeroCopyInputStream;
-  class ZeroCopyOutputStream;
+class CodedInputStream;
+class CodedOutputStream;
+class ZeroCopyInputStream;
+class ZeroCopyOutputStream;
 }
 namespace internal {
-  class WireFormatLite;
+
+class WireFormatLite;
+
+#ifndef SWIG
+// We compute sizes as size_t but cache them as int.  This function converts a
+// computed size to a cached size.  Since we don't proceed with serialization
+// if the total size was > INT_MAX, it is not important what this function
+// returns for inputs > INT_MAX.  However this case should not error or
+// GOOGLE_CHECK-fail, because the full size_t resolution is still returned from
+// ByteSizeLong() and checked against INT_MAX; we can catch the overflow
+// there.
+inline int ToCachedSize(size_t size) { return static_cast<int>(size); }
+
+// We mainly calculate sizes in terms of size_t, but some functions that
+// compute sizes return "int".  These int sizes are expected to always be
+// positive. This function is more efficient than casting an int to size_t
+// directly on 64-bit platforms because it avoids making the compiler emit a
+// sign extending instruction, which we don't want and don't want to pay for.
+inline size_t FromIntSize(int size) {
+  // Convert to unsigned before widening so sign extension is not necessary.
+  return static_cast<unsigned int>(size);
 }
 
+// For cases where a legacy function returns an integer size.  We GOOGLE_DCHECK()
+// that the conversion will fit within an integer; if this is false then we
+// are losing information.
+inline int ToIntSize(size_t size) {
+  GOOGLE_DCHECK_LE(size, static_cast<size_t>(INT_MAX));
+  return static_cast<int>(size);
+}
+
+// This type wraps a variable whose constructor and destructor are explicitly
+// called. It is particularly useful for a global variable, without its
+// constructor and destructor run on start and end of the program lifetime.
+// This circumvents the initial construction order fiasco, while keeping
+// the address of the empty string a compile time constant.
+//
+// Pay special attention to the initialization state of the object.
+// 1. The object is "uninitialized" to begin with.
+// 2. Call DefaultConstruct() only if the object is uninitialized.
+//    After the call, the object becomes "initialized".
+// 3. Call get() and get_mutable() only if the object is initialized.
+// 4. Call Destruct() only if the object is initialized.
+//    After the call, the object becomes uninitialized.
+template <typename T>
+class ExplicitlyConstructed {
+ public:
+  void DefaultConstruct() {
+    new (&union_) T();
+  }
+
+  void Destruct() {
+    get_mutable()->~T();
+  }
+
+#if LANG_CXX11
+  constexpr
+#endif
+      const T&
+      get() const {
+    return reinterpret_cast<const T&>(union_);
+  }
+  T* get_mutable() { return reinterpret_cast<T*>(&union_); }
+
+ private:
+  // Prefer c++14 aligned_storage, but for compatibility this will do.
+  union AlignedUnion {
+    char space[sizeof(T)];
+    int64 align_to_int64;
+    void* align_to_ptr;
+  } union_;
+};
+
+// Default empty string object. Don't use this directly. Instead, call
+// GetEmptyString() to get the reference.
+extern ExplicitlyConstructed< ::std::string> fixed_address_empty_string;
+LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_;
+LIBPROTOBUF_EXPORT void InitEmptyString();
+
+
+LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() {
+  return fixed_address_empty_string.get();
+}
+
+LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() {
+  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
+  return GetEmptyStringAlreadyInited();
+}
+
+LIBPROTOBUF_EXPORT size_t StringSpaceUsedExcludingSelfLong(const string& str);
+#endif  // SWIG
+}  // namespace internal
+
 // Interface to light weight protocol messages.
 //
 // This interface is implemented by all protocol message objects.  Non-lite
@@ -102,18 +210,19 @@
   // Get the arena, if any, associated with this message. Virtual method
   // required for generic operations but most arena-related operations should
   // use the GetArenaNoVirtual() generated-code method. Default implementation
-  // to reduce code size by avoiding the need for per-type implementations when
-  // types do not implement arena support.
+  // to reduce code size by avoiding the need for per-type implementations
+  // when types do not implement arena support.
   virtual ::google::protobuf::Arena* GetArena() const { return NULL; }
 
-  // Get a pointer that may be equal to this message's arena, or may not be. If
-  // the value returned by this method is equal to some arena pointer, then this
-  // message is on that arena; however, if this message is on some arena, this
-  // method may or may not return that arena's pointer. As a tradeoff, this
-  // method may be more efficient than GetArena(). The intent is to allow
-  // underlying representations that use e.g. tagged pointers to sometimes store
-  // the arena pointer directly, and sometimes in a more indirect way, and allow
-  // a fastpath comparison against the arena pointer when it's easy to obtain.
+  // Get a pointer that may be equal to this message's arena, or may not be.
+  // If the value returned by this method is equal to some arena pointer, then
+  // this message is on that arena; however, if this message is on some arena,
+  // this method may or may not return that arena's pointer. As a tradeoff,
+  // this method may be more efficient than GetArena(). The intent is to allow
+  // underlying representations that use e.g. tagged pointers to sometimes
+  // store the arena pointer directly, and sometimes in a more indirect way,
+  // and allow a fastpath comparison against the arena pointer when it's easy
+  // to obtain.
   virtual void* GetMaybeArenaPointer() const { return GetArena(); }
 
   // Clear all fields of the message and set them to their default values.
@@ -131,19 +240,20 @@
   // for full messages.  See message.h.
   virtual string InitializationErrorString() const;
 
-  // If |other| is the exact same class as this, calls MergeFrom().  Otherwise,
+  // If |other| is the exact same class as this, calls MergeFrom(). Otherwise,
   // results are undefined (probably crash).
   virtual void CheckTypeAndMergeFrom(const MessageLite& other) = 0;
 
   // Parsing ---------------------------------------------------------
   // Methods for parsing in protocol buffer format.  Most of these are
-  // just simple wrappers around MergeFromCodedStream().  Clear() will be called
-  // before merging the input.
+  // just simple wrappers around MergeFromCodedStream().  Clear() will be
+  // called before merging the input.
 
-  // Fill the message with a protocol buffer parsed from the given input stream.
-  // Returns false on a read error or if the input is in the wrong format.  A
-  // successful return does not indicate the entire input is consumed, ensure
-  // you call ConsumedEntireMessage() to check that if applicable.
+  // Fill the message with a protocol buffer parsed from the given input
+  // stream. Returns false on a read error or if the input is in the wrong
+  // format.  A successful return does not indicate the entire input is
+  // consumed, ensure you call ConsumedEntireMessage() to check that if
+  // applicable.
   bool ParseFromCodedStream(io::CodedInputStream* input);
   // Like ParseFromCodedStream(), but accepts messages that are missing
   // required fields.
@@ -249,13 +359,16 @@
   virtual size_t ByteSizeLong() const = 0;
 
   // Legacy ByteSize() API.
-  int ByteSize() const { return internal::ToIntSize(ByteSizeLong()); }
+  PROTOBUF_RUNTIME_DEPRECATED("Please use ByteSizeLong() instead")
+  int ByteSize() const {
+    return internal::ToIntSize(ByteSizeLong());
+  }
 
   // Serializes the message without recomputing the size.  The message must not
   // have changed since the last call to ByteSize(), and the value returned by
   // ByteSize must be non-negative.  Otherwise the results are undefined.
   virtual void SerializeWithCachedSizes(
-      io::CodedOutputStream* output) const = 0;
+      io::CodedOutputStream* output) const;
 
   // Functions below here are not part of the public interface.  It isn't
   // enforced, but they should be treated as private, and will be private
@@ -286,11 +399,31 @@
                                                          uint8* target) const;
 
  private:
+  // TODO(gerbens) make this a pure abstract function
+  virtual const void* InternalGetTable() const { return NULL; }
+
   friend class internal::WireFormatLite;
+  friend class Message;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
 };
 
+namespace internal {
+
+extern bool LIBPROTOBUF_EXPORT proto3_preserve_unknown_;
+
+// DO NOT USE: For migration only. Will be removed when Proto3 defaults to
+// preserve unknowns.
+inline bool GetProto3PreserveUnknownsDefault() {
+  return proto3_preserve_unknown_;
+}
+
+// DO NOT USE: For migration only. Will be removed when Proto3 defaults to
+// preserve unknowns.
+void LIBPROTOBUF_EXPORT SetProto3PreserveUnknownsDefault(bool preserve);
+}  // namespace internal
+
+
 }  // namespace protobuf
 
 }  // namespace google
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index 0469f4c..06a7f65 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -37,9 +37,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#ifdef _MSC_VER
-#include <io.h>
-#else
+#ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <sstream>
@@ -51,11 +49,13 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/arena.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/generated_message_reflection.h>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
@@ -63,6 +63,13 @@
 namespace google {
 namespace protobuf {
 
+#if defined(_MSC_VER)
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::open;
+#endif
+
 #ifndef O_BINARY
 #ifdef _O_BINARY
 #define O_BINARY _O_BINARY
@@ -112,8 +119,9 @@
   string filename = TestSourceDir() +
                     "/google/protobuf/testdata/golden_message";
   int file = open(filename.c_str(), O_RDONLY | O_BINARY);
+  ASSERT_GE(file, 0);
 
-  unittest::TestAllTypes message;
+  protobuf_unittest::TestAllTypes message;
   EXPECT_TRUE(message.ParseFromFileDescriptor(file));
   TestUtil::ExpectAllFieldsSet(message);
 
@@ -125,8 +133,9 @@
       TestSourceDir() +
       "/google/protobuf/testdata/golden_packed_fields_message";
   int file = open(filename.c_str(), O_RDONLY | O_BINARY);
+  ASSERT_GE(file, 0);
 
-  unittest::TestPackedTypes message;
+  protobuf_unittest::TestPackedTypes message;
   EXPECT_TRUE(message.ParseFromFileDescriptor(file));
   TestUtil::ExpectPackedFieldsSet(message);
 
@@ -248,42 +257,6 @@
     "fields: a, b, c");
 }
 
-TEST(MessageTest, CheckOverflow) {
-  unittest::TestAllTypes message;
-  // Create a message with size just over 2GB. This triggers integer overflow
-  // when computing message size.
-  const string data(1024, 'x');
-  Cord one_megabyte;
-  for (int i = 0; i < 1024; i++) {
-    one_megabyte.Append(data);
-  }
-
-  for (int i = 0; i < 2 * 1024 + 1; ++i) {
-    message.add_repeated_cord()->CopyFrom(one_megabyte);
-  }
-
-  Cord serialized;
-  EXPECT_FALSE(message.AppendToCord(&serialized));
-}
-
-TEST(MessageTest, CheckBigOverflow) {
-  unittest::TestAllTypes message;
-  // Create a message with size just over 4GB. We should be able to detect this
-  // too, even though it will make a plain "int" wrap back to a positive number.
-  const string data(1024, 'x');
-  Cord one_megabyte;
-  for (int i = 0; i < 1024; i++) {
-    one_megabyte.Append(data);
-  }
-
-  for (int i = 0; i < 4 * 1024 + 1; ++i) {
-    message.add_repeated_cord()->CopyFrom(one_megabyte);
-  }
-
-  Cord serialized;
-  EXPECT_FALSE(message.AppendToCord(&serialized));
-}
-
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
 namespace {
@@ -422,6 +395,18 @@
   EXPECT_FALSE(message.ParseFromString(invalid_data));
   message.Clear();
   EXPECT_EQ(0, message.optional_uint64());
+
+  // invalid data for field "optional_string". Length prefix is 1 but no
+  // payload.
+  string invalid_string_data = "\x72\x01";
+  {
+    google::protobuf::Arena arena;
+    unittest::TestAllTypes* arena_message =
+        google::protobuf::Arena::CreateMessage<unittest::TestAllTypes>(&arena);
+    EXPECT_FALSE(arena_message->ParseFromString(invalid_string_data));
+    arena_message->Clear();
+    EXPECT_EQ("", arena_message->optional_string());
+  }
 }
 
 namespace {
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index 64fde0c..6022be9 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -150,8 +150,11 @@
   GOOGLE_ATTRIBUTE_NOINLINE T* mutable_unknown_fields_slow() {
     Arena* my_arena = arena();
     Container* container = Arena::Create<Container>(my_arena);
+    // Two-step assignment works around a bug in clang's static analyzer:
+    // https://bugs.llvm.org/show_bug.cgi?id=34198.
+    ptr_ = container;
     ptr_ = reinterpret_cast<void*>(
-        reinterpret_cast<intptr_t>(container) | kTagContainer);
+        reinterpret_cast<intptr_t>(ptr_) | kTagContainer);
     container->arena = my_arena;
     return &(container->unknown_fields);
   }
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index 2838e0f..3a0fb80 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -129,7 +129,8 @@
   ExpectAllFieldsSet(*arena_message);
 }
 
-TEST(Proto3ArenaTest, UnknownFields) {
+TEST(Proto3ArenaTest, UnknownFieldsDefaultDrop) {
+  ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(false);
   TestAllTypes original;
   SetAllFields(&original);
 
@@ -150,6 +151,28 @@
       arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
 }
 
+TEST(Proto3ArenaTest, UnknownFieldsDefaultPreserve) {
+  ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(true);
+  TestAllTypes original;
+  SetAllFields(&original);
+
+  Arena arena;
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+  arena_message->ParseFromString(original.SerializeAsString());
+  ExpectAllFieldsSet(*arena_message);
+
+  // In proto3 we can still get a pointer to the UnknownFieldSet through
+  // reflection API.
+  UnknownFieldSet* unknown_fields =
+      arena_message->GetReflection()->MutableUnknownFields(arena_message);
+  // We can modify this UnknownFieldSet.
+  unknown_fields->AddVarint(1, 2);
+  // And the unknown fields should be changed.
+  ASSERT_NE(original.ByteSize(), arena_message->ByteSize());
+  ASSERT_FALSE(
+      arena_message->GetReflection()->GetUnknownFields(*arena_message).empty());
+}
+
 TEST(Proto3ArenaTest, Swap) {
   Arena arena1;
   Arena arena2;
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index a1013f6..d8003b8 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -59,7 +59,6 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/type_traits.h>
 #include <google/protobuf/arena.h>
-#include <google/protobuf/generated_message_util.h>
 #include <google/protobuf/message_lite.h>
 
 
@@ -281,9 +280,6 @@
   friend class Arena;
   typedef void InternalArenaConstructable_;
 
-  // Move the contents of |from| into |to|, possibly clobbering |from| in the
-  // process.  For primitive types this is just a memcpy(), but it could be
-  // specialized for non-primitive types to, say, swap each element instead.
   void MoveArray(Element* to, Element* from, int size);
 
   // Copy the elements of |from| into |to|.
@@ -597,6 +593,7 @@
   // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0.
   void** InternalExtend(int extend_amount);
 
+  friend class AccessorHelper;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase);
 };
 
@@ -609,8 +606,7 @@
 #endif
 
   static inline GenericType* New(Arena* arena) {
-    return ::google::protobuf::Arena::CreateMaybeMessage<Type>(
-        arena, static_cast<GenericType*>(0));
+    return ::google::protobuf::Arena::CreateMaybeMessage<Type>(arena);
   }
   static inline GenericType* NewFromPrototype(
       const GenericType* prototype, ::google::protobuf::Arena* arena = NULL);
@@ -1335,7 +1331,7 @@
       static_cast<size_t>(new_size),
       (std::numeric_limits<size_t>::max() - kRepHeaderSize) / sizeof(Element))
       << "Requested size is too large to fit into size_t.";
-  size_t bytes = kRepHeaderSize + sizeof(Element) * new_size;
+  size_t bytes = kRepHeaderSize + sizeof(Element) * static_cast<size_t>(new_size);
   if (arena == NULL) {
     rep_ = static_cast<Rep*>(::operator new(bytes));
   } else {
@@ -1399,7 +1395,7 @@
 template <typename Element>
 struct ElementCopier<Element, true> {
   void operator()(Element* to, const Element* from, int array_size) {
-    memcpy(to, from, array_size * sizeof(Element));
+    memcpy(to, from, static_cast<size_t>(array_size) * sizeof(Element));
   }
 };
 
@@ -1651,7 +1647,7 @@
 
 template <typename TypeHandler>
 inline size_t RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() const {
-  size_t allocated_bytes = total_size_ * sizeof(void*);
+  size_t allocated_bytes = static_cast<size_t>(total_size_) * sizeof(void*);
   if (rep_ != NULL) {
     for (int i = 0; i < rep_->allocated_size; ++i) {
       allocated_bytes += TypeHandler::SpaceUsedLong(
@@ -2449,6 +2445,12 @@
     *field_->Add() = *ptr_to_value;
     return *this;
   }
+#if LANG_CXX11
+  RepeatedPtrFieldBackInsertIterator<T>& operator=(T&& value) {
+    *field_->Add() = std::move(value);
+    return *this;
+  }
+#endif
   RepeatedPtrFieldBackInsertIterator<T>& operator*() {
     return *this;
   }
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 043cc74..ae50146 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -1586,6 +1586,38 @@
   EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString());
 }
 
+#if LANG_CXX11
+TEST_F(RepeatedFieldInsertionIteratorsTest, MoveStrings) {
+  std::vector<string> src = {"a", "b", "c", "d"};
+  std::vector<string> copy = src;  // copy since move leaves in undefined state
+  TestAllTypes testproto;
+  std::move(copy.begin(), copy.end(),
+            RepeatedFieldBackInserter(testproto.mutable_repeated_string()));
+
+  ASSERT_THAT(testproto.repeated_string(), testing::ElementsAreArray(src));
+}
+
+TEST_F(RepeatedFieldInsertionIteratorsTest, MoveProtos) {
+  auto make_nested = [](int32 x) {
+    Nested ret;
+    ret.set_bb(x);
+    return ret;
+  };
+  std::vector<Nested> src = {make_nested(3), make_nested(5), make_nested(7)};
+  std::vector<Nested> copy = src;  // copy since move leaves in undefined state
+  TestAllTypes testproto;
+  std::move(
+      copy.begin(), copy.end(),
+      RepeatedFieldBackInserter(testproto.mutable_repeated_nested_message()));
+
+  ASSERT_EQ(src.size(), testproto.repeated_nested_message_size());
+  for (int i = 0; i < src.size(); ++i) {
+    EXPECT_EQ(src[i].DebugString(),
+              testproto.repeated_nested_message(i).DebugString());
+  }
+}
+#endif
+
 }  // namespace
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 3244444..a69739c 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -19,7 +19,10 @@
 
 namespace google {
 namespace protobuf {
-class SourceContextDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<SourceContext> {
+class SourceContextDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<SourceContext>
+     _instance;
 } _SourceContext_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto {
@@ -32,20 +35,20 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -53,8 +56,7 @@
   ~0u,  // no _weak_field_map_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceContext, file_name_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(SourceContext)},
 };
 
@@ -84,26 +86,22 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _SourceContext_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _SourceContext_default_instance_.DefaultConstruct();
-}
+  _SourceContext_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_SourceContext_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n$google/protobuf/source_context.proto\022\017"
       "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile"
       "_name\030\001 \001(\tB\225\001\n\023com.google.protobufB\022Sou"
@@ -116,14 +114,14 @@
       descriptor, 251);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/source_context.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -198,7 +196,12 @@
 
 void SourceContext::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  _internal_metadata_.Clear();
 }
 
 bool SourceContext::MergePartialFromCodedStream(
@@ -214,11 +217,11 @@
       // string file_name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_file_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->file_name().data(), this->file_name().length(),
+            this->file_name().data(), static_cast<int>(this->file_name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.SourceContext.file_name"));
         } else {
@@ -229,12 +232,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -257,18 +259,23 @@
   // string file_name = 1;
   if (this->file_name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->file_name().data(), this->file_name().length(),
+      this->file_name().data(), static_cast<int>(this->file_name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.SourceContext.file_name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
       1, this->file_name(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.SourceContext)
 }
 
 ::google::protobuf::uint8* SourceContext::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -276,7 +283,7 @@
   // string file_name = 1;
   if (this->file_name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->file_name().data(), this->file_name().length(),
+      this->file_name().data(), static_cast<int>(this->file_name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.SourceContext.file_name");
     target =
@@ -284,6 +291,10 @@
         1, this->file_name(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext)
   return target;
 }
@@ -292,6 +303,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // string file_name = 1;
   if (this->file_name().size() > 0) {
     total_size += 1 +
@@ -357,8 +373,10 @@
   InternalSwap(other);
 }
 void SourceContext::InternalSwap(SourceContext* other) {
+  using std::swap;
   file_name_.Swap(&other->file_name_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata SourceContext::GetMetadata() const {
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 23cd7f3..b4617c5 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -48,8 +48,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -68,7 +69,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  SourceContext(SourceContext&& from) noexcept
+    : SourceContext() {
+    *this = ::std::move(from);
+  }
 
+  inline SourceContext& operator=(SourceContext&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   static const ::google::protobuf::Descriptor* descriptor();
   static const SourceContext& default_instance();
 
@@ -80,6 +95,9 @@
     0;
 
   void Swap(SourceContext* other);
+  friend void swap(SourceContext& a, SourceContext& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -149,6 +167,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // SourceContext
 
 // string file_name = 1;
@@ -204,6 +226,9 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 207e9ef..02d9306 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -19,12 +19,20 @@
 
 namespace google {
 namespace protobuf {
-class Struct_FieldsEntryDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Struct::Struct_FieldsEntry> {
+class Struct_FieldsEntryDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Struct::Struct_FieldsEntry>
+     _instance;
 } _Struct_FieldsEntry_default_instance_;
-class StructDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Struct> {
+class StructDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Struct>
+     _instance;
 } _Struct_default_instance_;
-class ValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Value> {
-  public:
+class ValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Value>
+     _instance;
   int null_value_;
   double number_value_;
   ::google::protobuf::internal::ArenaStringPtr string_value_;
@@ -32,7 +40,10 @@
   const ::google::protobuf::Struct* struct_value_;
   const ::google::protobuf::ListValue* list_value_;
 } _Value_default_instance_;
-class ListValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<ListValue> {
+class ListValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<ListValue>
+     _instance;
 } _ListValue_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fstruct_2eproto {
@@ -46,23 +57,23 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Struct, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -74,12 +85,12 @@
   ~0u,  // no _extensions_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, _oneof_case_[0]),
   ~0u,  // no _weak_field_map_
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET((&_Value_default_instance_), null_value_),
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET((&_Value_default_instance_), number_value_),
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET((&_Value_default_instance_), string_value_),
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET((&_Value_default_instance_), bool_value_),
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET((&_Value_default_instance_), struct_value_),
-  GOOGLE_PROTOBUF_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET((&_Value_default_instance_), list_value_),
+  offsetof(ValueDefaultTypeInternal, null_value_),
+  offsetof(ValueDefaultTypeInternal, number_value_),
+  offsetof(ValueDefaultTypeInternal, string_value_),
+  offsetof(ValueDefaultTypeInternal, bool_value_),
+  offsetof(ValueDefaultTypeInternal, struct_value_),
+  offsetof(ValueDefaultTypeInternal, list_value_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Value, kind_),
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, _internal_metadata_),
@@ -88,8 +99,7 @@
   ~0u,  // no _weak_field_map_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ListValue, values_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Struct)},
   { 6, -1, sizeof(Value)},
   { 18, -1, sizeof(ListValue)},
@@ -110,7 +120,7 @@
   AssignDescriptors(
       "google/protobuf/struct.proto", schemas, file_default_instances, TableStruct::offsets, factory,
       file_level_metadata, file_level_enum_descriptors, NULL);
-file_level_metadata[0].reflection = Struct::Struct_FieldsEntry::CreateReflection(file_level_metadata[0].descriptor, _Struct_FieldsEntry_default_instance_.get_mutable());
+file_level_metadata[0].reflection = Struct::Struct_FieldsEntry::CreateReflection(file_level_metadata[0].descriptor, _Struct_FieldsEntry_default_instance_._instance.get_mutable());
 }
 
 void protobuf_AssignDescriptorsOnce() {
@@ -125,27 +135,20 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Struct_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _Value_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-  _ListValue_default_instance_.Shutdown();
-  delete file_level_metadata[3].reflection;
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _Struct_FieldsEntry_default_instance_.DefaultConstruct();
-  _Struct_default_instance_.DefaultConstruct();
-  _Value_default_instance_.DefaultConstruct();
-  _ListValue_default_instance_.DefaultConstruct();
-  _Struct_FieldsEntry_default_instance_.get_mutable()->set_default_instance(_Struct_FieldsEntry_default_instance_.get_mutable());
-  _Struct_FieldsEntry_default_instance_.get_mutable()->InitAsDefaultInstance();
+  _Struct_FieldsEntry_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Struct_FieldsEntry_default_instance_);_Struct_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Struct_default_instance_);_Value_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Value_default_instance_);_ListValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_ListValue_default_instance_);_Struct_FieldsEntry_default_instance_._instance.get_mutable()->set_default_instance(_Struct_FieldsEntry_default_instance_._instance.get_mutable());
+  _Struct_FieldsEntry_default_instance_._instance.get_mutable()->InitAsDefaultInstance();
   _Value_default_instance_.null_value_ = 0;
   _Value_default_instance_.number_value_ = 0;
   _Value_default_instance_.string_value_.UnsafeSetDefault(
@@ -161,9 +164,10 @@
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\034google/protobuf/struct.proto\022\017google.p"
       "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo"
       "gle.protobuf.Struct.FieldsEntry\032E\n\013Field"
@@ -186,14 +190,14 @@
       descriptor, 641);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/struct.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -253,9 +257,7 @@
   : ::google::protobuf::Message(),
   _internal_metadata_(arena),
   fields_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Struct)
@@ -280,6 +282,7 @@
 
 void Struct::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -313,7 +316,12 @@
 
 void Struct::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Struct)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   fields_.Clear();
+  _internal_metadata_.Clear();
 }
 
 bool Struct::MergePartialFromCodedStream(
@@ -329,7 +337,7 @@
       // map<string, .google.protobuf.Value> fields = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           Struct_FieldsEntry::Parser< ::google::protobuf::internal::MapField<
               Struct_FieldsEntry,
               ::std::string, ::google::protobuf::Value,
@@ -340,7 +348,7 @@
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
               input, &parser));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            parser.key().data(), parser.key().length(),
+            parser.key().data(), static_cast<int>(parser.key().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Struct.FieldsEntry.key"));
         } else {
@@ -351,12 +359,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -385,7 +392,7 @@
     struct Utf8Check {
       static void Check(ConstPtr p) {
         ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-          p->first.data(), p->first.length(),
+          p->first.data(), static_cast<int>(p->first.length()),
           ::google::protobuf::internal::WireFormatLite::SERIALIZE,
           "google.protobuf.Struct.FieldsEntry.key");
       }
@@ -400,19 +407,19 @@
       for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
           it = this->fields().begin();
           it != this->fields().end(); ++it, ++n) {
-        items[n] = SortItem(&*it);
+        items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);
       }
-      ::std::sort(&items[0], &items[n], Less());
+      ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
       ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
       for (size_type i = 0; i < n; i++) {
         entry.reset(fields_.NewEntryWrapper(
-            items[i]->first, items[i]->second));
+            items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second));
         ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
             1, *entry, output);
         if (entry->GetArena() != NULL) {
           entry.release();
         }
-        Utf8Check::Check(items[i]);
+        Utf8Check::Check(items[static_cast<ptrdiff_t>(i)]);
       }
     } else {
       ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
@@ -431,11 +438,16 @@
     }
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Struct)
 }
 
 ::google::protobuf::uint8* Struct::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -449,7 +461,7 @@
     struct Utf8Check {
       static void Check(ConstPtr p) {
         ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-          p->first.data(), p->first.length(),
+          p->first.data(), static_cast<int>(p->first.length()),
           ::google::protobuf::internal::WireFormatLite::SERIALIZE,
           "google.protobuf.Struct.FieldsEntry.key");
       }
@@ -464,13 +476,13 @@
       for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator
           it = this->fields().begin();
           it != this->fields().end(); ++it, ++n) {
-        items[n] = SortItem(&*it);
+        items[static_cast<ptrdiff_t>(n)] = SortItem(&*it);
       }
-      ::std::sort(&items[0], &items[n], Less());
+      ::std::sort(&items[0], &items[static_cast<ptrdiff_t>(n)], Less());
       ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
       for (size_type i = 0; i < n; i++) {
         entry.reset(fields_.NewEntryWrapper(
-            items[i]->first, items[i]->second));
+            items[static_cast<ptrdiff_t>(i)]->first, items[static_cast<ptrdiff_t>(i)]->second));
         target = ::google::protobuf::internal::WireFormatLite::
                    InternalWriteMessageNoVirtualToArray(
                        1, *entry, deterministic, target);
@@ -478,7 +490,7 @@
         if (entry->GetArena() != NULL) {
           entry.release();
         }
-        Utf8Check::Check(items[i]);
+        Utf8Check::Check(items[static_cast<ptrdiff_t>(i)]);
       }
     } else {
       ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry;
@@ -499,6 +511,10 @@
     }
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct)
   return target;
 }
@@ -507,6 +523,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // map<string, .google.protobuf.Value> fields = 1;
   total_size += 1 *
       ::google::protobuf::internal::FromIntSize(this->fields_size());
@@ -597,8 +618,10 @@
   InternalSwap(other);
 }
 void Struct::InternalSwap(Struct* other) {
+  using std::swap;
   fields_.Swap(&other->fields_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Struct::GetMetadata() const {
@@ -651,9 +674,7 @@
 Value::Value(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Value)
@@ -708,6 +729,7 @@
 
 void Value::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -784,7 +806,12 @@
 
 void Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Value)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   clear_kind();
+  _internal_metadata_.Clear();
 }
 
 bool Value::MergePartialFromCodedStream(
@@ -800,7 +827,7 @@
       // .google.protobuf.NullValue null_value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -815,7 +842,7 @@
       // double number_value = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(17u)) {
+            static_cast< ::google::protobuf::uint8>(17u /* 17 & 0xFF */)) {
           clear_kind();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
@@ -830,11 +857,11 @@
       // string string_value = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_string_value()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->string_value().data(), this->string_value().length(),
+            this->string_value().data(), static_cast<int>(this->string_value().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Value.string_value"));
         } else {
@@ -846,7 +873,7 @@
       // bool bool_value = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(32u)) {
+            static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) {
           clear_kind();
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -861,7 +888,7 @@
       // .google.protobuf.Struct struct_value = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(42u)) {
+            static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_struct_value()));
         } else {
@@ -873,7 +900,7 @@
       // .google.protobuf.ListValue list_value = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_list_value()));
         } else {
@@ -884,12 +911,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -923,7 +949,7 @@
   // string string_value = 3;
   if (has_string_value()) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->string_value().data(), this->string_value().length(),
+      this->string_value().data(), static_cast<int>(this->string_value().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Value.string_value");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -947,11 +973,16 @@
       6, *kind_.list_value_, output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Value)
 }
 
 ::google::protobuf::uint8* Value::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -970,7 +1001,7 @@
   // string string_value = 3;
   if (has_string_value()) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->string_value().data(), this->string_value().length(),
+      this->string_value().data(), static_cast<int>(this->string_value().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Value.string_value");
     target =
@@ -997,6 +1028,10 @@
         6, *kind_.list_value_, deterministic, target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value)
   return target;
 }
@@ -1005,6 +1040,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   switch (kind_case()) {
     // .google.protobuf.NullValue null_value = 1;
     case kNullValue: {
@@ -1145,9 +1185,11 @@
   InternalSwap(other);
 }
 void Value::InternalSwap(Value* other) {
-  std::swap(kind_, other->kind_);
-  std::swap(_oneof_case_[0], other->_oneof_case_[0]);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(kind_, other->kind_);
+  swap(_oneof_case_[0], other->_oneof_case_[0]);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Value::GetMetadata() const {
@@ -1247,6 +1289,19 @@
       GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
 }
+#if LANG_CXX11
+void Value::set_string_value(::std::string&& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value)
+}
+#endif
 void Value::set_string_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   if (!has_string_value()) {
@@ -1560,9 +1615,7 @@
   : ::google::protobuf::Message(),
   _internal_metadata_(arena),
   values_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fstruct_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.ListValue)
@@ -1587,6 +1640,7 @@
 
 void ListValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -1620,7 +1674,12 @@
 
 void ListValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   values_.Clear();
+  _internal_metadata_.Clear();
 }
 
 bool ListValue::MergePartialFromCodedStream(
@@ -1636,7 +1695,7 @@
       // repeated .google.protobuf.Value values = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_values()));
         } else {
@@ -1647,12 +1706,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1673,27 +1731,38 @@
   (void) cached_has_bits;
 
   // repeated .google.protobuf.Value values = 1;
-  for (unsigned int i = 0, n = this->values_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->values_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      1, this->values(i), output);
+      1, this->values(static_cast<int>(i)), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.ListValue)
 }
 
 ::google::protobuf::uint8* ListValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.Value values = 1;
-  for (unsigned int i = 0, n = this->values_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->values_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        1, this->values(i), deterministic, target);
+        1, this->values(static_cast<int>(i)), deterministic, target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue)
   return target;
 }
@@ -1702,14 +1771,19 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.Value values = 1;
   {
-    unsigned int count = this->values_size();
+    unsigned int count = static_cast<unsigned int>(this->values_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->values(i));
+          this->values(static_cast<int>(i)));
     }
   }
 
@@ -1783,8 +1857,10 @@
   InternalSwap(other);
 }
 void ListValue::InternalSwap(ListValue* other) {
+  using std::swap;
   values_.InternalSwap(&other->values_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata ListValue::GetMetadata() const {
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index a37a565..57ae7d9 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -29,6 +29,7 @@
 #include <google/protobuf/repeated_field.h>  // IWYU pragma: export
 #include <google/protobuf/extension_set.h>  // IWYU pragma: export
 #include <google/protobuf/map.h>  // IWYU pragma: export
+#include <google/protobuf/map_entry.h>
 #include <google/protobuf/map_field_inl.h>
 #include <google/protobuf/generated_enum_reflection.h>
 #include <google/protobuf/unknown_field_set.h>
@@ -60,8 +61,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -103,7 +105,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Struct(Struct&& from) noexcept
+    : Struct() {
+    *this = ::std::move(from);
+  }
 
+  inline Struct& operator=(Struct&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -122,6 +138,9 @@
 
   void UnsafeArenaSwap(Struct* other);
   void Swap(Struct* other);
+  friend void swap(Struct& a, Struct& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -182,7 +201,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   public:
@@ -204,6 +223,7 @@
     static const Message* internal_default_instance() { return reinterpret_cast<const Message*>(&_Struct_FieldsEntry_default_instance_); }
     ::google::protobuf::Metadata GetMetadata() const;
   };
+  private:
   ::google::protobuf::internal::MapField<
       Struct_FieldsEntry,
       ::std::string, ::google::protobuf::Value,
@@ -227,7 +247,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Value(Value&& from) noexcept
+    : Value() {
+    *this = ::std::move(from);
+  }
 
+  inline Value& operator=(Value&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -256,6 +290,9 @@
 
   void UnsafeArenaSwap(Value* other);
   void Swap(Value* other);
+  friend void swap(Value& a, Value& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -328,6 +365,9 @@
   static const int kStringValueFieldNumber = 3;
   const ::std::string& string_value() const;
   void set_string_value(const ::std::string& value);
+  #if LANG_CXX11
+  void set_string_value(::std::string&& value);
+  #endif
   void set_string_value(const char* value);
   void set_string_value(const char* value, size_t size);
   ::std::string* mutable_string_value();
@@ -397,7 +437,7 @@
   inline void clear_has_kind();
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   union KindUnion {
@@ -427,7 +467,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  ListValue(ListValue&& from) noexcept
+    : ListValue() {
+    *this = ::std::move(from);
+  }
 
+  inline ListValue& operator=(ListValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -446,6 +500,9 @@
 
   void UnsafeArenaSwap(ListValue* other);
   void Swap(ListValue* other);
+  friend void swap(ListValue& a, ListValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -508,7 +565,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value > values_;
@@ -521,6 +578,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // -------------------------------------------------------------------
 
 // Struct
@@ -636,6 +697,19 @@
       GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
 }
+#if LANG_CXX11
+inline void Value::set_string_value(::std::string&& value) {
+  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
+  if (!has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value)
+}
+#endif
 inline void Value::set_string_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   if (!has_string_value()) {
@@ -963,6 +1037,9 @@
   return values_;
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 // -------------------------------------------------------------------
 
@@ -977,7 +1054,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#ifndef SWIG
 namespace google {
 namespace protobuf {
 
@@ -989,7 +1065,6 @@
 
 }  // namespace protobuf
 }  // namespace google
-#endif  // SWIG
 
 // @@protoc_insertion_point(global_scope)
 
diff --git a/src/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
index 75aee30..64c838f 100644
--- a/src/google/protobuf/stubs/atomicops.h
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -63,28 +63,21 @@
 namespace protobuf {
 namespace internal {
 
-#if defined(GOOGLE_PROTOBUF_ARCH_POWER)
-#if defined(_LP64) || defined(__LP64__)
-typedef int32 Atomic32;
-typedef intptr_t Atomic64;
+#ifdef GOOGLE_PROTOBUF_ARCH_32_BIT
+  typedef intptr_t Atomic32;
+  typedef int64 Atomic64;
 #else
-typedef intptr_t Atomic32;
-typedef int64 Atomic64;
-#endif
-#else
-typedef int32 Atomic32;
-#ifdef GOOGLE_PROTOBUF_ARCH_64_BIT
-// We need to be able to go between Atomic64 and AtomicWord implicitly.  This
-// means Atomic64 and AtomicWord should be the same type on 64-bit.
-#if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL)
-// NaCl's intptr_t is not actually 64-bits on 64-bit!
-// http://code.google.com/p/nativeclient/issues/detail?id=1162
-// sparcv9's pointer type is 32bits
-typedef int64 Atomic64;
-#else
-typedef intptr_t Atomic64;
-#endif
-#endif
+  typedef int32 Atomic32;
+  // We need to be able to go between Atomic64 and AtomicWord implicitly.  This
+  // means Atomic64 and AtomicWord should be the same type on 64-bit.
+  #if defined(__ILP32__) || defined(GOOGLE_PROTOBUF_OS_NACL)
+  // NaCl's intptr_t is not actually 64-bits on 64-bit!
+  // http://code.google.com/p/nativeclient/issues/detail?id=1162
+  // sparcv9's pointer type is 32bits
+  typedef int64 Atomic64;
+  #else
+  typedef intptr_t Atomic64;
+  #endif
 #endif
 
 // Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
old mode 100644
new mode 100755
index 1465591..7382216
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -30,6 +30,7 @@
 
 // Author: [email protected] (Kenton Varda)
 
+#include <google/protobuf/message_lite.h>  // TODO(gerbens) ideally remove this.
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/stubs/status.h>
@@ -416,13 +417,30 @@
 namespace internal {
 
 typedef void OnShutdownFunc();
-vector<void (*)()>* shutdown_functions = NULL;
-Mutex* shutdown_functions_mutex = NULL;
+struct ShutdownData {
+  ~ShutdownData() {
+    for (int i = 0; i < functions.size(); i++) {
+      functions[i]();
+    }
+    for (int i = 0; i < strings.size(); i++) {
+      strings[i]->~string();
+    }
+    for (int i = 0; i < messages.size(); i++) {
+      messages[i]->~MessageLite();
+    }
+  }
+
+  vector<void (*)()> functions;
+  vector<const std::string*> strings;
+  vector<const MessageLite*> messages;
+  Mutex mutex;
+};
+
+ShutdownData* shutdown_data = NULL;
 GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init);
 
 void InitShutdownFunctions() {
-  shutdown_functions = new vector<void (*)()>;
-  shutdown_functions_mutex = new Mutex;
+  shutdown_data = new ShutdownData;
 }
 
 inline void InitShutdownFunctionsOnce() {
@@ -431,8 +449,20 @@
 
 void OnShutdown(void (*func)()) {
   InitShutdownFunctionsOnce();
-  MutexLock lock(shutdown_functions_mutex);
-  shutdown_functions->push_back(func);
+  MutexLock lock(&shutdown_data->mutex);
+  shutdown_data->functions.push_back(func);
+}
+
+void OnShutdownDestroyString(const std::string* ptr) {
+  InitShutdownFunctionsOnce();
+  MutexLock lock(&shutdown_data->mutex);
+  shutdown_data->strings.push_back(ptr);
+}
+
+void OnShutdownDestroyMessage(const void* ptr) {
+  InitShutdownFunctionsOnce();
+  MutexLock lock(&shutdown_data->mutex);
+  shutdown_data->messages.push_back(static_cast<const MessageLite*>(ptr));
 }
 
 }  // namespace internal
@@ -445,15 +475,10 @@
   // called.
 
   // Make it safe to call this multiple times.
-  if (internal::shutdown_functions == NULL) return;
+  if (internal::shutdown_data == NULL) return;
 
-  for (int i = 0; i < internal::shutdown_functions->size(); i++) {
-    internal::shutdown_functions->at(i)();
-  }
-  delete internal::shutdown_functions;
-  internal::shutdown_functions = NULL;
-  delete internal::shutdown_functions_mutex;
-  internal::shutdown_functions_mutex = NULL;
+  delete internal::shutdown_data;
+  internal::shutdown_data = NULL;
 }
 
 #if PROTOBUF_USE_EXCEPTIONS
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 60874e0..ff36348 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -101,27 +101,27 @@
 
 // The current version, represented as a single integer to make comparison
 // easier:  major * 10^6 + minor * 10^3 + micro
-#define GOOGLE_PROTOBUF_VERSION 3003000
+#define GOOGLE_PROTOBUF_VERSION 3004000
 
 // A suffix string for alpha, beta or rc releases. Empty for stable releases.
 #define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
 
 // The minimum library version which works with the current version of the
 // headers.
-#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3003000
+#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3004000
 
 // The minimum header version which works with the current version of
 // the library.  This constant should only be used by protoc's C++ code
 // generator.
-static const int kMinHeaderVersionForLibrary = 3003000;
+static const int kMinHeaderVersionForLibrary = 3004000;
 
 // The minimum protoc version which works with the current version of the
 // headers.
-#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3003000
+#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3004000
 
 // The minimum header version which works with the current version of
 // protoc.  This constant should only be used in VerifyVersion().
-static const int kMinHeaderVersionForProtoc = 3003000;
+static const int kMinHeaderVersionForProtoc = 3004000;
 
 // Verifies that the headers and libraries are compatible.  Use the macro
 // below to call this.
@@ -200,6 +200,10 @@
 
 // Register a function to be called when ShutdownProtocolBuffers() is called.
 LIBPROTOBUF_EXPORT void OnShutdown(void (*func)());
+// Destroy the string (call string destructor)
+LIBPROTOBUF_EXPORT void OnShutdownDestroyString(const std::string* ptr);
+// Destroy (not delete) the message
+LIBPROTOBUF_EXPORT void OnShutdownDestroyMessage(const void* ptr);
 
 }  // namespace internal
 
@@ -227,10 +231,8 @@
 // in some versions of MSVC.
 // TODO(acozzette): remove these using statements
 using std::istream;
-using std::map;
 using std::ostream;
 using std::pair;
-using std::set;
 using std::string;
 using std::vector;
 
diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h
index 763a6e6..1f1f6ed 100644
--- a/src/google/protobuf/stubs/fastmem.h
+++ b/src/google/protobuf/stubs/fastmem.h
@@ -111,7 +111,8 @@
     b += sizeof(uint32);
   }
   while (a < a_limit) {
-    int d = static_cast<uint32>(*a++) - static_cast<uint32>(*b++);
+    int d =
+        static_cast<int>(static_cast<uint32>(*a++) - static_cast<uint32>(*b++));
     if (d) return d;
   }
   return 0;
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index be998b2..612b586 100644
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -40,10 +40,9 @@
 
 #define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1
 #define GOOGLE_PROTOBUF_HAVE_HASH_SET 1
-#define GOOGLE_PROTOBUF_HAVE_64BIT_HASH 1
 
 // Use C++11 unordered_{map|set} if available.
-#if ((_LIBCPP_STD_VER >= 11) || \
+#if ((defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) || \
     (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \
     (__GLIBCXX__ > 20090421)))
 # define GOOGLE_PROTOBUF_HAS_CXX11_HASH
@@ -93,8 +92,11 @@
 #  define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set
 # endif
 
+// GCC <= 4.1 does not define std::tr1::hash for `long long int` or `long long unsigned int`
 # if __GNUC__ == 4 && __GNUC__MINOR__ <= 1
-#  undef GOOGLE_PROTOBUF_HAVE_64BIT_HASH
+#  define GOOGLE_PROTOBUF_MISSING_HASH
+#  include <map>
+#  include <set>
 # endif
 
 // Version checks for MSC.
@@ -348,7 +350,7 @@
   inline size_t operator()(const char* str) const {
     size_t result = 0;
     for (; *str != '\0'; str++) {
-      result = 5 * result + *str;
+      result = 5 * result + static_cast<size_t>(*str);
     }
     return result;
   }
diff --git a/src/google/protobuf/stubs/io_win32.cc b/src/google/protobuf/stubs/io_win32.cc
new file mode 100644
index 0000000..51656a7
--- /dev/null
+++ b/src/google/protobuf/stubs/io_win32.cc
@@ -0,0 +1,362 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: [email protected] (Laszlo Csomor)
+//
+// Implementation for long-path-aware open/mkdir/etc. on Windows.
+//
+// These functions convert the input path to an absolute Windows path
+// with "\\?\" prefix if necessary, then pass that to _wopen/_wmkdir/etc.
+// (declared in <io.h>) respectively. This allows working with files/directories
+// whose paths are longer than MAX_PATH (260 chars).
+//
+// This file is only used on Windows, it's empty on other platforms.
+
+#if defined(_MSC_VER)
+
+// Comment this out to fall back to using the ANSI versions (open, mkdir, ...)
+// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to
+// debug failing tests if that's caused by the long path support.
+#define SUPPORT_LONGPATHS
+
+#include <ctype.h>
+#include <direct.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <wctype.h>
+#include <windows.h>
+
+#include <google/protobuf/stubs/io_win32.h>
+#include <google/protobuf/stubs/scoped_ptr.h>
+
+#include <cassert>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace win32 {
+namespace {
+
+using std::string;
+using std::wstring;
+
+template <typename char_type>
+struct CharTraits {
+  static bool is_alpha(char_type ch);
+};
+
+template <>
+struct CharTraits<char> {
+  static bool is_alpha(char ch) { return isalpha(ch); }
+};
+
+template <>
+struct CharTraits<wchar_t> {
+  static bool is_alpha(wchar_t ch) { return iswalpha(ch); }
+};
+
+// Returns true if the path starts with a drive letter, e.g. "c:".
+// Note that this won't check for the "\" after the drive letter, so this also
+// returns true for "c:foo" (which is "c:\${PWD}\foo").
+// This check requires that a path not have a longpath prefix ("\\?\").
+template <typename char_type>
+bool has_drive_letter(const char_type* ch) {
+  return CharTraits<char_type>::is_alpha(ch[0]) && ch[1] == ':';
+}
+
+// Returns true if the path starts with a longpath prefix ("\\?\").
+template <typename char_type>
+bool has_longpath_prefix(const char_type* path) {
+  return path[0] == '\\' && path[1] == '\\' && path[2] == '?' &&
+         path[3] == '\\';
+}
+
+template <typename char_type>
+bool is_separator(char_type c) {
+  return c == '/' || c == '\\';
+}
+
+// Returns true if the path starts with a drive specifier (e.g. "c:\").
+template <typename char_type>
+bool is_path_absolute(const char_type* path) {
+  return has_drive_letter(path) && is_separator(path[2]);
+}
+
+template <typename char_type>
+bool is_drive_relative(const char_type* path) {
+  return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2]));
+}
+
+template <typename char_type>
+void replace_directory_separators(char_type* p) {
+  for (; *p; ++p) {
+    if (*p == '/') {
+      *p = '\\';
+    }
+  }
+}
+
+string join_paths(const string& path1, const string& path2) {
+  if (path1.empty() || is_path_absolute(path2.c_str()) ||
+      has_longpath_prefix(path2.c_str())) {
+    return path2;
+  }
+  if (path2.empty()) {
+    return path1;
+  }
+
+  if (is_separator(path1[path1.size() - 1])) {
+    return is_separator(path2[0]) ? (path1 + path2.substr(1))
+                                       : (path1 + path2);
+  } else {
+    return is_separator(path2[0]) ? (path1 + path2)
+                                       : (path1 + '\\' + path2);
+  }
+}
+
+string normalize(string path) {
+  if (has_longpath_prefix(path.c_str())) {
+    path = path.substr(4);
+  }
+
+  static const string dot(".");
+  static const string dotdot("..");
+
+  std::vector<string> segments;
+  int segment_start = -1;
+  // Find the path segments in `path` (separated by "/").
+  for (int i = 0;; ++i) {
+    if (!is_separator(path[i]) && path[i] != '\0') {
+      // The current character does not end a segment, so start one unless it's
+      // already started.
+      if (segment_start < 0) {
+        segment_start = i;
+      }
+    } else if (segment_start >= 0 && i > segment_start) {
+      // The current character is "/" or "\0", so this ends a segment.
+      // Add that to `segments` if there's anything to add; handle "." and "..".
+      string segment(path, segment_start, i - segment_start);
+      segment_start = -1;
+      if (segment == dotdot) {
+        if (!segments.empty() &&
+            (!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) {
+          segments.pop_back();
+        }
+      } else if (segment != dot && !segment.empty()) {
+        segments.push_back(segment);
+      }
+    }
+    if (path[i] == '\0') {
+      break;
+    }
+  }
+
+  // Handle the case when `path` is just a drive specifier (or some degenerate
+  // form of it, e.g. "c:\..").
+  if (segments.size() == 1 && segments[0].size() == 2 &&
+      has_drive_letter(segments[0].c_str())) {
+    return segments[0] + '\\';
+  }
+
+  // Join all segments.
+  bool first = true;
+  std::ostringstream result;
+  for (const auto& s : segments) {
+    if (!first) {
+      result << '\\';
+    }
+    first = false;
+    result << s;
+  }
+  // Preserve trailing separator if the input contained it.
+  if (!path.empty() && is_separator(path[path.size() - 1])) {
+    result << '\\';
+  }
+  return result.str();
+}
+
+WCHAR* as_wstring(const string& s) {
+  int len = ::MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s.size(), NULL, 0);
+  WCHAR* result = new WCHAR[len + 1];
+  ::MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s.size(), result, len + 1);
+  result[len] = 0;
+  return result;
+}
+
+void as_wchar_path(const string& path, wstring* wchar_path) {
+  scoped_array<WCHAR> wbuf(as_wstring(path));
+  replace_directory_separators(wbuf.get());
+  wchar_path->assign(wbuf.get());
+}
+
+bool as_windows_path(const string& path, wstring* result) {
+  if (path.empty()) {
+    result->clear();
+    return true;
+  }
+  if (is_separator(path[0]) || is_drive_relative(path.c_str())) {
+    return false;
+  }
+
+  string mutable_path = path;
+  if (!is_path_absolute(mutable_path.c_str()) &&
+      !has_longpath_prefix(mutable_path.c_str())) {
+    char cwd[MAX_PATH];
+    ::GetCurrentDirectoryA(MAX_PATH, cwd);
+    mutable_path = join_paths(cwd, mutable_path);
+  }
+  as_wchar_path(normalize(mutable_path), result);
+  if (!has_longpath_prefix(result->c_str())) {
+    // Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API
+    // from processing the path and "helpfully" removing trailing dots from the
+    // path, for example.
+    // See https://github.com/bazelbuild/bazel/issues/2935
+    *result = wstring(L"\\\\?\\") + *result;
+  }
+  return true;
+}
+
+}  // namespace
+
+int open(const char* path, int flags, int mode) {
+#ifdef SUPPORT_LONGPATHS
+  wstring wpath;
+  if (!as_windows_path(path, &wpath)) {
+    errno = ENOENT;
+    return -1;
+  }
+  return ::_wopen(wpath.c_str(), flags, mode);
+#else
+  return ::_open(path, flags, mode);
+#endif
+}
+
+int mkdir(const char* path, int _mode) {
+#ifdef SUPPORT_LONGPATHS
+  wstring wpath;
+  if (!as_windows_path(path, &wpath)) {
+    errno = ENOENT;
+    return -1;
+  }
+  return ::_wmkdir(wpath.c_str());
+#else   // not SUPPORT_LONGPATHS
+  return ::_mkdir(path);
+#endif  // not SUPPORT_LONGPATHS
+}
+
+int access(const char* path, int mode) {
+#ifdef SUPPORT_LONGPATHS
+  wstring wpath;
+  if (!as_windows_path(path, &wpath)) {
+    errno = ENOENT;
+    return -1;
+  }
+  return ::_waccess(wpath.c_str(), mode);
+#else
+  return ::_access(path, mode);
+#endif
+}
+
+int chdir(const char* path) {
+#ifdef SUPPORT_LONGPATHS
+  wstring wpath;
+  if (!as_windows_path(path, &wpath)) {
+    errno = ENOENT;
+    return -1;
+  }
+  return ::_wchdir(wpath.c_str());
+#else
+  return ::_chdir(path);
+#endif
+}
+
+int stat(const char* path, struct _stat* buffer) {
+#ifdef SUPPORT_LONGPATHS
+  wstring wpath;
+  if (!as_windows_path(path, &wpath)) {
+    errno = ENOENT;
+    return -1;
+  }
+  return ::_wstat(wpath.c_str(), buffer);
+#else   // not SUPPORT_LONGPATHS
+  return ::_stat(path, buffer);
+#endif  // not SUPPORT_LONGPATHS
+}
+
+FILE* fopen(const char* path, const char* mode) {
+#ifdef SUPPORT_LONGPATHS
+  wstring wpath;
+  if (!as_windows_path(path, &wpath)) {
+    errno = ENOENT;
+    return NULL;
+  }
+  scoped_array<WCHAR> wmode(as_wstring(mode));
+  return ::_wfopen(wpath.c_str(), wmode.get());
+#else
+  return ::fopen(path, mode);
+#endif
+}
+
+int close(int fd) { return ::close(fd); }
+
+int dup(int fd) { return ::_dup(fd); }
+
+int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); }
+
+int read(int fd, void* buffer, size_t size) {
+  return ::_read(fd, buffer, size);
+}
+
+int setmode(int fd, int mode) { return ::_setmode(fd, mode); }
+
+int write(int fd, const void* buffer, size_t size) {
+  return ::_write(fd, buffer, size);
+}
+
+wstring testonly_path_to_winpath(const string& path) {
+  wstring wpath;
+  as_windows_path(path, &wpath);
+  return wpath;
+}
+
+}  // namespace win32
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // defined(_MSC_VER)
+
diff --git a/src/google/protobuf/stubs/io_win32.h b/src/google/protobuf/stubs/io_win32.h
new file mode 100644
index 0000000..a20e64c
--- /dev/null
+++ b/src/google/protobuf/stubs/io_win32.h
@@ -0,0 +1,104 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: [email protected] (Laszlo Csomor)
+//
+// This file contains the declarations for Windows implementations of
+// commonly used POSIX functions such as open(2) and access(2), as well
+// as macro definitions for flags of these functions.
+//
+// By including this file you'll redefine open/access/etc. to
+// ::google::protobuf::internal::win32::{open/access/etc.}.
+// Make sure you don't include a header that attempts to redeclare or
+// redefine these functions, that'll lead to confusing compilation
+// errors. It's best to #include this file as the last one to ensure that.
+//
+// This file is only used on Windows, it's empty on other platforms.
+
+#ifndef GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
+#define GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
+
+#if defined(_WIN32)
+
+#include <string>
+#include <google/protobuf/stubs/port.h>
+
+// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the
+// following functions already, except for mkdir.
+#ifdef _MSC_VER
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace win32 {
+
+LIBPROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode);
+LIBPROTOBUF_EXPORT int access(const char* path, int mode);
+LIBPROTOBUF_EXPORT int chdir(const char* path);
+LIBPROTOBUF_EXPORT int close(int fd);
+LIBPROTOBUF_EXPORT int dup(int fd);
+LIBPROTOBUF_EXPORT int dup2(int fd1, int fd2);
+LIBPROTOBUF_EXPORT int mkdir(const char* path, int _mode);
+LIBPROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0);
+LIBPROTOBUF_EXPORT int read(int fd, void* buffer, size_t size);
+LIBPROTOBUF_EXPORT int setmode(int fd, int mode);
+LIBPROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer);
+LIBPROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size);
+LIBPROTOBUF_EXPORT std::wstring testonly_path_to_winpath(
+    const std::string& path);
+
+}  // namespace win32
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+#else  // _MSC_VER
+#define mkdir(name, mode) mkdir(name)
+#endif // !_MSC_VER
+
+#ifndef W_OK
+#define W_OK 02  // not defined by MSVC for whatever reason
+#endif
+
+#ifndef F_OK
+#define F_OK 00  // not defined by MSVC for whatever reason
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#endif  // defined(_WIN32)
+
+#endif  // GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
+
+
diff --git a/src/google/protobuf/stubs/io_win32_unittest.cc b/src/google/protobuf/stubs/io_win32_unittest.cc
new file mode 100644
index 0000000..90bd9c9
--- /dev/null
+++ b/src/google/protobuf/stubs/io_win32_unittest.cc
@@ -0,0 +1,367 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: [email protected] (Laszlo Csomor)
+//
+// Unit tests for long-path-aware open/mkdir/access on Windows.
+//
+// This file is only used on Windows, it's empty on other platforms.
+
+#if defined(_WIN32)
+
+#define WIN32_LEAN_AND_MEAN
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <wchar.h>
+#include <windows.h>
+
+#include <google/protobuf/stubs/io_win32.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace win32 {
+namespace {
+
+using std::string;
+using std::unique_ptr;
+using std::wstring;
+
+class IoWin32Test : public ::testing::Test {
+ public:
+  void SetUp() override;
+  void TearDown() override;
+
+ protected:
+  bool CreateAllUnder(wstring path);
+  bool DeleteAllUnder(wstring path);
+
+  string test_tmpdir;
+  wstring wtest_tmpdir;
+};
+
+#define ASSERT_INITIALIZED              \
+  {                                     \
+    EXPECT_FALSE(test_tmpdir.empty());  \
+    EXPECT_FALSE(wtest_tmpdir.empty()); \
+  }
+
+void IoWin32Test::SetUp() {
+  test_tmpdir = string(TestTempDir());
+  wtest_tmpdir.clear();
+  if (test_tmpdir.empty()) {
+    const char* test_tmpdir_env = getenv("TEST_TMPDIR");
+    if (test_tmpdir_env != nullptr && *test_tmpdir_env) {
+      test_tmpdir = string(test_tmpdir_env);
+    }
+
+    // Only Bazel defines TEST_TMPDIR, CMake does not, so look for other
+    // suitable environment variables.
+    if (test_tmpdir.empty()) {
+      for (const char* name : {"TEMP", "TMP"}) {
+        test_tmpdir_env = getenv(name);
+        if (test_tmpdir_env != nullptr && *test_tmpdir_env) {
+          test_tmpdir = string(test_tmpdir_env);
+          break;
+        }
+      }
+    }
+
+    // No other temp directory was found. Use the current director
+    if (test_tmpdir.empty()) {
+      char buffer[MAX_PATH];
+      // Use GetCurrentDirectoryA instead of GetCurrentDirectoryW, because the
+      // current working directory must always be shorter than MAX_PATH, even
+      // with
+      // "\\?\" prefix (except on Windows 10 version 1607 and beyond, after
+      // opting in to long paths by default [1]).
+      //
+      // [1] https://msdn.microsoft.com/en-us/library/windows/ \
+      //   desktop/aa365247(v=vs.85).aspx#maxpath
+      DWORD result = ::GetCurrentDirectoryA(MAX_PATH, buffer);
+      if (result > 0) {
+        test_tmpdir = string(buffer);
+      } else {
+        // Using assertions in SetUp/TearDown seems to confuse the test
+        // framework, so just leave the member variables empty in case of
+        // failure.
+        GOOGLE_CHECK_OK(false);
+        return;
+      }
+    }
+  }
+
+  while (test_tmpdir.back() == '/' || test_tmpdir.back() == '\\') {
+    test_tmpdir.pop_back();
+  }
+  test_tmpdir += "\\io_win32_unittest.tmp";
+
+  // CreateDirectoryA's limit is 248 chars, see MSDN.
+  // https://msdn.microsoft.com/en-us/library/windows/ \
+  //   desktop/aa363855(v=vs.85).aspx
+  wtest_tmpdir = testonly_path_to_winpath(test_tmpdir);
+  if (!DeleteAllUnder(wtest_tmpdir) || !CreateAllUnder(wtest_tmpdir)) {
+    GOOGLE_CHECK_OK(false);
+    test_tmpdir.clear();
+    wtest_tmpdir.clear();
+  }
+}
+
+void IoWin32Test::TearDown() {
+  if (!wtest_tmpdir.empty()) {
+    DeleteAllUnder(wtest_tmpdir);
+  }
+}
+
+bool IoWin32Test::CreateAllUnder(wstring path) {
+  // Prepend UNC prefix if the path doesn't have it already. Don't bother
+  // checking if the path is shorter than MAX_PATH, let's just do it
+  // unconditionally.
+  if (path.find(L"\\\\?\\") != 0) {
+    path = wstring(L"\\\\?\\") + path;
+  }
+  if (::CreateDirectoryW(path.c_str(), NULL) ||
+      GetLastError() == ERROR_ALREADY_EXISTS ||
+      GetLastError() == ERROR_ACCESS_DENIED) {
+    return true;
+  }
+  if (GetLastError() == ERROR_PATH_NOT_FOUND) {
+    size_t pos = path.find_last_of(L'\\');
+    if (pos != wstring::npos) {
+      wstring parent(path, 0, pos);
+      if (CreateAllUnder(parent) && CreateDirectoryW(path.c_str(), NULL)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool IoWin32Test::DeleteAllUnder(wstring path) {
+  static const wstring kDot(L".");
+  static const wstring kDotDot(L"..");
+
+  // Prepend UNC prefix if the path doesn't have it already. Don't bother
+  // checking if the path is shorter than MAX_PATH, let's just do it
+  // unconditionally.
+  if (path.find(L"\\\\?\\") != 0) {
+    path = wstring(L"\\\\?\\") + path;
+  }
+  // Append "\" if necessary.
+  if (path.back() != '\\') {
+    path.push_back('\\');
+  }
+
+  WIN32_FIND_DATAW metadata;
+  HANDLE handle = ::FindFirstFileW((path + L"*").c_str(), &metadata);
+  if (handle == INVALID_HANDLE_VALUE) {
+    return true;  // directory doesn't exist
+  }
+
+  bool result = true;
+  do {
+    wstring childname = metadata.cFileName;
+    if (kDot != childname && kDotDot != childname) {
+      wstring childpath = path + childname;
+      if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+        // If this is not a junction, delete its contents recursively.
+        // Finally delete this directory/junction too.
+        if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 &&
+             !DeleteAllUnder(childpath)) ||
+            !::RemoveDirectoryW(childpath.c_str())) {
+          result = false;
+          break;
+        }
+      } else {
+        if (!::DeleteFileW(childpath.c_str())) {
+          result = false;
+          break;
+        }
+      }
+    }
+  } while (::FindNextFileW(handle, &metadata));
+  ::FindClose(handle);
+  return result;
+}
+
+TEST_F(IoWin32Test, AccessTest) {
+  ASSERT_INITIALIZED;
+
+  string path = test_tmpdir;
+  while (path.size() < MAX_PATH - 30) {
+    path += "\\accesstest";
+    EXPECT_EQ(mkdir(path.c_str(), 0644), 0);
+  }
+  string file = path + "\\file.txt";
+  int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644);
+  if (fd > 0) {
+    EXPECT_EQ(close(fd), 0);
+  } else {
+    EXPECT_TRUE(false);
+  }
+
+  EXPECT_EQ(access(test_tmpdir.c_str(), F_OK), 0);
+  EXPECT_EQ(access(path.c_str(), F_OK), 0);
+  EXPECT_EQ(access(path.c_str(), W_OK), 0);
+  EXPECT_EQ(access(file.c_str(), F_OK | W_OK), 0);
+  EXPECT_NE(access((file + ".blah").c_str(), F_OK), 0);
+  EXPECT_NE(access((file + ".blah").c_str(), W_OK), 0);
+
+  EXPECT_EQ(access(".", F_OK), 0);
+  EXPECT_EQ(access(".", W_OK), 0);
+  EXPECT_EQ(access((test_tmpdir + "/accesstest").c_str(), F_OK | W_OK), 0);
+  ASSERT_EQ(access((test_tmpdir + "/./normalize_me/.././accesstest").c_str(),
+                   F_OK | W_OK),
+            0);
+  EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", F_OK), 0);
+  EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", W_OK), 0);
+
+  ASSERT_EQ(access("c:bad", F_OK), -1);
+  ASSERT_EQ(errno, ENOENT);
+  ASSERT_EQ(access("/tmp/bad", F_OK), -1);
+  ASSERT_EQ(errno, ENOENT);
+  ASSERT_EQ(access("\\bad", F_OK), -1);
+  ASSERT_EQ(errno, ENOENT);
+}
+
+TEST_F(IoWin32Test, OpenTest) {
+  ASSERT_INITIALIZED;
+
+  string path = test_tmpdir;
+  while (path.size() < MAX_PATH) {
+    path += "\\opentest";
+    EXPECT_EQ(mkdir(path.c_str(), 0644), 0);
+  }
+  string file = path + "\\file.txt";
+  int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644);
+  if (fd > 0) {
+    EXPECT_EQ(write(fd, "hello", 5), 5);
+    EXPECT_EQ(close(fd), 0);
+  } else {
+    EXPECT_TRUE(false);
+  }
+
+  ASSERT_EQ(open("c:bad.txt", O_CREAT | O_WRONLY, 0644), -1);
+  ASSERT_EQ(errno, ENOENT);
+  ASSERT_EQ(open("/tmp/bad.txt", O_CREAT | O_WRONLY, 0644), -1);
+  ASSERT_EQ(errno, ENOENT);
+  ASSERT_EQ(open("\\bad.txt", O_CREAT | O_WRONLY, 0644), -1);
+  ASSERT_EQ(errno, ENOENT);
+}
+
+TEST_F(IoWin32Test, MkdirTest) {
+  ASSERT_INITIALIZED;
+
+  string path = test_tmpdir;
+  do {
+    path += "\\mkdirtest";
+    ASSERT_EQ(mkdir(path.c_str(), 0644), 0);
+  } while (path.size() <= MAX_PATH);
+
+  ASSERT_EQ(mkdir("c:bad", 0644), -1);
+  ASSERT_EQ(errno, ENOENT);
+  ASSERT_EQ(mkdir("/tmp/bad", 0644), -1);
+  ASSERT_EQ(errno, ENOENT);
+  ASSERT_EQ(mkdir("\\bad", 0644), -1);
+  ASSERT_EQ(errno, ENOENT);
+}
+
+TEST_F(IoWin32Test, ChdirTest) {
+  char owd[MAX_PATH];
+  EXPECT_GT(::GetCurrentDirectoryA(MAX_PATH, owd), 0);
+  string path("C:\\");
+  EXPECT_EQ(access(path.c_str(), F_OK), 0);
+  ASSERT_EQ(chdir(path.c_str()), 0);
+  EXPECT_TRUE(::SetCurrentDirectoryA(owd));
+
+  // Do not try to chdir into the test_tmpdir, it may already contain directory
+  // names with trailing dots.
+  // Instead test here with an obviously dot-trailed path. If the win32_chdir
+  // function would not convert the path to absolute and prefix with "\\?\" then
+  // the Win32 API would ignore the trailing dot, but because of the prefixing
+  // there'll be no path processing done, so we'll actually attempt to chdir
+  // into "C:\some\path\foo."
+  path = test_tmpdir + "/foo.";
+  EXPECT_EQ(mkdir(path.c_str(), 644), 0);
+  EXPECT_EQ(access(path.c_str(), F_OK), 0);
+  ASSERT_NE(chdir(path.c_str()), 0);
+}
+
+TEST_F(IoWin32Test, AsWindowsPathTest) {
+  DWORD size = GetCurrentDirectoryW(0, NULL);
+  unique_ptr<wchar_t[]> cwd_str(new wchar_t[size]);
+  EXPECT_GT(GetCurrentDirectoryW(size, cwd_str.get()), 0);
+  wstring cwd = wstring(L"\\\\?\\") + cwd_str.get();
+
+  ASSERT_EQ(testonly_path_to_winpath("relative_mkdirtest"),
+            cwd + L"\\relative_mkdirtest");
+  ASSERT_EQ(testonly_path_to_winpath("preserve//\\trailing///"),
+            cwd + L"\\preserve\\trailing\\");
+  ASSERT_EQ(testonly_path_to_winpath("./normalize_me\\/../blah"),
+            cwd + L"\\blah");
+  std::ostringstream relpath;
+  for (wchar_t* p = cwd_str.get(); *p; ++p) {
+    if (*p == '/' || *p == '\\') {
+      relpath << "../";
+    }
+  }
+  relpath << ".\\/../\\./beyond-toplevel";
+  ASSERT_EQ(testonly_path_to_winpath(relpath.str()),
+            wstring(L"\\\\?\\") + cwd_str.get()[0] + L":\\beyond-toplevel");
+
+  // Absolute unix paths lack drive letters, driveless absolute windows paths
+  // do too. Neither can be converted to a drive-specifying absolute Windows
+  // path.
+  ASSERT_EQ(testonly_path_to_winpath("/absolute/unix/path"), L"");
+  // Though valid on Windows, we also don't support UNC paths (\\UNC\\blah).
+  ASSERT_EQ(testonly_path_to_winpath("\\driveless\\absolute"), L"");
+  // Though valid in cmd.exe, drive-relative paths are not supported.
+  ASSERT_EQ(testonly_path_to_winpath("c:foo"), L"");
+  ASSERT_EQ(testonly_path_to_winpath("c:/foo"), L"\\\\?\\c:\\foo");
+}
+
+}  // namespace
+}  // namespace win32
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // defined(_WIN32)
+
diff --git a/src/google/protobuf/stubs/mathlimits.h b/src/google/protobuf/stubs/mathlimits.h
index 275d953..2391ac4 100644
--- a/src/google/protobuf/stubs/mathlimits.h
+++ b/src/google/protobuf/stubs/mathlimits.h
@@ -43,18 +43,23 @@
 #ifndef UTIL_MATH_MATHLIMITS_H__
 #define UTIL_MATH_MATHLIMITS_H__
 
-// GCC 4.9 has a bug that makes it impossible to use isinf and isnan when both
-// <math.h> and <cmath> get pulled into the same translation unit.
-// Unfortunately it is difficult to prevent this from happening, so to work
-// around the problem we use std::isinf and std::isnan from <cmath> for C++11
-// builds and otherwise use the plain isinf and isnan functions from <math.h>.
 // Note that for Windows we do something different because it does not support
 // the plain isinf and isnan.
 #if __cplusplus >= 201103L
+// GCC 4.9 has a bug that makes isinf and isnan ambigious when both <math.h>
+// and <cmath> get pulled into the same translation unit. We use the ones in
+// std:: namespace explicitly for C++11
 #include <cmath>
+#define GOOGLE_PROTOBUF_USE_STD_CMATH
+#elif _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
+// libstdc++ <cmath> header undefines the global macros and put functions in
+// std:: namespace even before C++11. Use the ones in std:: instead too.
+#include <cmath>
+#define GOOGLE_PROTOBUF_USE_STD_CMATH
 #else
 #include <math.h>
 #endif
+
 #include <string.h>
 
 #include <cfloat>
@@ -229,7 +234,7 @@
 // For non-Windows builds we use the std:: versions of isinf and isnan if they
 // are available; see the comment about <cmath> at the top of this file for the
 // details on why we need to do this.
-#if __cplusplus >= 201103L
+#ifdef GOOGLE_PROTOBUF_USE_STD_CMATH
 #define ISINF std::isinf
 #define ISNAN std::isnan
 #else
diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h
index 7ef1cb6..174290f 100644
--- a/src/google/protobuf/stubs/mutex.h
+++ b/src/google/protobuf/stubs/mutex.h
@@ -70,14 +70,6 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex);
 };
 
-// Undefine the macros  to workaround the conflicts with Google internal
-// MutexLock implementation.
-// TODO(liujisi): Remove the undef once internal macros are removed.
-#undef MutexLock
-#undef ReaderMutexLock
-#undef WriterMutexLock
-#undef MutexLockMaybe
-
 // MutexLock(mu) acquires mu when constructed and releases it when destroyed.
 class LIBPROTOBUF_EXPORT MutexLock {
  public:
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index 0afd55d..0f304c6 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -256,8 +256,11 @@
 # define GOOGLE_PROTOBUF_USE_UNALIGNED 0
 #else
 // x86 and x86-64 can perform unaligned loads/stores directly.
-# define GOOGLE_PROTOBUF_USE_UNALIGNED defined(_M_X64) || \
-     defined(__x86_64__) || defined(_M_IX86) || defined(__i386__)
+# if defined(_M_X64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__)
+#  define GOOGLE_PROTOBUF_USE_UNALIGNED 1
+# else
+#  define GOOGLE_PROTOBUF_USE_UNALIGNED 0
+# endif
 #endif
 
 #if GOOGLE_PROTOBUF_USE_UNALIGNED
@@ -354,7 +357,7 @@
  public:
   static uint32 Log2FloorNonZero(uint32 n) {
 #if defined(__GNUC__)
-  return 31 ^ __builtin_clz(n);
+  return 31 ^ static_cast<uint32>(__builtin_clz(n));
 #elif defined(COMPILER_MSVC) && defined(_M_IX86)
   _asm {
     bsr ebx, n
@@ -373,7 +376,7 @@
     // To work around this, when we build for NaCl we use the portable
     // implementation instead.
 #if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_OS_NACL)
-  return 63 ^ __builtin_clzll(n);
+  return 63 ^ static_cast<uint32>(__builtin_clzll(n));
 #else
   return Log2FloorNonZero64_Portable(n);
 #endif
@@ -400,9 +403,9 @@
     const uint32 topbits = static_cast<uint32>(n >> 32);
     if (topbits == 0) {
       // Top bits are zero, so scan in bottom bits
-      return Log2FloorNonZero(static_cast<uint32>(n));
+      return static_cast<int>(Log2FloorNonZero(static_cast<uint32>(n)));
     } else {
-      return 32 + Log2FloorNonZero(topbits);
+      return 32 + static_cast<int>(Log2FloorNonZero(topbits));
     }
   }
 };
@@ -467,6 +470,10 @@
   }
 };
 
+#ifndef GOOGLE_ATTRIBUTE_SECTION_VARIABLE
+#define GOOGLE_ATTRIBUTE_SECTION_VARIABLE(name)
+#endif
+
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index 8910688..563ff75 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -292,7 +292,7 @@
   int compare(StringPiece x) const {
     const stringpiece_ssize_type min_size =
         length_ < x.length_ ? length_ : x.length_;
-    int r = memcmp(ptr_, x.ptr_, min_size);
+    int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
     if (r < 0) return -1;
     if (r > 0) return 1;
     if (length_ < x.length_) return -1;
@@ -310,7 +310,7 @@
   // "as_string()" method defined here for existing code.
   string ToString() const {
     if (ptr_ == NULL) return string();
-    return string(data(), size());
+    return string(data(), static_cast<size_type>(size()));
   }
 
   operator string() const {
@@ -321,12 +321,14 @@
   void AppendToString(string* target) const;
 
   bool starts_with(StringPiece x) const {
-    return (length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0);
+    return (length_ >= x.length_) &&
+           (memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0);
   }
 
   bool ends_with(StringPiece x) const {
     return ((length_ >= x.length_) &&
-            (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0));
+            (memcmp(ptr_ + (length_-x.length_), x.ptr_,
+                 static_cast<size_t>(x.length_)) == 0));
   }
 
   // Checks whether StringPiece starts with x and if so advances the beginning
@@ -398,7 +400,7 @@
   }
 
   return x.data() == y.data() || len <= 0 ||
-      memcmp(x.data(), y.data(), len) == 0;
+      memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0;
 }
 
 inline bool operator!=(StringPiece x, StringPiece y) {
@@ -408,7 +410,7 @@
 inline bool operator<(StringPiece x, StringPiece y) {
   const stringpiece_ssize_type min_size =
       x.size() < y.size() ? x.size() : y.size();
-  const int r = memcmp(x.data(), y.data(), min_size);
+  const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
   return (r < 0) || (r == 0 && x.size() < y.size());
 }
 
@@ -458,7 +460,9 @@
     return size_;
   }
 
-  std::string ToString() const { return std::string(data_, size_); }
+  std::string ToString() const {
+    return std::string(data_, static_cast<size_t>(size_));
+  }
  private:
   const char* data_;
   stringpiece_ssize_type size_;
@@ -473,7 +477,7 @@
   size_t operator()(const StringPiece& s) const {
     size_t result = 0;
     for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {  
-      result = 5 * result + *str;
+      result = 5 * result + static_cast<size_t>(*str);
     }
     return result;
   }
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 336894b..1a4d71c 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -1401,7 +1401,7 @@
   float parsed_value;
   if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) {
     int snprintf_result =
-      snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+2, value);
+      snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+3, value);
 
     // Should never overflow; see above.
     GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
diff --git a/src/google/protobuf/test_messages_proto2.proto b/src/google/protobuf/test_messages_proto2.proto
new file mode 100644
index 0000000..cbe0d17
--- /dev/null
+++ b/src/google/protobuf/test_messages_proto2.proto
@@ -0,0 +1,216 @@
+// 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.
+//
+// Test schema for proto2 messages.  This test schema is used by:
+//
+// - conformance tests
+//
+
+syntax = "proto2";
+
+package protobuf_test_messages.proto2;
+option java_package = "com.google.protobuf_test_messages.proto2";
+
+// This is the default, but we specify it here explicitly.
+option optimize_for = SPEED;
+
+option cc_enable_arenas = true;
+
+// This proto includes every type of field in both singular and repeated
+// forms.
+//
+// Also, crucially, all messages and enums in this file are eventually
+// submessages of this message.  So for example, a fuzz test of TestAllTypes
+// could trigger bugs that occur in any message type in this file.  We verify
+// this stays true in a unit test.
+message TestAllTypesProto2 {
+  message NestedMessage {
+    optional int32 a = 1;
+    optional TestAllTypesProto2 corecursive = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 0;
+    BAR = 1;
+    BAZ = 2;
+    NEG = -1;  // Intentionally negative.
+  }
+
+  // Singular
+  optional int32 optional_int32    =  1;
+  optional int64 optional_int64    =  2;
+  optional uint32 optional_uint32   =  3;
+  optional uint64 optional_uint64   =  4;
+  optional sint32 optional_sint32   =  5;
+  optional sint64 optional_sint64   =  6;
+  optional fixed32 optional_fixed32  =  7;
+  optional fixed64 optional_fixed64  =  8;
+  optional sfixed32 optional_sfixed32 =  9;
+  optional sfixed64 optional_sfixed64 = 10;
+  optional float optional_float    = 11;
+  optional double optional_double   = 12;
+  optional bool optional_bool     = 13;
+  optional string optional_string   = 14;
+  optional bytes optional_bytes    = 15;
+
+  optional NestedMessage                        optional_nested_message  = 18;
+  optional ForeignMessage                       optional_foreign_message = 19;
+
+  optional NestedEnum                           optional_nested_enum     = 21;
+  optional ForeignEnum                          optional_foreign_enum    = 22;
+
+  optional string optional_string_piece = 24 [ctype=STRING_PIECE];
+  optional string optional_cord = 25 [ctype=CORD];
+
+  optional TestAllTypesProto2 recursive_message = 27;
+
+  // Repeated
+  repeated    int32 repeated_int32    = 31;
+  repeated    int64 repeated_int64    = 32;
+  repeated   uint32 repeated_uint32   = 33;
+  repeated   uint64 repeated_uint64   = 34;
+  repeated   sint32 repeated_sint32   = 35;
+  repeated   sint64 repeated_sint64   = 36;
+  repeated  fixed32 repeated_fixed32  = 37;
+  repeated  fixed64 repeated_fixed64  = 38;
+  repeated sfixed32 repeated_sfixed32 = 39;
+  repeated sfixed64 repeated_sfixed64 = 40;
+  repeated    float repeated_float    = 41;
+  repeated   double repeated_double   = 42;
+  repeated     bool repeated_bool     = 43;
+  repeated   string repeated_string   = 44;
+  repeated    bytes repeated_bytes    = 45;
+
+  repeated NestedMessage       repeated_nested_message  = 48;
+  repeated ForeignMessage      repeated_foreign_message = 49;
+
+  repeated NestedEnum          repeated_nested_enum     = 51;
+  repeated ForeignEnum         repeated_foreign_enum    = 52;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  // Map
+  map <   int32, int32>    map_int32_int32 = 56;
+  map <   int64, int64>    map_int64_int64 = 57;
+  map <  uint32, uint32>   map_uint32_uint32 = 58;
+  map <  uint64, uint64>   map_uint64_uint64 = 59;
+  map <  sint32, sint32>   map_sint32_sint32 = 60;
+  map <  sint64, sint64>   map_sint64_sint64 = 61;
+  map < fixed32, fixed32>  map_fixed32_fixed32 = 62;
+  map < fixed64, fixed64>  map_fixed64_fixed64 = 63;
+  map <sfixed32, sfixed32> map_sfixed32_sfixed32 = 64;
+  map <sfixed64, sfixed64> map_sfixed64_sfixed64 = 65;
+  map <   int32, float>    map_int32_float = 66;
+  map <   int32, double>   map_int32_double = 67;
+  map <    bool, bool>     map_bool_bool = 68;
+  map <  string, string>   map_string_string = 69;
+  map <  string, bytes>    map_string_bytes = 70;
+  map <  string, NestedMessage>  map_string_nested_message = 71;
+  map <  string, ForeignMessage> map_string_foreign_message = 72;
+  map <  string, NestedEnum>     map_string_nested_enum = 73;
+  map <  string, ForeignEnum>    map_string_foreign_enum = 74;
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 111;
+    NestedMessage oneof_nested_message = 112;
+    string oneof_string = 113;
+    bytes oneof_bytes = 114;
+    bool oneof_bool = 115;
+    uint64 oneof_uint64 = 116;
+    float oneof_float = 117;
+    double oneof_double = 118;
+    NestedEnum oneof_enum = 119;
+  }
+
+  // extensions
+  extensions 120 to 200;
+
+  // groups
+  optional group Data = 201 {
+    optional int32 group_int32 = 202;
+    optional uint32 group_uint32 = 203;
+  };
+
+  // Test field-name-to-JSON-name convention.
+  // (protobuf says names can be any valid C/C++ identifier.)
+  optional int32 fieldname1 = 401;
+  optional int32 field_name2 = 402;
+  optional int32 _field_name3 = 403;
+  optional int32 field__name4_ = 404;
+  optional int32 field0name5 = 405;
+  optional int32 field_0_name6 = 406;
+  optional int32 fieldName7 = 407;
+  optional int32 FieldName8 = 408;
+  optional int32 field_Name9 = 409;
+  optional int32 Field_Name10 = 410;
+  optional int32 FIELD_NAME11 = 411;
+  optional int32 FIELD_name12 = 412;
+  optional int32 __field_name13 = 413;
+  optional int32 __Field_name14 = 414;
+  optional int32 field__name15 = 415;
+  optional int32 field__Name16 = 416;
+  optional int32 field_name17__ = 417;
+  optional int32 Field_name18__ = 418;
+
+  // message_set test case.
+  message MessageSetCorrect {
+    option message_set_wire_format = true;
+    extensions 4 to max;
+  }
+
+  message MessageSetCorrectExtension1 {
+    extend MessageSetCorrect {
+      optional MessageSetCorrectExtension1 message_set_extension = 1547769;
+    }
+    optional string str = 25;
+  }
+
+  message MessageSetCorrectExtension2 {
+    extend MessageSetCorrect {
+      optional MessageSetCorrectExtension2 message_set_extension = 4135312;
+    }
+    optional int32 i = 9;
+  }
+}
+
+message ForeignMessage {
+  optional int32 c = 1;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 0;
+  FOREIGN_BAR = 1;
+  FOREIGN_BAZ = 2;
+}
+
+extend TestAllTypesProto2 {
+  optional int32 extension_int32 = 120;
+}
diff --git a/src/google/protobuf/test_messages_proto3.proto b/src/google/protobuf/test_messages_proto3.proto
index 7923033..84b9da9 100644
--- a/src/google/protobuf/test_messages_proto3.proto
+++ b/src/google/protobuf/test_messages_proto3.proto
@@ -39,6 +39,7 @@
 
 package protobuf_test_messages.proto3;
 option java_package = "com.google.protobuf_test_messages.proto3";
+option objc_class_prefix = "Proto3";
 
 // This is the default, but we specify it here explicitly.
 option optimize_for = SPEED;
@@ -59,10 +60,10 @@
 // submessages of this message.  So for example, a fuzz test of TestAllTypes
 // could trigger bugs that occur in any message type in this file.  We verify
 // this stays true in a unit test.
-message TestAllTypes {
+message TestAllTypesProto3 {
   message NestedMessage {
     int32 a = 1;
-    TestAllTypes corecursive = 2;
+    TestAllTypesProto3 corecursive = 2;
   }
 
   enum NestedEnum {
@@ -98,7 +99,7 @@
   string optional_string_piece = 24 [ctype=STRING_PIECE];
   string optional_cord = 25 [ctype=CORD];
 
-  TestAllTypes recursive_message = 27;
+  TestAllTypesProto3 recursive_message = 27;
 
   // Repeated
   repeated    int32 repeated_int32    = 31;
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index 470512e..f32222b 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -38,24 +38,31 @@
 #ifdef _MSC_VER
 #define WIN32_LEAN_AND_MEAN  // yeah, right
 #include <windows.h>         // Find*File().  :(
-#include <io.h>
-#include <direct.h>
+// #include <direct.h>
 #else
 #include <dirent.h>
 #include <unistd.h>
 #endif
 #include <errno.h>
 
+#include <google/protobuf/stubs/io_win32.h>
+
 namespace google {
 namespace protobuf {
 
 #ifdef _WIN32
-#define mkdir(name, mode) mkdir(name)
 // Windows doesn't have symbolic links.
 #define lstat stat
-#ifndef F_OK
-#define F_OK 00  // not defined by MSVC for whatever reason
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
 #endif
+
+#ifdef _MSC_VER
+using google::protobuf::internal::win32::access;
+using google::protobuf::internal::win32::chdir;
+using google::protobuf::internal::win32::fopen;
+using google::protobuf::internal::win32::mkdir;
+using google::protobuf::internal::win32::stat;
 #endif
 
 bool File::Exists(const string& name) {
@@ -113,6 +120,9 @@
 }
 
 bool File::CreateDir(const string& name, int mode) {
+  if (!name.empty()) {
+    GOOGLE_CHECK_OK(name.back() != '.');
+  }
   return mkdir(name.c_str(), mode) == 0;
 }
 
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index d45706b..33a75ed 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -33,14 +33,14 @@
 
 #include <google/protobuf/testing/googletest.h>
 #include <google/protobuf/testing/file.h>
+#include <google/protobuf/stubs/io_win32.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <errno.h>
 #include <stdlib.h>
 #ifdef _MSC_VER
-#include <io.h>
-#include <direct.h>
+// #include <direct.h>
 #else
 #include <unistd.h>
 #endif
@@ -52,8 +52,14 @@
 namespace google {
 namespace protobuf {
 
-#ifdef _WIN32
-#define mkdir(name, mode) mkdir(name)
+#ifdef _MSC_VER
+// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
+// them like we do below.
+using google::protobuf::internal::win32::close;
+using google::protobuf::internal::win32::dup2;
+using google::protobuf::internal::win32::dup;
+using google::protobuf::internal::win32::mkdir;
+using google::protobuf::internal::win32::open;
 #endif
 
 #ifndef O_BINARY
@@ -111,14 +117,32 @@
   char b[L_tmpnam + 1];     // HPUX multithread return 0 if s is 0
   string result = tmpnam(b);
 #ifdef _WIN32
+  // Avoid a trailing dot by changing it to an underscore. On Win32 the names of
+  // files and directories can, but should not, end with dot.
+  //
+  // In MS-DOS and FAT16 filesystem the filenames were 8dot3 style so it didn't
+  // make sense to have a name ending in dot without an extension, so the shell
+  // silently ignored trailing dots. To this day the Win32 API still maintains
+  // this behavior and silently ignores trailing dots in path arguments of
+  // functions such as CreateFile{A,W}. Even POSIX API function implementations
+  // seem to wrap the Win32 API functions (e.g. CreateDirectoryA) and behave
+  // this way.
+  // It's possible to avoid this behavior and create files / directories with
+  // trailing dots (using CreateFileW / CreateDirectoryW and prefixing the path
+  // with "\\?\") but these will be degenerate in the sense that you cannot
+  // chdir into such directories (or navigate into them with Windows Explorer)
+  // nor can you open such files with some programs (e.g. Notepad).
+  if (result.back() == '.') {
+    result[result.size() - 1] = '_';
+  }
   // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed
   // to be used in the current working directory.  WTF?
   if (HasPrefixString(result, "\\")) {
     result.erase(0, 1);
   }
-  // The Win32 API accepts forward slashes as a path delimiter even though
-  // backslashes are standard.  Let's avoid confusion and use only forward
-  // slashes.
+  // The Win32 API accepts forward slashes as a path delimiter as long as the
+  // path doesn't use the "\\?\" prefix.
+  // Let's avoid confusion and use only forward slashes.
   result = StringReplace(result, "\\", "/", true);
 #endif  // _WIN32
   return result;
diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h
index c0d99e6..2db3bfe 100644
--- a/src/google/protobuf/testing/googletest.h
+++ b/src/google/protobuf/testing/googletest.h
@@ -37,9 +37,10 @@
 #include <map>
 #include <vector>
 #include <google/protobuf/stubs/common.h>
-
+#include <gmock/gmock.h>
 // Disable death tests if we use exceptions in CHECK().
-#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST)
+#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) && \
+    !GTEST_OS_WINDOWS
 #define PROTOBUF_HAS_DEATH_TEST
 #endif
 
@@ -85,7 +86,7 @@
   const vector<string>& GetMessages(LogLevel error);
 
  private:
-  map<LogLevel, vector<string> > messages_;
+  std::map<LogLevel, vector<string> > messages_;
   LogHandler* old_handler_;
 
   static void HandleLog(LogLevel level, const char* filename, int line,
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 04c887e..f1d2e8b 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -42,20 +42,21 @@
 
 #include <google/protobuf/text_format.h>
 
+#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/any.h>
+#include <google/protobuf/io/strtod.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/tokenizer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/io/strtod.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/any.h>
-#include <google/protobuf/stubs/stringprintf.h>
+#include <google/protobuf/wire_format_lite.h>
 #include <google/protobuf/stubs/strutil.h>
+
 #include <google/protobuf/stubs/map_util.h>
 #include <google/protobuf/stubs/stl_util.h>
 
@@ -364,7 +365,7 @@
     const Descriptor* descriptor = message->GetDescriptor();
 
     string field_name;
-
+    bool reserved_field = false;
     const FieldDescriptor* field = NULL;
     int start_line = tokenizer_.current().line;
     int start_column = tokenizer_.current().column;
@@ -426,6 +427,8 @@
       if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
         if (descriptor->IsExtensionNumber(field_number)) {
           field = reflection->FindKnownExtensionByNumber(field_number);
+        } else if (descriptor->IsReservedNumber(field_number)) {
+          reserved_field = true;
         } else {
           field = descriptor->FindFieldByNumber(field_number);
         }
@@ -454,9 +457,13 @@
           LowerString(&lower_field_name);
           field = descriptor->FindFieldByLowercaseName(lower_field_name);
         }
+
+        if (field == NULL) {
+          reserved_field = descriptor->IsReservedName(field_name);
+        }
       }
 
-      if (field == NULL) {
+      if (field == NULL && !reserved_field) {
         if (!allow_unknown_field_) {
           ReportError("Message type \"" + descriptor->full_name() +
                       "\" has no field named \"" + field_name + "\".");
@@ -468,9 +475,10 @@
       }
     }
 
-    // Skips unknown field.
+    // Skips unknown or reserved fields.
     if (field == NULL) {
-      GOOGLE_CHECK(allow_unknown_field_);
+      GOOGLE_CHECK(allow_unknown_field_ || reserved_field);
+
       // Try to guess the type of this field.
       // If this field is not a message, there should be a ":" between the
       // field name and the field value and also the field value should not
@@ -1147,7 +1155,8 @@
 // ===========================================================================
 // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted
 // from the Printer found in //google/protobuf/io/printer.h
-class TextFormat::Printer::TextGenerator {
+class TextFormat::Printer::TextGenerator
+    : public TextFormat::BaseTextGenerator {
  public:
   explicit TextGenerator(io::ZeroCopyOutputStream* output,
                          int initial_indent_level)
@@ -1156,9 +1165,8 @@
       buffer_size_(0),
       at_start_of_line_(true),
       failed_(false),
-      indent_(""),
+      indent_level_(initial_indent_level),
       initial_indent_level_(initial_indent_level) {
-    indent_.resize(initial_indent_level_ * 2, ' ');
   }
 
   ~TextGenerator() {
@@ -1173,50 +1181,45 @@
   // inserted at the beginning of each line of text.  Indent() may be called
   // multiple times to produce deeper indents.
   void Indent() {
-    indent_ += "  ";
+    ++indent_level_;
   }
 
   // Reduces the current indent level by two spaces, or crashes if the indent
   // level is zero.
   void Outdent() {
-    if (indent_.empty() ||
-        indent_.size() < initial_indent_level_ * 2) {
+    if (indent_level_ == 0 ||
+        indent_level_ < initial_indent_level_) {
       GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
       return;
     }
 
-    indent_.resize(indent_.size() - 2);
-  }
-
-  // Print text to the output stream.
-  void Print(const string& str) {
-    Print(str.data(), str.size());
-  }
-
-  // Print text to the output stream.
-  void Print(const char* text) {
-    Print(text, strlen(text));
+    --indent_level_;
   }
 
   // Print text to the output stream.
   void Print(const char* text, size_t size) {
-    size_t pos = 0;  // The number of bytes we've written so far.
+    if (indent_level_ > 0) {
+      size_t pos = 0;  // The number of bytes we've written so far.
+      for (size_t i = 0; i < size; i++) {
+        if (text[i] == '\n') {
+          // Saw newline.  If there is more text, we may need to insert an
+          // indent here.  So, write what we have so far, including the '\n'.
+          Write(text + pos, i - pos + 1);
+          pos = i + 1;
 
-    for (size_t i = 0; i < size; i++) {
-      if (text[i] == '\n') {
-        // Saw newline.  If there is more text, we may need to insert an indent
-        // here.  So, write what we have so far, including the '\n'.
-        Write(text + pos, i - pos + 1);
-        pos = i + 1;
-
-        // Setting this true will cause the next Write() to insert an indent
-        // first.
+          // Setting this true will cause the next Write() to insert an indent
+          // first.
+          at_start_of_line_ = true;
+        }
+      }
+      // Write the rest.
+      Write(text + pos, size - pos);
+    } else {
+      Write(text, size);
+      if (text[size - 1] == '\n') {
         at_start_of_line_ = true;
       }
     }
-
-    // Write the rest.
-    Write(text + pos, size - pos);
   }
 
   // True if any write to the underlying stream failed.  (We don't just
@@ -1234,7 +1237,7 @@
     if (at_start_of_line_) {
       // Insert an indent.
       at_start_of_line_ = false;
-      Write(indent_.data(), indent_.size());
+      WriteIndent();
       if (failed_) return;
     }
 
@@ -1256,13 +1259,35 @@
     buffer_size_ -= size;
   }
 
+  void WriteIndent() {
+    if (indent_level_ == 0) { return; }
+    GOOGLE_DCHECK(!failed_);
+    int size = 2 * indent_level_;
+
+    while (size > buffer_size_) {
+      // Data exceeds space in the buffer. Write what we can and request a new
+      // buffer.
+      memset(buffer_, ' ', buffer_size_);
+      size -= buffer_size_;
+      void* void_buffer;
+      failed_ = !output_->Next(&void_buffer, &buffer_size_);
+      if (failed_) return;
+      buffer_ = reinterpret_cast<char*>(void_buffer);
+    }
+
+    // Buffer is big enough to receive the data; copy it.
+    memset(buffer_, ' ', size);
+    buffer_ += size;
+    buffer_size_ -= size;
+  }
+
   io::ZeroCopyOutputStream* const output_;
   char* buffer_;
   int buffer_size_;
   bool at_start_of_line_;
   bool failed_;
 
-  string indent_;
+  int indent_level_;
   int initial_indent_level_;
 };
 
@@ -1380,90 +1405,274 @@
 
 // ===========================================================================
 
-// The default implementation for FieldValuePrinter. The base class just
-// does simple formatting. That way, deriving classes could decide to fallback
-// to that behavior.
+TextFormat::BaseTextGenerator::~BaseTextGenerator() {}
+
+namespace {
+
+// A BaseTextGenerator that writes to a string.
+class StringBaseTextGenerator : public TextFormat::BaseTextGenerator {
+ public:
+  void Print(const char* text, size_t size) { output_.append(text, size); }
+
+// Some compilers do not support ref-qualifiers even in C++11 mode.
+// Disable the optimization for now and revisit it later.
+#if 0 // LANG_CXX11
+  string Consume() && { return std::move(output_); }
+#else   // !LANG_CXX11
+  const string& Get() { return output_; }
+#endif  // LANG_CXX11
+
+ private:
+  string output_;
+};
+
+}  // namespace
+
+// The default implementation for FieldValuePrinter. We just delegate the
+// implementation to the default FastFieldValuePrinter to avoid duplicating the
+// logic.
 TextFormat::FieldValuePrinter::FieldValuePrinter() {}
 TextFormat::FieldValuePrinter::~FieldValuePrinter() {}
+
+#if 0 // LANG_CXX11
+#define FORWARD_IMPL(fn, ...)            \
+  StringBaseTextGenerator generator;     \
+  delegate_.fn(__VA_ARGS__, &generator); \
+  return std::move(generator).Consume()
+#else  // !LANG_CXX11
+#define FORWARD_IMPL(fn, ...)            \
+  StringBaseTextGenerator generator;     \
+  delegate_.fn(__VA_ARGS__, &generator); \
+  return generator.Get()
+#endif  // LANG_CXX11
+
 string TextFormat::FieldValuePrinter::PrintBool(bool val) const {
-  return val ? "true" : "false";
+  FORWARD_IMPL(PrintBool, val);
 }
 string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const {
-  return SimpleItoa(val);
+  FORWARD_IMPL(PrintInt32, val);
 }
 string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const {
-  return SimpleItoa(val);
+  FORWARD_IMPL(PrintUInt32, val);
 }
 string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const {
-  return SimpleItoa(val);
+  FORWARD_IMPL(PrintInt64, val);
 }
 string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const {
-  return SimpleItoa(val);
+  FORWARD_IMPL(PrintUInt64, val);
 }
 string TextFormat::FieldValuePrinter::PrintFloat(float val) const {
-  return SimpleFtoa(val);
+  FORWARD_IMPL(PrintFloat, val);
 }
 string TextFormat::FieldValuePrinter::PrintDouble(double val) const {
-  return SimpleDtoa(val);
+  FORWARD_IMPL(PrintDouble, val);
 }
 string TextFormat::FieldValuePrinter::PrintString(const string& val) const {
-  string printed("\"");
-  CEscapeAndAppend(val, &printed);
-  printed.push_back('\"');
-  return printed;
+  FORWARD_IMPL(PrintString, val);
 }
 string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const {
   return PrintString(val);
 }
 string TextFormat::FieldValuePrinter::PrintEnum(int32 val,
                                                 const string& name) const {
-  return name;
+  FORWARD_IMPL(PrintEnum, val, name);
 }
 string TextFormat::FieldValuePrinter::PrintFieldName(
     const Message& message,
     const Reflection* reflection,
     const FieldDescriptor* field) const {
-  if (field->is_extension()) {
-    // We special-case MessageSet elements for compatibility with proto1.
-    if (field->containing_type()->options().message_set_wire_format()
-        && field->type() == FieldDescriptor::TYPE_MESSAGE
-        && field->is_optional()
-        && field->extension_scope() == field->message_type()) {
-      return StrCat("[", field->message_type()->full_name(), "]");
-    } else {
-      return StrCat("[", field->full_name(), "]");
-    }
-  } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
-    // Groups must be serialized with their original capitalization.
-    return field->message_type()->name();
-  } else {
-    return field->name();
-  }
+  FORWARD_IMPL(PrintFieldName, message, reflection, field);
 }
 string TextFormat::FieldValuePrinter::PrintMessageStart(
     const Message& message,
     int field_index,
     int field_count,
     bool single_line_mode) const {
-  return single_line_mode ? " { " : " {\n";
+  FORWARD_IMPL(PrintMessageStart, message, field_index, field_count,
+               single_line_mode);
 }
 string TextFormat::FieldValuePrinter::PrintMessageEnd(
     const Message& message,
     int field_index,
     int field_count,
     bool single_line_mode) const {
-  return single_line_mode ? "} " : "}\n";
+  FORWARD_IMPL(PrintMessageEnd, message, field_index, field_count,
+               single_line_mode);
+}
+#undef FORWARD_IMPL
+
+TextFormat::FastFieldValuePrinter::FastFieldValuePrinter() {}
+TextFormat::FastFieldValuePrinter::~FastFieldValuePrinter() {}
+void TextFormat::FastFieldValuePrinter::PrintBool(
+    bool val, BaseTextGenerator* generator) const {
+  if (val) {
+    generator->PrintLiteral("true");
+  } else {
+    generator->PrintLiteral("false");
+  }
+}
+void TextFormat::FastFieldValuePrinter::PrintInt32(
+    int32 val, BaseTextGenerator* generator) const {
+  generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintUInt32(
+    uint32 val, BaseTextGenerator* generator) const {
+  generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintInt64(
+    int64 val, BaseTextGenerator* generator) const {
+  generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintUInt64(
+    uint64 val, BaseTextGenerator* generator) const {
+  generator->PrintString(SimpleItoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintFloat(
+    float val, BaseTextGenerator* generator) const {
+  generator->PrintString(SimpleFtoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintDouble(
+    double val, BaseTextGenerator* generator) const {
+  generator->PrintString(SimpleDtoa(val));
+}
+void TextFormat::FastFieldValuePrinter::PrintEnum(
+    int32 val, const string& name, BaseTextGenerator* generator) const {
+  generator->PrintString(name);
+}
+
+void TextFormat::FastFieldValuePrinter::PrintString(
+    const string& val, BaseTextGenerator* generator) const {
+  generator->PrintLiteral("\"");
+  generator->PrintString(CEscape(val));
+  generator->PrintLiteral("\"");
+}
+void TextFormat::FastFieldValuePrinter::PrintBytes(
+    const string& val, BaseTextGenerator* generator) const {
+  PrintString(val, generator);
+}
+void TextFormat::FastFieldValuePrinter::PrintFieldName(
+    const Message& message, const Reflection* reflection,
+    const FieldDescriptor* field, BaseTextGenerator* generator) const {
+  if (field->is_extension()) {
+    generator->PrintLiteral("[");
+    // We special-case MessageSet elements for compatibility with proto1.
+    if (field->containing_type()->options().message_set_wire_format() &&
+        field->type() == FieldDescriptor::TYPE_MESSAGE &&
+        field->is_optional() &&
+        field->extension_scope() == field->message_type()) {
+      generator->PrintString(field->message_type()->full_name());
+    } else {
+      generator->PrintString(field->full_name());
+    }
+    generator->PrintLiteral("]");
+  } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    // Groups must be serialized with their original capitalization.
+    generator->PrintString(field->message_type()->name());
+  } else {
+    generator->PrintString(field->name());
+  }
+}
+void TextFormat::FastFieldValuePrinter::PrintMessageStart(
+    const Message& message, int field_index, int field_count,
+    bool single_line_mode, BaseTextGenerator* generator) const {
+  if (single_line_mode) {
+    generator->PrintLiteral(" { ");
+  } else {
+    generator->PrintLiteral(" {\n");
+  }
+}
+void TextFormat::FastFieldValuePrinter::PrintMessageEnd(
+    const Message& message, int field_index, int field_count,
+    bool single_line_mode, BaseTextGenerator* generator) const {
+  if (single_line_mode) {
+    generator->PrintLiteral("} ");
+  } else {
+    generator->PrintLiteral("}\n");
+  }
 }
 
 namespace {
-// Our own specialization: for UTF8 escaped strings.
-class FieldValuePrinterUtf8Escaping : public TextFormat::FieldValuePrinter {
+
+// A legacy compatibility wrapper. Takes ownership of the delegate.
+class FieldValuePrinterWrapper : public TextFormat::FastFieldValuePrinter {
  public:
-  virtual string PrintString(const string& val) const {
-    return StrCat("\"", strings::Utf8SafeCEscape(val), "\"");
+  explicit FieldValuePrinterWrapper(
+      const TextFormat::FieldValuePrinter* delegate)
+      : delegate_(delegate) {}
+
+  void SetDelegate(const TextFormat::FieldValuePrinter* delegate) {
+    delegate_.reset(delegate);
   }
-  virtual string PrintBytes(const string& val) const {
-    return TextFormat::FieldValuePrinter::PrintString(val);
+
+  void PrintBool(bool val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintBool(val));
+  }
+  void PrintInt32(int32 val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintInt32(val));
+  }
+  void PrintUInt32(uint32 val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintUInt32(val));
+  }
+  void PrintInt64(int64 val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintInt64(val));
+  }
+  void PrintUInt64(uint64 val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintUInt64(val));
+  }
+  void PrintFloat(float val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintFloat(val));
+  }
+  void PrintDouble(double val, TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintDouble(val));
+  }
+  void PrintString(const string& val,
+                   TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintString(val));
+  }
+  void PrintBytes(const string& val,
+                  TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintBytes(val));
+  }
+  void PrintEnum(int32 val, const string& name,
+                 TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintEnum(val, name));
+  }
+  void PrintFieldName(const Message& message, const Reflection* reflection,
+                      const FieldDescriptor* field,
+                      TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(
+        delegate_->PrintFieldName(message, reflection, field));
+  }
+  void PrintMessageStart(const Message& message, int field_index,
+                         int field_count, bool single_line_mode,
+                         TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintMessageStart(
+        message, field_index, field_count, single_line_mode));
+  }
+  void PrintMessageEnd(const Message& message, int field_index, int field_count,
+                       bool single_line_mode,
+                       TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintString(delegate_->PrintMessageEnd(
+        message, field_index, field_count, single_line_mode));
+  }
+
+ private:
+  google::protobuf::scoped_ptr<const TextFormat::FieldValuePrinter> delegate_;
+};
+
+// Our own specialization: for UTF8 escaped strings.
+class FastFieldValuePrinterUtf8Escaping
+    : public TextFormat::FastFieldValuePrinter {
+ public:
+  void PrintString(const string& val,
+                   TextFormat::BaseTextGenerator* generator) const {
+    generator->PrintLiteral("\"");
+    generator->PrintString(strings::Utf8SafeCEscape(val));
+    generator->PrintLiteral("\"");
+  }
+  void PrintBytes(const string& val,
+                  TextFormat::BaseTextGenerator* generator) const {
+    return FastFieldValuePrinter::PrintString(val, generator);
   }
 };
 
@@ -1486,19 +1695,39 @@
 }
 
 void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) {
-  SetDefaultFieldValuePrinter(as_utf8
-                              ? new FieldValuePrinterUtf8Escaping()
-                              : new FieldValuePrinter());
+  SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping()
+                                      : new FastFieldValuePrinter());
 }
 
 void TextFormat::Printer::SetDefaultFieldValuePrinter(
     const FieldValuePrinter* printer) {
+  default_field_value_printer_.reset(new FieldValuePrinterWrapper(printer));
+}
+
+void TextFormat::Printer::SetDefaultFieldValuePrinter(
+    const FastFieldValuePrinter* printer) {
   default_field_value_printer_.reset(printer);
 }
 
 bool TextFormat::Printer::RegisterFieldValuePrinter(
     const FieldDescriptor* field,
     const FieldValuePrinter* printer) {
+  if (field == NULL || printer == NULL) {
+    return false;
+  }
+  FieldValuePrinterWrapper* const wrapper =
+      new FieldValuePrinterWrapper(NULL);
+  if (custom_printers_.insert(std::make_pair(field, wrapper)).second) {
+    wrapper->SetDelegate(printer);
+    return true;
+  } else {
+    delete wrapper;
+    return false;
+  }
+}
+
+bool TextFormat::Printer::RegisterFieldValuePrinter(
+    const FieldDescriptor* field, const FastFieldValuePrinter* printer) {
   return field != NULL && printer != NULL &&
          custom_printers_.insert(std::make_pair(field, printer)).second;
 }
@@ -1527,7 +1756,7 @@
                                 io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, initial_indent_level_);
 
-  Print(message, generator);
+  Print(message, &generator);
 
   // Output false if the generator failed internally.
   return !generator.failed();
@@ -1538,7 +1767,7 @@
     io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, initial_indent_level_);
 
-  PrintUnknownFields(unknown_fields, generator);
+  PrintUnknownFields(unknown_fields, &generator);
 
   // Output false if the generator failed internally.
   return !generator.failed();
@@ -1556,7 +1785,7 @@
 }  // namespace
 
 bool TextFormat::Printer::PrintAny(const Message& message,
-                                   TextGenerator& generator) const {
+                                   TextGenerator* generator) const {
   const FieldDescriptor* type_url_field;
   const FieldDescriptor* value_field;
   if (!internal::GetAnyFieldDescriptors(message, &type_url_field,
@@ -1589,20 +1818,21 @@
     GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents";
     return false;
   }
-  generator.Print(StrCat("[", type_url, "]"));
-  const FieldValuePrinter* printer = FindWithDefault(
+  generator->PrintLiteral("[");
+  generator->PrintString(type_url);
+  generator->PrintLiteral("]");
+  const FastFieldValuePrinter* printer = FindWithDefault(
       custom_printers_, value_field, default_field_value_printer_.get());
-  generator.Print(
-      printer->PrintMessageStart(message, -1, 0, single_line_mode_));
-  generator.Indent();
+  printer->PrintMessageStart(message, -1, 0, single_line_mode_, generator);
+  generator->Indent();
   Print(*value_message, generator);
-  generator.Outdent();
-  generator.Print(printer->PrintMessageEnd(message, -1, 0, single_line_mode_));
+  generator->Outdent();
+  printer->PrintMessageEnd(message, -1, 0, single_line_mode_, generator);
   return true;
 }
 
 void TextFormat::Printer::Print(const Message& message,
-                                TextGenerator& generator) const {
+                                TextGenerator* generator) const {
   const Descriptor* descriptor = message.GetDescriptor();
   const Reflection* reflection = message.GetReflection();
   if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ &&
@@ -1634,13 +1864,13 @@
   io::StringOutputStream output_stream(output);
   TextGenerator generator(&output_stream, initial_indent_level_);
 
-  PrintFieldValue(message, message.GetReflection(), field, index, generator);
+  PrintFieldValue(message, message.GetReflection(), field, index, &generator);
 }
 
 void TextFormat::Printer::PrintField(const Message& message,
                                      const Reflection* reflection,
                                      const FieldDescriptor* field,
-                                     TextGenerator& generator) const {
+                                     TextGenerator* generator) const {
   if (use_short_repeated_primitives_ &&
       field->is_repeated() &&
       field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
@@ -1669,92 +1899,88 @@
     PrintFieldName(message, reflection, field, generator);
 
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-      const FieldValuePrinter* printer = FindWithDefault(
+      const FastFieldValuePrinter* printer = FindWithDefault(
           custom_printers_, field, default_field_value_printer_.get());
       const Message& sub_message =
           field->is_repeated()
               ? (is_map ? *map_entries[j]
                         : reflection->GetRepeatedMessage(message, field, j))
               : reflection->GetMessage(message, field);
-      generator.Print(
-          printer->PrintMessageStart(
-              sub_message, field_index, count, single_line_mode_));
-      generator.Indent();
+      printer->PrintMessageStart(sub_message, field_index, count,
+                                 single_line_mode_, generator);
+      generator->Indent();
       Print(sub_message, generator);
-      generator.Outdent();
-      generator.Print(
-          printer->PrintMessageEnd(
-              sub_message, field_index, count, single_line_mode_));
+      generator->Outdent();
+      printer->PrintMessageEnd(sub_message, field_index, count,
+                               single_line_mode_, generator);
     } else {
-      generator.Print(": ");
+      generator->PrintLiteral(": ");
       // Write the field value.
       PrintFieldValue(message, reflection, field, field_index, generator);
       if (single_line_mode_) {
-        generator.Print(" ");
+        generator->PrintLiteral(" ");
       } else {
-        generator.Print("\n");
+        generator->PrintLiteral("\n");
       }
     }
   }
 }
 
 void TextFormat::Printer::PrintShortRepeatedField(
-    const Message& message,
-    const Reflection* reflection,
-    const FieldDescriptor* field,
-    TextGenerator& generator) const {
+    const Message& message, const Reflection* reflection,
+    const FieldDescriptor* field, TextGenerator* generator) const {
   // Print primitive repeated field in short form.
   PrintFieldName(message, reflection, field, generator);
 
   int size = reflection->FieldSize(message, field);
-  generator.Print(": [");
+  generator->PrintLiteral(": [");
   for (int i = 0; i < size; i++) {
-    if (i > 0) generator.Print(", ");
+    if (i > 0) generator->PrintLiteral(", ");
     PrintFieldValue(message, reflection, field, i, generator);
   }
   if (single_line_mode_) {
-    generator.Print("] ");
+    generator->PrintLiteral("] ");
   } else {
-    generator.Print("]\n");
+    generator->PrintLiteral("]\n");
   }
 }
 
 void TextFormat::Printer::PrintFieldName(const Message& message,
                                          const Reflection* reflection,
                                          const FieldDescriptor* field,
-                                         TextGenerator& generator) const {
+                                         TextGenerator* generator) const {
   // if use_field_number_ is true, prints field number instead
   // of field name.
   if (use_field_number_) {
-    generator.Print(SimpleItoa(field->number()));
+    generator->PrintString(SimpleItoa(field->number()));
     return;
   }
 
-  const FieldValuePrinter* printer = FindWithDefault(
+  const FastFieldValuePrinter* printer = FindWithDefault(
       custom_printers_, field, default_field_value_printer_.get());
-  generator.Print(printer->PrintFieldName(message, reflection, field));
+  printer->PrintFieldName(message, reflection, field, generator);
 }
 
-void TextFormat::Printer::PrintFieldValue(
-    const Message& message,
-    const Reflection* reflection,
-    const FieldDescriptor* field,
-    int index,
-    TextGenerator& generator) const {
+void TextFormat::Printer::PrintFieldValue(const Message& message,
+                                          const Reflection* reflection,
+                                          const FieldDescriptor* field,
+                                          int index,
+                                          TextGenerator* generator) const {
   GOOGLE_DCHECK(field->is_repeated() || (index == -1))
       << "Index must be -1 for non-repeated fields";
 
-  const FieldValuePrinter* printer
-      = FindWithDefault(custom_printers_, field,
-                        default_field_value_printer_.get());
+  const FastFieldValuePrinter* printer = FindWithDefault(
+      custom_printers_, field, default_field_value_printer_.get());
 
   switch (field->cpp_type()) {
-#define OUTPUT_FIELD(CPPTYPE, METHOD)                                   \
-    case FieldDescriptor::CPPTYPE_##CPPTYPE:                            \
-      generator.Print(printer->Print##METHOD(field->is_repeated()       \
-               ? reflection->GetRepeated##METHOD(message, field, index) \
-               : reflection->Get##METHOD(message, field)));             \
-        break
+#define OUTPUT_FIELD(CPPTYPE, METHOD)                                \
+  case FieldDescriptor::CPPTYPE_##CPPTYPE:                           \
+    printer->Print##METHOD(                                          \
+        field->is_repeated()                                         \
+            ? reflection->GetRepeated##METHOD(message, field, index) \
+            : reflection->Get##METHOD(message, field),               \
+        generator);                                                  \
+    break
 
     OUTPUT_FIELD( INT32,  Int32);
     OUTPUT_FIELD( INT64,  Int64);
@@ -1780,10 +2006,10 @@
         value_to_print = &truncated_value;
       }
       if (field->type() == FieldDescriptor::TYPE_STRING) {
-        generator.Print(printer->PrintString(*value_to_print));
+        printer->PrintString(*value_to_print, generator);
       } else {
         GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES);
-        generator.Print(printer->PrintBytes(*value_to_print));
+        printer->PrintBytes(*value_to_print, generator);
       }
       break;
     }
@@ -1795,7 +2021,7 @@
       const EnumValueDescriptor* enum_desc =
           field->enum_type()->FindValueByNumber(enum_value);
       if (enum_desc != NULL) {
-        generator.Print(printer->PrintEnum(enum_value, enum_desc->name()));
+        printer->PrintEnum(enum_value, enum_desc->name(), generator);
       } else {
         // Ordinarily, enum_desc should not be null, because proto2 has the
         // invariant that set enum field values must be in-range, but with the
@@ -1803,8 +2029,8 @@
         // it is possible for the user to force an unknown integer value.  So we
         // simply use the integer value itself as the enum value name in this
         // case.
-        generator.Print(printer->PrintEnum(enum_value,
-                                           StringPrintf("%d", enum_value)));
+        printer->PrintEnum(enum_value, StringPrintf("%d", enum_value),
+                           generator);
       }
       break;
     }
@@ -1867,90 +2093,93 @@
 }
 
 void TextFormat::Printer::PrintUnknownFields(
-    const UnknownFieldSet& unknown_fields, TextGenerator& generator) const {
+    const UnknownFieldSet& unknown_fields, TextGenerator* generator) const {
   for (int i = 0; i < unknown_fields.field_count(); i++) {
     const UnknownField& field = unknown_fields.field(i);
     string field_number = SimpleItoa(field.number());
 
     switch (field.type()) {
       case UnknownField::TYPE_VARINT:
-        generator.Print(field_number);
-        generator.Print(": ");
-        generator.Print(SimpleItoa(field.varint()));
+        generator->PrintString(field_number);
+        generator->PrintLiteral(": ");
+        generator->PrintString(SimpleItoa(field.varint()));
         if (single_line_mode_) {
-          generator.Print(" ");
+          generator->PrintLiteral(" ");
         } else {
-          generator.Print("\n");
+          generator->PrintLiteral("\n");
         }
         break;
       case UnknownField::TYPE_FIXED32: {
-        generator.Print(field_number);
-        generator.Print(": 0x");
-        generator.Print(
+        generator->PrintString(field_number);
+        generator->PrintLiteral(": 0x");
+        generator->PrintString(
             StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
         if (single_line_mode_) {
-          generator.Print(" ");
+          generator->PrintLiteral(" ");
         } else {
-          generator.Print("\n");
+          generator->PrintLiteral("\n");
         }
         break;
       }
       case UnknownField::TYPE_FIXED64: {
-        generator.Print(field_number);
-        generator.Print(": 0x");
-        generator.Print(
+        generator->PrintString(field_number);
+        generator->PrintLiteral(": 0x");
+        generator->PrintString(
             StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
         if (single_line_mode_) {
-          generator.Print(" ");
+          generator->PrintLiteral(" ");
         } else {
-          generator.Print("\n");
+          generator->PrintLiteral("\n");
         }
         break;
       }
       case UnknownField::TYPE_LENGTH_DELIMITED: {
-        generator.Print(field_number);
+        generator->PrintString(field_number);
         const string& value = field.length_delimited();
         UnknownFieldSet embedded_unknown_fields;
         if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) {
           // This field is parseable as a Message.
           // So it is probably an embedded message.
           if (single_line_mode_) {
-            generator.Print(" { ");
+            generator->PrintLiteral(" { ");
           } else {
-            generator.Print(" {\n");
-            generator.Indent();
+            generator->PrintLiteral(" {\n");
+            generator->Indent();
           }
           PrintUnknownFields(embedded_unknown_fields, generator);
           if (single_line_mode_) {
-            generator.Print("} ");
+            generator->PrintLiteral("} ");
           } else {
-            generator.Outdent();
-            generator.Print("}\n");
+            generator->Outdent();
+            generator->PrintLiteral("}\n");
           }
         } else {
           // This field is not parseable as a Message.
           // So it is probably just a plain string.
-          string printed(": \"");
-          CEscapeAndAppend(value, &printed);
-          printed.append(single_line_mode_ ? "\" " : "\"\n");
-          generator.Print(printed);
+          generator->PrintLiteral(": \"");
+          generator->PrintString(CEscape(value));
+          if (single_line_mode_) {
+            generator->PrintLiteral("\" ");
+          } else {
+            generator->PrintLiteral("\"\n");
+          }
         }
         break;
       }
       case UnknownField::TYPE_GROUP:
-        generator.Print(field_number);
+        generator->PrintString(field_number);
         if (single_line_mode_) {
-          generator.Print(" { ");
+          generator->PrintLiteral(" { ");
         } else {
-          generator.Print(" {\n");
-          generator.Indent();
+          generator->PrintLiteral(" {\n");
+          generator->Indent();
         }
         PrintUnknownFields(field.group(), generator);
         if (single_line_mode_) {
-          generator.Print("} ");
+          generator->PrintLiteral("} ");
         } else {
-          generator.Outdent();
-          generator.Print("}\n");
+          generator->Outdent();
+          generator->PrintLiteral("}\n");
         }
         break;
     }
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index 560fd39..cd0e307 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -65,21 +65,22 @@
 class LIBPROTOBUF_EXPORT TextFormat {
  public:
   // Outputs a textual representation of the given message to the given
-  // output stream.
+  // output stream. Returns false if printing fails.
   static bool Print(const Message& message, io::ZeroCopyOutputStream* output);
 
   // Print the fields in an UnknownFieldSet.  They are printed by tag number
   // only.  Embedded messages are heuristically identified by attempting to
-  // parse them.
+  // parse them. Returns false if printing fails.
   static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields,
                                  io::ZeroCopyOutputStream* output);
 
   // Like Print(), but outputs directly to a string.
   // Note: output will be cleared prior to printing, and will be left empty
-  // even if printing fails.
+  // even if printing fails. Returns false if printing fails.
   static bool PrintToString(const Message& message, string* output);
 
-  // Like PrintUnknownFields(), but outputs directly to a string.
+  // Like PrintUnknownFields(), but outputs directly to a string. Returns false
+  // if printing fails.
   static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields,
                                          string* output);
 
@@ -92,11 +93,57 @@
                                       int index,
                                       string* output);
 
-  // The default printer that converts scalar values from fields into
-  // their string representation.
-  // You can derive from this FieldValuePrinter if you want to have
-  // fields to be printed in a different way and register it at the
-  // Printer.
+  class LIBPROTOBUF_EXPORT BaseTextGenerator {
+   public:
+    virtual ~BaseTextGenerator();
+    // Print text to the output stream.
+    virtual void Print(const char* text, size_t size) = 0;
+
+    void PrintString(const string& str) { Print(str.data(), str.size()); }
+
+    template <size_t n>
+    void PrintLiteral(const char (&text)[n]) {
+      Print(text, n - 1);  // n includes the terminating zero character.
+    }
+  };
+
+  // The default printer that converts scalar values from fields into their
+  // string representation.
+  // You can derive from this FastFieldValuePrinter if you want to have fields
+  // to be printed in a different way and register it at the Printer.
+  class LIBPROTOBUF_EXPORT FastFieldValuePrinter {
+   public:
+    FastFieldValuePrinter();
+    virtual ~FastFieldValuePrinter();
+    virtual void PrintBool(bool val, BaseTextGenerator* generator) const;
+    virtual void PrintInt32(int32 val, BaseTextGenerator* generator) const;
+    virtual void PrintUInt32(uint32 val, BaseTextGenerator* generator) const;
+    virtual void PrintInt64(int64 val, BaseTextGenerator* generator) const;
+    virtual void PrintUInt64(uint64 val, BaseTextGenerator* generator) const;
+    virtual void PrintFloat(float val, BaseTextGenerator* generator) const;
+    virtual void PrintDouble(double val, BaseTextGenerator* generator) const;
+    virtual void PrintString(const string& val,
+                             BaseTextGenerator* generator) const;
+    virtual void PrintBytes(const string& val,
+                            BaseTextGenerator* generator) const;
+    virtual void PrintEnum(int32 val, const string& name,
+                           BaseTextGenerator* generator) const;
+    virtual void PrintFieldName(const Message& message,
+                                const Reflection* reflection,
+                                const FieldDescriptor* field,
+                                BaseTextGenerator* generator) const;
+    virtual void PrintMessageStart(const Message& message, int field_index,
+                                   int field_count, bool single_line_mode,
+                                   BaseTextGenerator* generator) const;
+    virtual void PrintMessageEnd(const Message& message, int field_index,
+                                 int field_count, bool single_line_mode,
+                                 BaseTextGenerator* generator) const;
+
+   private:
+    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter);
+  };
+
+// DEPRECATED: Please use FastFieldValuePrinter.
   class LIBPROTOBUF_EXPORT FieldValuePrinter {
    public:
     FieldValuePrinter();
@@ -124,6 +171,7 @@
                                    bool single_line_mode) const;
 
    private:
+    FastFieldValuePrinter delegate_;
     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter);
   };
 
@@ -183,12 +231,13 @@
     // Set true to output UTF-8 instead of ASCII.  The only difference
     // is that bytes >= 0x80 in string fields will not be escaped,
     // because they are assumed to be part of UTF-8 multi-byte
-    // sequences. This will change the default FieldValuePrinter.
+    // sequences. This will change the default FastFieldValuePrinter.
     void SetUseUtf8StringEscaping(bool as_utf8);
 
-    // Set the default FieldValuePrinter that is used for all fields that
+    // Set the default (Fast)FieldValuePrinter that is used for all fields that
     // don't have a field-specific printer registered.
     // Takes ownership of the printer.
+    void SetDefaultFieldValuePrinter(const FastFieldValuePrinter* printer);
     void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer);
 
     // Sets whether we want to hide unknown fields or not.
@@ -233,13 +282,15 @@
       truncate_string_field_longer_than_ = truncate_string_field_longer_than;
     }
 
-    // Register a custom field-specific FieldValuePrinter for fields
+    // Register a custom field-specific (Fast)FieldValuePrinter for fields
     // with a particular FieldDescriptor.
     // Returns "true" if the registration succeeded, or "false", if there is
     // already a printer for that FieldDescriptor.
     // Takes ownership of the printer on successful registration.
     bool RegisterFieldValuePrinter(const FieldDescriptor* field,
                                    const FieldValuePrinter* printer);
+    bool RegisterFieldValuePrinter(const FieldDescriptor* field,
+                                   const FastFieldValuePrinter* printer);
 
    private:
     // Forward declaration of an internal class used to print the text
@@ -248,43 +299,38 @@
 
     // Internal Print method, used for writing to the OutputStream via
     // the TextGenerator class.
-    void Print(const Message& message,
-               TextGenerator& generator) const;
+    void Print(const Message& message, TextGenerator* generator) const;
 
     // Print a single field.
-    void PrintField(const Message& message,
-                    const Reflection* reflection,
+    void PrintField(const Message& message, const Reflection* reflection,
                     const FieldDescriptor* field,
-                    TextGenerator& generator) const;
+                    TextGenerator* generator) const;
 
     // Print a repeated primitive field in short form.
     void PrintShortRepeatedField(const Message& message,
                                  const Reflection* reflection,
                                  const FieldDescriptor* field,
-                                 TextGenerator& generator) const;
+                                 TextGenerator* generator) const;
 
     // Print the name of a field -- i.e. everything that comes before the
     // ':' for a single name/value pair.
-    void PrintFieldName(const Message& message,
-                        const Reflection* reflection,
+    void PrintFieldName(const Message& message, const Reflection* reflection,
                         const FieldDescriptor* field,
-                        TextGenerator& generator) const;
+                        TextGenerator* generator) const;
 
     // Outputs a textual representation of the value of the field supplied on
     // the message supplied or the default value if not set.
-    void PrintFieldValue(const Message& message,
-                         const Reflection* reflection,
-                         const FieldDescriptor* field,
-                         int index,
-                         TextGenerator& generator) const;
+    void PrintFieldValue(const Message& message, const Reflection* reflection,
+                         const FieldDescriptor* field, int index,
+                         TextGenerator* generator) const;
 
     // Print the fields in an UnknownFieldSet.  They are printed by tag number
     // only.  Embedded messages are heuristically identified by attempting to
     // parse them.
     void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
-                            TextGenerator& generator) const;
+                            TextGenerator* generator) const;
 
-    bool PrintAny(const Message& message, TextGenerator& generator) const;
+    bool PrintAny(const Message& message, TextGenerator* generator) const;
 
     int initial_indent_level_;
 
@@ -302,9 +348,9 @@
 
     int64 truncate_string_field_longer_than_;
 
-    google::protobuf::scoped_ptr<const FieldValuePrinter> default_field_value_printer_;
-    typedef std::map<const FieldDescriptor*,
-                     const FieldValuePrinter*> CustomPrinterMap;
+    google::protobuf::scoped_ptr<const FastFieldValuePrinter> default_field_value_printer_;
+    typedef std::map<const FieldDescriptor*, const FastFieldValuePrinter*>
+        CustomPrinterMap;
     CustomPrinterMap custom_printers_;
   };
 
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 422a86b..f823bcb 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -53,6 +53,7 @@
 #include <google/protobuf/unittest_mset_wire_format.pb.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>
@@ -454,13 +455,29 @@
   EXPECT_EQ("optional_int32: value-is(42)\nrepeated_int32: 42\n", text);
 }
 
+TEST_F(TextFormatTest, FieldSpecificCustomPrinterRegisterSameFieldTwice) {
+  protobuf_unittest::TestAllTypes message;
+  TextFormat::Printer printer;
+  const FieldDescriptor* const field =
+      message.GetDescriptor()->FindFieldByName("optional_int32");
+  ASSERT_TRUE(printer.RegisterFieldValuePrinter(
+      field, new CustomInt32FieldValuePrinter()));
+  const TextFormat::FieldValuePrinter* const rejected =
+      new CustomInt32FieldValuePrinter();
+  ASSERT_FALSE(printer.RegisterFieldValuePrinter(field, rejected));
+  delete rejected;
+}
+
 TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) {
   protobuf_unittest::TestAllTypes message;
   TextFormat::Printer printer;
   // NULL printer.
   EXPECT_FALSE(printer.RegisterFieldValuePrinter(
       message.GetDescriptor()->FindFieldByName("optional_int32"),
-      NULL));
+      static_cast<const TextFormat::FieldValuePrinter*>(NULL)));
+  EXPECT_FALSE(printer.RegisterFieldValuePrinter(
+      message.GetDescriptor()->FindFieldByName("optional_int32"),
+      static_cast<const TextFormat::FastFieldValuePrinter*>(NULL)));
   // Because registration fails, the ownership of this printer is never taken.
   TextFormat::FieldValuePrinter my_field_printer;
   // NULL field
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index b2fe28a..44ddc74 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -19,7 +19,10 @@
 
 namespace google {
 namespace protobuf {
-class TimestampDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Timestamp> {
+class TimestampDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Timestamp>
+     _instance;
 } _Timestamp_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto {
@@ -32,20 +35,20 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -54,8 +57,7 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, seconds_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Timestamp, nanos_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Timestamp)},
 };
 
@@ -85,26 +87,22 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Timestamp_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _Timestamp_default_instance_.DefaultConstruct();
-}
+  _Timestamp_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Timestamp_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\037google/protobuf/timestamp.proto\022\017googl"
       "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003"
       "\022\r\n\005nanos\030\002 \001(\005B~\n\023com.google.protobufB\016"
@@ -116,14 +114,14 @@
       descriptor, 231);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/timestamp.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -151,9 +149,7 @@
 Timestamp::Timestamp(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2ftimestamp_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp)
@@ -164,14 +160,15 @@
       _cached_size_(0) {
   _internal_metadata_.MergeFrom(from._internal_metadata_);
   ::memcpy(&seconds_, &from.seconds_,
-    reinterpret_cast<char*>(&nanos_) -
-    reinterpret_cast<char*>(&seconds_) + sizeof(nanos_));
+    static_cast<size_t>(reinterpret_cast<char*>(&nanos_) -
+    reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp)
 }
 
 void Timestamp::SharedCtor() {
-  ::memset(&seconds_, 0, reinterpret_cast<char*>(&nanos_) -
-    reinterpret_cast<char*>(&seconds_) + sizeof(nanos_));
+  ::memset(&seconds_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&nanos_) -
+      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
   _cached_size_ = 0;
 }
 
@@ -182,6 +179,7 @@
 
 void Timestamp::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -215,8 +213,14 @@
 
 void Timestamp::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp)
-  ::memset(&seconds_, 0, reinterpret_cast<char*>(&nanos_) -
-    reinterpret_cast<char*>(&seconds_) + sizeof(nanos_));
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  ::memset(&seconds_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&nanos_) -
+      reinterpret_cast<char*>(&seconds_)) + sizeof(nanos_));
+  _internal_metadata_.Clear();
 }
 
 bool Timestamp::MergePartialFromCodedStream(
@@ -232,7 +236,7 @@
       // int64 seconds = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
@@ -246,7 +250,7 @@
       // int32 nanos = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -259,12 +263,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -294,11 +297,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Timestamp)
 }
 
 ::google::protobuf::uint8* Timestamp::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -313,6 +321,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp)
   return target;
 }
@@ -321,6 +333,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // int64 seconds = 1;
   if (this->seconds() != 0) {
     total_size += 1 +
@@ -410,9 +427,11 @@
   InternalSwap(other);
 }
 void Timestamp::InternalSwap(Timestamp* other) {
-  std::swap(seconds_, other->seconds_);
-  std::swap(nanos_, other->nanos_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(seconds_, other->seconds_);
+  swap(nanos_, other->nanos_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Timestamp::GetMetadata() const {
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 9847854..61596ed 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -48,8 +48,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -68,7 +69,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Timestamp(Timestamp&& from) noexcept
+    : Timestamp() {
+    *this = ::std::move(from);
+  }
 
+  inline Timestamp& operator=(Timestamp&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -87,6 +102,9 @@
 
   void UnsafeArenaSwap(Timestamp* other);
   void Swap(Timestamp* other);
+  friend void swap(Timestamp& a, Timestamp& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -149,7 +167,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::int64 seconds_;
@@ -163,6 +181,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Timestamp
 
 // int64 seconds = 1;
@@ -193,6 +215,9 @@
   // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 
 // @@protoc_insertion_point(namespace_scope)
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 8f017a8..abb5239 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -19,15 +19,30 @@
 
 namespace google {
 namespace protobuf {
-class TypeDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Type> {
+class TypeDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Type>
+     _instance;
 } _Type_default_instance_;
-class FieldDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Field> {
+class FieldDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Field>
+     _instance;
 } _Field_default_instance_;
-class EnumDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Enum> {
+class EnumDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Enum>
+     _instance;
 } _Enum_default_instance_;
-class EnumValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<EnumValue> {
+class EnumValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<EnumValue>
+     _instance;
 } _EnumValue_default_instance_;
-class OptionDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Option> {
+class OptionDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Option>
+     _instance;
 } _Option_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2ftype_2eproto {
@@ -41,24 +56,24 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Type, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -111,8 +126,7 @@
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, name_),
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Option, value_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(Type)},
   { 11, -1, sizeof(Field)},
   { 26, -1, sizeof(Enum)},
@@ -150,36 +164,27 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _Type_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-  _Field_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _Enum_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-  _EnumValue_default_instance_.Shutdown();
-  delete file_level_metadata[3].reflection;
-  _Option_default_instance_.Shutdown();
-  delete file_level_metadata[4].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
   ::google::protobuf::protobuf_google_2fprotobuf_2fany_2eproto::InitDefaults();
   ::google::protobuf::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::InitDefaults();
-  _Type_default_instance_.DefaultConstruct();
-  _Field_default_instance_.DefaultConstruct();
-  _Enum_default_instance_.DefaultConstruct();
-  _EnumValue_default_instance_.DefaultConstruct();
-  _Option_default_instance_.DefaultConstruct();
-  _Type_default_instance_.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>(
+  _Type_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Type_default_instance_);_Field_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Field_default_instance_);_Enum_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Enum_default_instance_);_EnumValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_EnumValue_default_instance_);_Option_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Option_default_instance_);_Type_default_instance_._instance.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>(
       ::google::protobuf::SourceContext::internal_default_instance());
-  _Enum_default_instance_.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>(
+  _Enum_default_instance_._instance.get_mutable()->source_context_ = const_cast< ::google::protobuf::SourceContext*>(
       ::google::protobuf::SourceContext::internal_default_instance());
-  _Option_default_instance_.get_mutable()->value_ = const_cast< ::google::protobuf::Any*>(
+  _Option_default_instance_._instance.get_mutable()->value_ = const_cast< ::google::protobuf::Any*>(
       ::google::protobuf::Any::internal_default_instance());
 }
 
@@ -187,9 +192,10 @@
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\032google/protobuf/type.proto\022\017google.pro"
       "tobuf\032\031google/protobuf/any.proto\032$google"
       "/protobuf/source_context.proto\"\327\001\n\004Type\022"
@@ -237,14 +243,14 @@
     "google/protobuf/type.proto", &protobuf_RegisterTypes);
   ::google::protobuf::protobuf_google_2fprotobuf_2fany_2eproto::AddDescriptors();
   ::google::protobuf::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::AddDescriptors();
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -406,9 +412,7 @@
   fields_(arena),
   oneofs_(arena),
   options_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Type)
@@ -437,8 +441,9 @@
 
 void Type::SharedCtor() {
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&source_context_, 0, reinterpret_cast<char*>(&syntax_) -
-    reinterpret_cast<char*>(&source_context_) + sizeof(syntax_));
+  ::memset(&source_context_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&syntax_) -
+      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
   _cached_size_ = 0;
 }
 
@@ -449,14 +454,13 @@
 
 void Type::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
 
   name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
-  if (this != internal_default_instance()) {
-    delete source_context_;
-  }
+  if (this != internal_default_instance()) delete source_context_;
 }
 
 void Type::ArenaDtor(void* object) {
@@ -486,6 +490,10 @@
 
 void Type::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Type)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   fields_.Clear();
   oneofs_.Clear();
   options_.Clear();
@@ -495,6 +503,7 @@
   }
   source_context_ = NULL;
   syntax_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool Type::MergePartialFromCodedStream(
@@ -510,11 +519,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Type.name"));
         } else {
@@ -526,7 +535,7 @@
       // repeated .google.protobuf.Field fields = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_fields()));
         } else {
@@ -538,12 +547,12 @@
       // repeated string oneofs = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->add_oneofs()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
             this->oneofs(this->oneofs_size() - 1).data(),
-            this->oneofs(this->oneofs_size() - 1).length(),
+            static_cast<int>(this->oneofs(this->oneofs_size() - 1).length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Type.oneofs"));
         } else {
@@ -555,7 +564,7 @@
       // repeated .google.protobuf.Option options = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_options()));
         } else {
@@ -567,7 +576,7 @@
       // .google.protobuf.SourceContext source_context = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(42u)) {
+            static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_source_context()));
         } else {
@@ -579,7 +588,7 @@
       // .google.protobuf.Syntax syntax = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(48u)) {
+            static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -593,12 +602,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -621,7 +629,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Type.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -629,15 +637,16 @@
   }
 
   // repeated .google.protobuf.Field fields = 2;
-  for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->fields_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->fields(i), output);
+      2, this->fields(static_cast<int>(i)), output);
   }
 
   // repeated string oneofs = 3;
   for (int i = 0, n = this->oneofs_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->oneofs(i).data(), this->oneofs(i).length(),
+      this->oneofs(i).data(), static_cast<int>(this->oneofs(i).length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Type.oneofs");
     ::google::protobuf::internal::WireFormatLite::WriteString(
@@ -645,9 +654,10 @@
   }
 
   // repeated .google.protobuf.Option options = 4;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      4, this->options(i), output);
+      4, this->options(static_cast<int>(i)), output);
   }
 
   // .google.protobuf.SourceContext source_context = 5;
@@ -662,11 +672,16 @@
       6, this->syntax(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Type)
 }
 
 ::google::protobuf::uint8* Type::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -674,7 +689,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Type.name");
     target =
@@ -683,16 +698,17 @@
   }
 
   // repeated .google.protobuf.Field fields = 2;
-  for (unsigned int i = 0, n = this->fields_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->fields_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->fields(i), deterministic, target);
+        2, this->fields(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated string oneofs = 3;
   for (int i = 0, n = this->oneofs_size(); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->oneofs(i).data(), this->oneofs(i).length(),
+      this->oneofs(i).data(), static_cast<int>(this->oneofs(i).length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Type.oneofs");
     target = ::google::protobuf::internal::WireFormatLite::
@@ -700,10 +716,11 @@
   }
 
   // repeated .google.protobuf.Option options = 4;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        4, this->options(i), deterministic, target);
+        4, this->options(static_cast<int>(i)), deterministic, target);
   }
 
   // .google.protobuf.SourceContext source_context = 5;
@@ -719,6 +736,10 @@
       6, this->syntax(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Type)
   return target;
 }
@@ -727,14 +748,19 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.Field fields = 2;
   {
-    unsigned int count = this->fields_size();
+    unsigned int count = static_cast<unsigned int>(this->fields_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->fields(i));
+          this->fields(static_cast<int>(i)));
     }
   }
 
@@ -748,12 +774,12 @@
 
   // repeated .google.protobuf.Option options = 4;
   {
-    unsigned int count = this->options_size();
+    unsigned int count = static_cast<unsigned int>(this->options_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->options(i));
+          this->options(static_cast<int>(i)));
     }
   }
 
@@ -858,13 +884,15 @@
   InternalSwap(other);
 }
 void Type::InternalSwap(Type* other) {
+  using std::swap;
   fields_.InternalSwap(&other->fields_);
   oneofs_.InternalSwap(&other->oneofs_);
   options_.InternalSwap(&other->options_);
   name_.Swap(&other->name_);
-  std::swap(source_context_, other->source_context_);
-  std::swap(syntax_, other->syntax_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(source_context_, other->source_context_);
+  swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Type::GetMetadata() const {
@@ -888,6 +916,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
 }
+#if LANG_CXX11
+void Type::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Type.name)
+}
+#endif
 void Type::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1080,9 +1116,10 @@
   source_context_ = NULL;
 }
 const ::google::protobuf::SourceContext& Type::source_context() const {
+  const ::google::protobuf::SourceContext* p = source_context_;
   // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
-  return source_context_ != NULL ? *source_context_
-                         : *::google::protobuf::SourceContext::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceContext*>(
+      &::google::protobuf::_SourceContext_default_instance_);
 }
 ::google::protobuf::SourceContext* Type::mutable_source_context() {
   
@@ -1165,9 +1202,7 @@
   : ::google::protobuf::Message(),
   _internal_metadata_(arena),
   options_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Field)
@@ -1199,8 +1234,8 @@
       GetArenaNoVirtual());
   }
   ::memcpy(&kind_, &from.kind_,
-    reinterpret_cast<char*>(&packed_) -
-    reinterpret_cast<char*>(&kind_) + sizeof(packed_));
+    static_cast<size_t>(reinterpret_cast<char*>(&packed_) -
+    reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Field)
 }
 
@@ -1209,8 +1244,9 @@
   type_url_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   json_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
   default_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&kind_, 0, reinterpret_cast<char*>(&packed_) -
-    reinterpret_cast<char*>(&kind_) + sizeof(packed_));
+  ::memset(&kind_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&packed_) -
+      reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
   _cached_size_ = 0;
 }
 
@@ -1221,6 +1257,7 @@
 
 void Field::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -1258,13 +1295,19 @@
 
 void Field::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Field)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   options_.Clear();
   name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
   type_url_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
   json_name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
   default_value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
-  ::memset(&kind_, 0, reinterpret_cast<char*>(&packed_) -
-    reinterpret_cast<char*>(&kind_) + sizeof(packed_));
+  ::memset(&kind_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&packed_) -
+      reinterpret_cast<char*>(&kind_)) + sizeof(packed_));
+  _internal_metadata_.Clear();
 }
 
 bool Field::MergePartialFromCodedStream(
@@ -1280,7 +1323,7 @@
       // .google.protobuf.Field.Kind kind = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -1295,7 +1338,7 @@
       // .google.protobuf.Field.Cardinality cardinality = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -1310,7 +1353,7 @@
       // int32 number = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(24u)) {
+            static_cast< ::google::protobuf::uint8>(24u /* 24 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -1324,11 +1367,11 @@
       // string name = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Field.name"));
         } else {
@@ -1340,11 +1383,11 @@
       // string type_url = 6;
       case 6: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(50u)) {
+            static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_type_url()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->type_url().data(), this->type_url().length(),
+            this->type_url().data(), static_cast<int>(this->type_url().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Field.type_url"));
         } else {
@@ -1356,7 +1399,7 @@
       // int32 oneof_index = 7;
       case 7: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(56u)) {
+            static_cast< ::google::protobuf::uint8>(56u /* 56 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -1370,7 +1413,7 @@
       // bool packed = 8;
       case 8: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(64u)) {
+            static_cast< ::google::protobuf::uint8>(64u /* 64 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -1384,7 +1427,7 @@
       // repeated .google.protobuf.Option options = 9;
       case 9: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(74u)) {
+            static_cast< ::google::protobuf::uint8>(74u /* 74 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_options()));
         } else {
@@ -1396,11 +1439,11 @@
       // string json_name = 10;
       case 10: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(82u)) {
+            static_cast< ::google::protobuf::uint8>(82u /* 82 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_json_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->json_name().data(), this->json_name().length(),
+            this->json_name().data(), static_cast<int>(this->json_name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Field.json_name"));
         } else {
@@ -1412,11 +1455,11 @@
       // string default_value = 11;
       case 11: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(90u)) {
+            static_cast< ::google::protobuf::uint8>(90u /* 90 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_default_value()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->default_value().data(), this->default_value().length(),
+            this->default_value().data(), static_cast<int>(this->default_value().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Field.default_value"));
         } else {
@@ -1427,12 +1470,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1472,7 +1514,7 @@
   // string name = 4;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1482,7 +1524,7 @@
   // string type_url = 6;
   if (this->type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->type_url().data(), this->type_url().length(),
+      this->type_url().data(), static_cast<int>(this->type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.type_url");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1500,15 +1542,16 @@
   }
 
   // repeated .google.protobuf.Option options = 9;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      9, this->options(i), output);
+      9, this->options(static_cast<int>(i)), output);
   }
 
   // string json_name = 10;
   if (this->json_name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->json_name().data(), this->json_name().length(),
+      this->json_name().data(), static_cast<int>(this->json_name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.json_name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -1518,18 +1561,23 @@
   // string default_value = 11;
   if (this->default_value().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->default_value().data(), this->default_value().length(),
+      this->default_value().data(), static_cast<int>(this->default_value().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.default_value");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
       11, this->default_value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Field)
 }
 
 ::google::protobuf::uint8* Field::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1554,7 +1602,7 @@
   // string name = 4;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.name");
     target =
@@ -1565,7 +1613,7 @@
   // string type_url = 6;
   if (this->type_url().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->type_url().data(), this->type_url().length(),
+      this->type_url().data(), static_cast<int>(this->type_url().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.type_url");
     target =
@@ -1584,16 +1632,17 @@
   }
 
   // repeated .google.protobuf.Option options = 9;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        9, this->options(i), deterministic, target);
+        9, this->options(static_cast<int>(i)), deterministic, target);
   }
 
   // string json_name = 10;
   if (this->json_name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->json_name().data(), this->json_name().length(),
+      this->json_name().data(), static_cast<int>(this->json_name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.json_name");
     target =
@@ -1604,7 +1653,7 @@
   // string default_value = 11;
   if (this->default_value().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->default_value().data(), this->default_value().length(),
+      this->default_value().data(), static_cast<int>(this->default_value().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Field.default_value");
     target =
@@ -1612,6 +1661,10 @@
         11, this->default_value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Field)
   return target;
 }
@@ -1620,14 +1673,19 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.Option options = 9;
   {
-    unsigned int count = this->options_size();
+    unsigned int count = static_cast<unsigned int>(this->options_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->options(i));
+          this->options(static_cast<int>(i)));
     }
   }
 
@@ -1787,17 +1845,19 @@
   InternalSwap(other);
 }
 void Field::InternalSwap(Field* other) {
+  using std::swap;
   options_.InternalSwap(&other->options_);
   name_.Swap(&other->name_);
   type_url_.Swap(&other->type_url_);
   json_name_.Swap(&other->json_name_);
   default_value_.Swap(&other->default_value_);
-  std::swap(kind_, other->kind_);
-  std::swap(cardinality_, other->cardinality_);
-  std::swap(number_, other->number_);
-  std::swap(oneof_index_, other->oneof_index_);
-  std::swap(packed_, other->packed_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(kind_, other->kind_);
+  swap(cardinality_, other->cardinality_);
+  swap(number_, other->number_);
+  swap(oneof_index_, other->oneof_index_);
+  swap(packed_, other->packed_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Field::GetMetadata() const {
@@ -1863,6 +1923,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
 }
+#if LANG_CXX11
+void Field::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.name)
+}
+#endif
 void Field::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1930,6 +1998,14 @@
   type_url_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
 }
+#if LANG_CXX11
+void Field::set_type_url(::std::string&& value) {
+  
+  type_url_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.type_url)
+}
+#endif
 void Field::set_type_url(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -2055,6 +2131,14 @@
   json_name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
 }
+#if LANG_CXX11
+void Field::set_json_name(::std::string&& value) {
+  
+  json_name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.json_name)
+}
+#endif
 void Field::set_json_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -2122,6 +2206,14 @@
   default_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value)
 }
+#if LANG_CXX11
+void Field::set_default_value(::std::string&& value) {
+  
+  default_value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.default_value)
+}
+#endif
 void Field::set_default_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -2234,9 +2326,7 @@
   _internal_metadata_(arena),
   enumvalue_(arena),
   options_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Enum)
@@ -2264,8 +2354,9 @@
 
 void Enum::SharedCtor() {
   name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
-  ::memset(&source_context_, 0, reinterpret_cast<char*>(&syntax_) -
-    reinterpret_cast<char*>(&source_context_) + sizeof(syntax_));
+  ::memset(&source_context_, 0, static_cast<size_t>(
+      reinterpret_cast<char*>(&syntax_) -
+      reinterpret_cast<char*>(&source_context_)) + sizeof(syntax_));
   _cached_size_ = 0;
 }
 
@@ -2276,14 +2367,13 @@
 
 void Enum::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
 
   name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
-  if (this != internal_default_instance()) {
-    delete source_context_;
-  }
+  if (this != internal_default_instance()) delete source_context_;
 }
 
 void Enum::ArenaDtor(void* object) {
@@ -2313,6 +2403,10 @@
 
 void Enum::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Enum)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   enumvalue_.Clear();
   options_.Clear();
   name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
@@ -2321,6 +2415,7 @@
   }
   source_context_ = NULL;
   syntax_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool Enum::MergePartialFromCodedStream(
@@ -2336,11 +2431,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Enum.name"));
         } else {
@@ -2352,7 +2447,7 @@
       // repeated .google.protobuf.EnumValue enumvalue = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_enumvalue()));
         } else {
@@ -2364,7 +2459,7 @@
       // repeated .google.protobuf.Option options = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_options()));
         } else {
@@ -2376,7 +2471,7 @@
       // .google.protobuf.SourceContext source_context = 4;
       case 4: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(34u)) {
+            static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_source_context()));
         } else {
@@ -2388,7 +2483,7 @@
       // .google.protobuf.Syntax syntax = 5;
       case 5: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(40u)) {
+            static_cast< ::google::protobuf::uint8>(40u /* 40 & 0xFF */)) {
           int value;
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
@@ -2402,12 +2497,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -2430,7 +2524,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Enum.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -2438,15 +2532,17 @@
   }
 
   // repeated .google.protobuf.EnumValue enumvalue = 2;
-  for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->enumvalue_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      2, this->enumvalue(i), output);
+      2, this->enumvalue(static_cast<int>(i)), output);
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      3, this->options(i), output);
+      3, this->options(static_cast<int>(i)), output);
   }
 
   // .google.protobuf.SourceContext source_context = 4;
@@ -2461,11 +2557,16 @@
       5, this->syntax(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Enum)
 }
 
 ::google::protobuf::uint8* Enum::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2473,7 +2574,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Enum.name");
     target =
@@ -2482,17 +2583,19 @@
   }
 
   // repeated .google.protobuf.EnumValue enumvalue = 2;
-  for (unsigned int i = 0, n = this->enumvalue_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->enumvalue_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        2, this->enumvalue(i), deterministic, target);
+        2, this->enumvalue(static_cast<int>(i)), deterministic, target);
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        3, this->options(i), deterministic, target);
+        3, this->options(static_cast<int>(i)), deterministic, target);
   }
 
   // .google.protobuf.SourceContext source_context = 4;
@@ -2508,6 +2611,10 @@
       5, this->syntax(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Enum)
   return target;
 }
@@ -2516,25 +2623,30 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.EnumValue enumvalue = 2;
   {
-    unsigned int count = this->enumvalue_size();
+    unsigned int count = static_cast<unsigned int>(this->enumvalue_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->enumvalue(i));
+          this->enumvalue(static_cast<int>(i)));
     }
   }
 
   // repeated .google.protobuf.Option options = 3;
   {
-    unsigned int count = this->options_size();
+    unsigned int count = static_cast<unsigned int>(this->options_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->options(i));
+          this->options(static_cast<int>(i)));
     }
   }
 
@@ -2638,12 +2750,14 @@
   InternalSwap(other);
 }
 void Enum::InternalSwap(Enum* other) {
+  using std::swap;
   enumvalue_.InternalSwap(&other->enumvalue_);
   options_.InternalSwap(&other->options_);
   name_.Swap(&other->name_);
-  std::swap(source_context_, other->source_context_);
-  std::swap(syntax_, other->syntax_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(source_context_, other->source_context_);
+  swap(syntax_, other->syntax_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Enum::GetMetadata() const {
@@ -2667,6 +2781,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
 }
+#if LANG_CXX11
+void Enum::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Enum.name)
+}
+#endif
 void Enum::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -2790,9 +2912,10 @@
   source_context_ = NULL;
 }
 const ::google::protobuf::SourceContext& Enum::source_context() const {
+  const ::google::protobuf::SourceContext* p = source_context_;
   // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
-  return source_context_ != NULL ? *source_context_
-                         : *::google::protobuf::SourceContext::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceContext*>(
+      &::google::protobuf::_SourceContext_default_instance_);
 }
 ::google::protobuf::SourceContext* Enum::mutable_source_context() {
   
@@ -2868,9 +2991,7 @@
   : ::google::protobuf::Message(),
   _internal_metadata_(arena),
   options_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumValue)
@@ -2903,6 +3024,7 @@
 
 void EnumValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -2937,9 +3059,14 @@
 
 void EnumValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   options_.Clear();
   name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
   number_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool EnumValue::MergePartialFromCodedStream(
@@ -2955,11 +3082,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.EnumValue.name"));
         } else {
@@ -2971,7 +3098,7 @@
       // int32 number = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(16u)) {
+            static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -2985,7 +3112,7 @@
       // repeated .google.protobuf.Option options = 3;
       case 3: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(26u)) {
+            static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                 input, add_options()));
         } else {
@@ -2996,12 +3123,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -3024,7 +3150,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.EnumValue.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -3037,16 +3163,22 @@
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
-      3, this->options(i), output);
+      3, this->options(static_cast<int>(i)), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValue)
 }
 
 ::google::protobuf::uint8* EnumValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3054,7 +3186,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.EnumValue.name");
     target =
@@ -3068,12 +3200,17 @@
   }
 
   // repeated .google.protobuf.Option options = 3;
-  for (unsigned int i = 0, n = this->options_size(); i < n; i++) {
+  for (unsigned int i = 0,
+      n = static_cast<unsigned int>(this->options_size()); i < n; i++) {
     target = ::google::protobuf::internal::WireFormatLite::
       InternalWriteMessageNoVirtualToArray(
-        3, this->options(i), deterministic, target);
+        3, this->options(static_cast<int>(i)), deterministic, target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValue)
   return target;
 }
@@ -3082,14 +3219,19 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // repeated .google.protobuf.Option options = 3;
   {
-    unsigned int count = this->options_size();
+    unsigned int count = static_cast<unsigned int>(this->options_size());
     total_size += 1UL * count;
     for (unsigned int i = 0; i < count; i++) {
       total_size +=
         ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
-          this->options(i));
+          this->options(static_cast<int>(i)));
     }
   }
 
@@ -3183,10 +3325,12 @@
   InternalSwap(other);
 }
 void EnumValue::InternalSwap(EnumValue* other) {
+  using std::swap;
   options_.InternalSwap(&other->options_);
   name_.Swap(&other->name_);
-  std::swap(number_, other->number_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(number_, other->number_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata EnumValue::GetMetadata() const {
@@ -3210,6 +3354,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
 }
+#if LANG_CXX11
+void EnumValue::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValue.name)
+}
+#endif
 void EnumValue::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -3361,9 +3513,7 @@
 Option::Option(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2ftype_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Option)
@@ -3399,14 +3549,13 @@
 
 void Option::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
 
   name_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), arena);
-  if (this != internal_default_instance()) {
-    delete value_;
-  }
+  if (this != internal_default_instance()) delete value_;
 }
 
 void Option::ArenaDtor(void* object) {
@@ -3436,11 +3585,16 @@
 
 void Option::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Option)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   name_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
   if (GetArenaNoVirtual() == NULL && value_ != NULL) {
     delete value_;
   }
   value_ = NULL;
+  _internal_metadata_.Clear();
 }
 
 bool Option::MergePartialFromCodedStream(
@@ -3456,11 +3610,11 @@
       // string name = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_name()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->name().data(), this->name().length(),
+            this->name().data(), static_cast<int>(this->name().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.Option.name"));
         } else {
@@ -3472,7 +3626,7 @@
       // .google.protobuf.Any value = 2;
       case 2: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(18u)) {
+            static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
                input, mutable_value()));
         } else {
@@ -3483,12 +3637,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -3511,7 +3664,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Option.name");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
@@ -3524,11 +3677,16 @@
       2, *this->value_, output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Option)
 }
 
 ::google::protobuf::uint8* Option::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -3536,7 +3694,7 @@
   // string name = 1;
   if (this->name().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->name().data(), this->name().length(),
+      this->name().data(), static_cast<int>(this->name().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.Option.name");
     target =
@@ -3551,6 +3709,10 @@
         2, *this->value_, deterministic, target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Option)
   return target;
 }
@@ -3559,6 +3721,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // string name = 1;
   if (this->name().size() > 0) {
     total_size += 1 +
@@ -3648,9 +3815,11 @@
   InternalSwap(other);
 }
 void Option::InternalSwap(Option* other) {
+  using std::swap;
   name_.Swap(&other->name_);
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Option::GetMetadata() const {
@@ -3674,6 +3843,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
 }
+#if LANG_CXX11
+void Option::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Option.name)
+}
+#endif
 void Option::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -3737,9 +3914,10 @@
   value_ = NULL;
 }
 const ::google::protobuf::Any& Option::value() const {
+  const ::google::protobuf::Any* p = value_;
   // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
-  return value_ != NULL ? *value_
-                         : *::google::protobuf::Any::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::Any*>(
+      &::google::protobuf::_Any_default_instance_);
 }
 ::google::protobuf::Any* Option::mutable_value() {
   
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index c1cd416..cc76cc9 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -35,9 +35,6 @@
 // @@protoc_insertion_point(includes)
 namespace google {
 namespace protobuf {
-class Any;
-class AnyDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
 class Enum;
 class EnumDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern EnumDefaultTypeInternal _Enum_default_instance_;
@@ -50,9 +47,6 @@
 class Option;
 class OptionDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern OptionDefaultTypeInternal _Option_default_instance_;
-class SourceContext;
-class SourceContextDefaultTypeInternal;
-LIBPROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
 class Type;
 class TypeDefaultTypeInternal;
 LIBPROTOBUF_EXPORT extern TypeDefaultTypeInternal _Type_default_instance_;
@@ -69,8 +63,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -171,7 +166,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Type(Type&& from) noexcept
+    : Type() {
+    *this = ::std::move(from);
+  }
 
+  inline Type& operator=(Type&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -190,6 +199,9 @@
 
   void UnsafeArenaSwap(Type* other);
   void Swap(Type* other);
+  friend void swap(Type& a, Type& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -287,6 +299,9 @@
   static const int kNameFieldNumber = 1;
   const ::std::string& name() const;
   void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
   void set_name(const char* value);
   void set_name(const char* value, size_t size);
   ::std::string* mutable_name();
@@ -322,7 +337,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::Field > fields_;
@@ -347,7 +362,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Field(Field&& from) noexcept
+    : Field() {
+    *this = ::std::move(from);
+  }
 
+  inline Field& operator=(Field&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -366,6 +395,9 @@
 
   void UnsafeArenaSwap(Field* other);
   void Swap(Field* other);
+  friend void swap(Field& a, Field& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -519,6 +551,9 @@
   static const int kNameFieldNumber = 4;
   const ::std::string& name() const;
   void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
   void set_name(const char* value);
   void set_name(const char* value, size_t size);
   ::std::string* mutable_name();
@@ -533,6 +568,9 @@
   static const int kTypeUrlFieldNumber = 6;
   const ::std::string& type_url() const;
   void set_type_url(const ::std::string& value);
+  #if LANG_CXX11
+  void set_type_url(::std::string&& value);
+  #endif
   void set_type_url(const char* value);
   void set_type_url(const char* value, size_t size);
   ::std::string* mutable_type_url();
@@ -547,6 +585,9 @@
   static const int kJsonNameFieldNumber = 10;
   const ::std::string& json_name() const;
   void set_json_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_json_name(::std::string&& value);
+  #endif
   void set_json_name(const char* value);
   void set_json_name(const char* value, size_t size);
   ::std::string* mutable_json_name();
@@ -561,6 +602,9 @@
   static const int kDefaultValueFieldNumber = 11;
   const ::std::string& default_value() const;
   void set_default_value(const ::std::string& value);
+  #if LANG_CXX11
+  void set_default_value(::std::string&& value);
+  #endif
   void set_default_value(const char* value);
   void set_default_value(const char* value, size_t size);
   ::std::string* mutable_default_value();
@@ -604,7 +648,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
@@ -633,7 +677,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Enum(Enum&& from) noexcept
+    : Enum() {
+    *this = ::std::move(from);
+  }
 
+  inline Enum& operator=(Enum&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -652,6 +710,9 @@
 
   void UnsafeArenaSwap(Enum* other);
   void Swap(Enum* other);
+  friend void swap(Enum& a, Enum& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -727,6 +788,9 @@
   static const int kNameFieldNumber = 1;
   const ::std::string& name() const;
   void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
   void set_name(const char* value);
   void set_name(const char* value, size_t size);
   ::std::string* mutable_name();
@@ -762,7 +826,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValue > enumvalue_;
@@ -786,7 +850,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  EnumValue(EnumValue&& from) noexcept
+    : EnumValue() {
+    *this = ::std::move(from);
+  }
 
+  inline EnumValue& operator=(EnumValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -805,6 +883,9 @@
 
   void UnsafeArenaSwap(EnumValue* other);
   void Swap(EnumValue* other);
+  friend void swap(EnumValue& a, EnumValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -868,6 +949,9 @@
   static const int kNameFieldNumber = 1;
   const ::std::string& name() const;
   void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
   void set_name(const char* value);
   void set_name(const char* value, size_t size);
   ::std::string* mutable_name();
@@ -887,7 +971,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::RepeatedPtrField< ::google::protobuf::Option > options_;
@@ -909,7 +993,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Option(Option&& from) noexcept
+    : Option() {
+    *this = ::std::move(from);
+  }
 
+  inline Option& operator=(Option&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -928,6 +1026,9 @@
 
   void UnsafeArenaSwap(Option* other);
   void Swap(Option* other);
+  friend void swap(Option& a, Option& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -979,6 +1080,9 @@
   static const int kNameFieldNumber = 1;
   const ::std::string& name() const;
   void set_name(const ::std::string& value);
+  #if LANG_CXX11
+  void set_name(::std::string&& value);
+  #endif
   void set_name(const char* value);
   void set_name(const char* value, size_t size);
   ::std::string* mutable_name();
@@ -1008,7 +1112,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::internal::ArenaStringPtr name_;
@@ -1022,6 +1126,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // Type
 
 // string name = 1;
@@ -1037,6 +1145,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
 }
+#if LANG_CXX11
+inline void Type::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Type.name)
+}
+#endif
 inline void Type::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1229,9 +1345,10 @@
   source_context_ = NULL;
 }
 inline const ::google::protobuf::SourceContext& Type::source_context() const {
+  const ::google::protobuf::SourceContext* p = source_context_;
   // @@protoc_insertion_point(field_get:google.protobuf.Type.source_context)
-  return source_context_ != NULL ? *source_context_
-                         : *::google::protobuf::SourceContext::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceContext*>(
+      &::google::protobuf::_SourceContext_default_instance_);
 }
 inline ::google::protobuf::SourceContext* Type::mutable_source_context() {
   
@@ -1344,6 +1461,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
 }
+#if LANG_CXX11
+inline void Field::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.name)
+}
+#endif
 inline void Field::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1411,6 +1536,14 @@
   type_url_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
 }
+#if LANG_CXX11
+inline void Field::set_type_url(::std::string&& value) {
+  
+  type_url_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.type_url)
+}
+#endif
 inline void Field::set_type_url(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1536,6 +1669,14 @@
   json_name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
 }
+#if LANG_CXX11
+inline void Field::set_json_name(::std::string&& value) {
+  
+  json_name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.json_name)
+}
+#endif
 inline void Field::set_json_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1603,6 +1744,14 @@
   default_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value)
 }
+#if LANG_CXX11
+inline void Field::set_default_value(::std::string&& value) {
+  
+  default_value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.default_value)
+}
+#endif
 inline void Field::set_default_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1674,6 +1823,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
 }
+#if LANG_CXX11
+inline void Enum::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Enum.name)
+}
+#endif
 inline void Enum::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1797,9 +1954,10 @@
   source_context_ = NULL;
 }
 inline const ::google::protobuf::SourceContext& Enum::source_context() const {
+  const ::google::protobuf::SourceContext* p = source_context_;
   // @@protoc_insertion_point(field_get:google.protobuf.Enum.source_context)
-  return source_context_ != NULL ? *source_context_
-                         : *::google::protobuf::SourceContext::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::SourceContext*>(
+      &::google::protobuf::_SourceContext_default_instance_);
 }
 inline ::google::protobuf::SourceContext* Enum::mutable_source_context() {
   
@@ -1870,6 +2028,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
 }
+#if LANG_CXX11
+inline void EnumValue::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValue.name)
+}
+#endif
 inline void EnumValue::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1985,6 +2151,14 @@
   name_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
 }
+#if LANG_CXX11
+inline void Option::set_name(::std::string&& value) {
+  
+  name_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Option.name)
+}
+#endif
 inline void Option::set_name(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -2048,9 +2222,10 @@
   value_ = NULL;
 }
 inline const ::google::protobuf::Any& Option::value() const {
+  const ::google::protobuf::Any* p = value_;
   // @@protoc_insertion_point(field_get:google.protobuf.Option.value)
-  return value_ != NULL ? *value_
-                         : *::google::protobuf::Any::internal_default_instance();
+  return p != NULL ? *p : *reinterpret_cast<const ::google::protobuf::Any*>(
+      &::google::protobuf::_Any_default_instance_);
 }
 inline ::google::protobuf::Any* Option::mutable_value() {
   
@@ -2090,6 +2265,9 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 // -------------------------------------------------------------------
 
@@ -2106,7 +2284,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#ifndef SWIG
 namespace google {
 namespace protobuf {
 
@@ -2128,7 +2305,6 @@
 
 }  // namespace protobuf
 }  // namespace google
-#endif  // SWIG
 
 // @@protoc_insertion_point(global_scope)
 
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index 2040487..45a0eda 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -397,6 +397,12 @@
   optional int32 dummy = 3;
 }
 
+message TestRequiredMessage {
+  optional TestRequired optional_message = 1;
+  repeated TestRequired repeated_message = 2;
+  required TestRequired required_message = 3;
+}
+
 // Test that we can use NestedMessage from outside TestAllTypes.
 message TestForeignNested {
   optional TestAllTypes.NestedMessage foreign_nested = 1;
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index c39ac6b..9a15bda 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -439,3 +439,18 @@
 extend TestHugeFieldNumbersLite {
   optional TestAllTypesLite test_all_types_lite = 536860000;
 }
+
+message TestOneofParsingLite {
+  oneof oneof_field {
+    int32 oneof_int32 = 1;
+    TestAllTypesLite oneof_submessage = 2;
+    string oneof_string = 3;
+    bytes oneof_bytes = 4 [default = "default bytes"];
+    string oneof_string_cord = 5 [ctype = CORD, default = "default Cord"];
+    bytes oneof_bytes_cord = 6 [ctype = CORD];
+    string oneof_string_string_piece = 7 [ctype = STRING_PIECE];
+    bytes oneof_bytes_string_piece = 8
+        [ctype = STRING_PIECE, default = "default StringPiece"];
+    V2EnumLite oneof_enum = 9;
+  }
+}
diff --git a/src/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto
index a27b1b2..84815d4 100644
--- a/src/google/protobuf/unittest_proto3.proto
+++ b/src/google/protobuf/unittest_proto3.proto
@@ -28,35 +28,13 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Author: [email protected] (Kenton Varda)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// A proto file we will use for unit testing.
-
 syntax = "proto3";
 
-// Some generic_services option(s) added automatically.
-// See:  http://go/proto2-generic-services-default
-option cc_generic_services = true;     // auto-added
-option java_generic_services = true;   // auto-added
-option py_generic_services = true;     // auto-added
-option cc_enable_arenas = true;
-option csharp_namespace = "Google.Protobuf.TestProtos";
-
-import "google/protobuf/unittest_import_proto3.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 test_util.h we do "using namespace unittest = protobuf_unittest".
-package protobuf_unittest;
-
-// Protos optimized for SPEED use a strict superset of the generated code
-// of equivalent ones optimized for CODE_SIZE, so we should optimize all our
-// tests for speed unless explicitly testing code size optimization.
 option optimize_for = SPEED;
 
-option java_outer_classname = "UnittestProto";
+import "google/protobuf/unittest_import.proto";
+
+package proto3_unittest;
 
 // This proto includes every type of field in both singular and repeated
 // forms.
@@ -69,7 +47,7 @@
   }
 
   enum NestedEnum {
-    NESTED_ENUM_UNSPECIFIED = 0;
+    ZERO = 0;
     FOO = 1;
     BAR = 2;
     BAZ = 3;
@@ -77,33 +55,49 @@
   }
 
   // Singular
-  int32 single_int32 = 1;
-  int64 single_int64 = 2;
-  uint32 single_uint32 = 3;
-  uint64 single_uint64 = 4;
-  sint32 single_sint32 = 5;
-  sint64 single_sint64 = 6;
-  fixed32 single_fixed32 = 7;
-  fixed64 single_fixed64 = 8;
-  sfixed32 single_sfixed32 = 9;
-  sfixed64 single_sfixed64 = 10;
-  float single_float = 11;
-  double single_double = 12;
-  bool single_bool = 13;
-  string single_string = 14;
-  bytes single_bytes = 15;
+     int32 optional_int32    =  1;
+     int64 optional_int64    =  2;
+    uint32 optional_uint32   =  3;
+    uint64 optional_uint64   =  4;
+    sint32 optional_sint32   =  5;
+    sint64 optional_sint64   =  6;
+   fixed32 optional_fixed32  =  7;
+   fixed64 optional_fixed64  =  8;
+  sfixed32 optional_sfixed32 =  9;
+  sfixed64 optional_sfixed64 = 10;
+     float optional_float    = 11;
+    double optional_double   = 12;
+      bool optional_bool     = 13;
+    string optional_string   = 14;
+     bytes optional_bytes    = 15;
 
-  NestedMessage single_nested_message = 18;
-  ForeignMessage single_foreign_message = 19;
-  protobuf_unittest_import.ImportMessage single_import_message = 20;
+  // Groups are not allowed in proto3.
+  // optional group OptionalGroup = 16 {
+  //   optional int32 a = 17;
+  // }
 
-  NestedEnum single_nested_enum = 21;
-  ForeignEnum single_foreign_enum = 22;
-  protobuf_unittest_import.ImportEnum single_import_enum = 23;
+  NestedMessage                        optional_nested_message  = 18;
+  ForeignMessage                       optional_foreign_message = 19;
+  protobuf_unittest_import.ImportMessage optional_import_message  = 20;
+
+  NestedEnum                           optional_nested_enum     = 21;
+  ForeignEnum                          optional_foreign_enum    = 22;
+
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // optional protobuf_unittest_import.ImportEnum    optional_import_enum  = 23;
+
+  string optional_string_piece = 24 [ctype=STRING_PIECE];
+  string optional_cord = 25 [ctype=CORD];
 
   // Defined in unittest_import_public.proto
   protobuf_unittest_import.PublicImportMessage
-      single_public_import_message = 26;
+      optional_public_import_message = 26;
+
+  NestedMessage optional_lazy_message = 27 [lazy=true];
+  protobuf_unittest_import.ImportMessage optional_lazy_import_message = 115
+      [lazy = true];
 
   // Repeated
   repeated    int32 repeated_int32    = 31;
@@ -122,18 +116,28 @@
   repeated   string repeated_string   = 44;
   repeated    bytes repeated_bytes    = 45;
 
+  // Groups are not allowed in proto3.
+  // repeated group RepeatedGroup = 46 {
+  //   optional int32 a = 47;
+  // }
+
   repeated NestedMessage                        repeated_nested_message  = 48;
   repeated ForeignMessage                       repeated_foreign_message = 49;
   repeated protobuf_unittest_import.ImportMessage repeated_import_message  = 50;
 
   repeated NestedEnum                           repeated_nested_enum     = 51;
   repeated ForeignEnum                          repeated_foreign_enum    = 52;
-  repeated protobuf_unittest_import.ImportEnum    repeated_import_enum     = 53;
-  // Defined in unittest_import_public.proto
-  repeated protobuf_unittest_import.PublicImportMessage
-      repeated_public_import_message = 54;
 
-  // For oneof test
+  // Omitted (compared to unittest.proto) because proto2 enums are not allowed
+  // inside proto2 messages.
+  //
+  // repeated protobuf_unittest_import.ImportEnum    repeated_import_enum  = 53;
+
+  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype=CORD];
+
+  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+
   oneof oneof_field {
     uint32 oneof_uint32 = 111;
     NestedMessage oneof_nested_message = 112;
@@ -142,176 +146,6 @@
   }
 }
 
-// This proto includes a recusively nested message.
-message NestedTestAllTypes {
-  NestedTestAllTypes child = 1;
-  TestAllTypes payload = 2;
-  repeated NestedTestAllTypes repeated_child = 3;
-}
-
-message TestDeprecatedFields {
-  int32 deprecated_int32 = 1 [deprecated=true];
-}
-
-// Define these after TestAllTypes to make sure the compiler can handle
-// that.
-message ForeignMessage {
-  int32 c = 1;
-}
-
-enum ForeignEnum {
-  FOREIGN_UNSPECIFIED = 0;
-  FOREIGN_FOO = 4;
-  FOREIGN_BAR = 5;
-  FOREIGN_BAZ = 6;
-}
-
-message TestReservedFields {
-  reserved 2, 15, 9 to 11;
-  reserved "bar", "baz";
-}
-
-
-// Test that we can use NestedMessage from outside TestAllTypes.
-message TestForeignNested {
-  TestAllTypes.NestedMessage foreign_nested = 1;
-}
-
-// Test that really large tag numbers don't break anything.
-message TestReallyLargeTagNumber {
-  // The largest possible tag number is 2^28 - 1, since the wire format uses
-  // three bits to communicate wire type.
-  int32 a = 1;
-  int32 bb = 268435455;
-}
-
-message TestRecursiveMessage {
-  TestRecursiveMessage a = 1;
-  int32 i = 2;
-}
-
-// Test that mutual recursion works.
-message TestMutualRecursionA {
-  TestMutualRecursionB bb = 1;
-}
-
-message TestMutualRecursionB {
-  TestMutualRecursionA a = 1;
-  int32 optional_int32 = 2;
-}
-
-message TestEnumAllowAlias {
-  TestEnumWithDupValue value = 1;
-}
-
-// Test an enum that has multiple values with the same number.
-enum TestEnumWithDupValue {
-  TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0;
-  option allow_alias = true;
-
-  FOO1 = 1;
-  BAR1 = 2;
-  BAZ = 3;
-  FOO2 = 1;
-  BAR2 = 2;
-}
-
-// Test an enum with large, unordered values.
-enum TestSparseEnum {
-  TEST_SPARSE_ENUM_UNSPECIFIED = 0;
-  SPARSE_A = 123;
-  SPARSE_B = 62374;
-  SPARSE_C = 12589234;
-  SPARSE_D = -15;
-  SPARSE_E = -53452;
-  // In proto3, value 0 must be the first one specified
-  // SPARSE_F = 0;
-  SPARSE_G = 2;
-}
-
-// Test message with CamelCase field names.  This violates Protocol Buffer
-// standard style.
-message TestCamelCaseFieldNames {
-  int32 PrimitiveField = 1;
-  string StringField = 2;
-  ForeignEnum EnumField = 3;
-  ForeignMessage MessageField = 4;
-
-  repeated int32 RepeatedPrimitiveField = 7;
-  repeated string RepeatedStringField = 8;
-  repeated ForeignEnum RepeatedEnumField = 9;
-  repeated ForeignMessage RepeatedMessageField = 10;
-}
-
-
-// We list fields out of order, to ensure that we're using field number and not
-// field index to determine serialization order.
-message TestFieldOrderings {
-  string my_string = 11;
-  int64 my_int = 1;
-  float my_float = 101;
-  message NestedMessage {
-    int64 oo = 2;
-    // The field name "b" fails to compile in proto1 because it conflicts with
-    // a local variable named "b" in one of the generated methods.  Doh.
-    // This file needs to compile in proto1 to test backwards-compatibility.
-    int32 bb = 1;
-  }
-
-  NestedMessage single_nested_message  = 200;
-}
-
-message SparseEnumMessage {
-  TestSparseEnum sparse_enum = 1;
-}
-
-// Test String and Bytes: string is for valid UTF-8 strings
-message OneString {
-  string data = 1;
-}
-
-message MoreString {
-  repeated string data = 1;
-}
-
-message OneBytes {
-  bytes data = 1;
-}
-
-message MoreBytes {
-  bytes data = 1;
-}
-
-// Test int32, uint32, int64, uint64, and bool are all compatible
-message Int32Message {
-  int32 data = 1;
-}
-
-message Uint32Message {
-  uint32 data = 1;
-}
-
-message Int64Message {
-  int64 data = 1;
-}
-
-message Uint64Message {
-  uint64 data = 1;
-}
-
-message BoolMessage {
-  bool data = 1;
-}
-
-// Test oneofs.
-message TestOneof {
-  oneof foo {
-    int32 foo_int = 1;
-    string foo_string = 2;
-    TestAllTypes foo_message = 3;
-  }
-}
-
 // Test messages for packed fields
 
 message TestPackedTypes {
@@ -331,61 +165,44 @@
   repeated ForeignEnum packed_enum  = 103 [packed = true];
 }
 
-// A message with the same fields as TestPackedTypes, but without packing. Used
-// to test packed <-> unpacked wire compatibility.
+// Explicitly set packed to false
 message TestUnpackedTypes {
-  repeated    int32 unpacked_int32    =  90 [packed = false];
-  repeated    int64 unpacked_int64    =  91 [packed = false];
-  repeated   uint32 unpacked_uint32   =  92 [packed = false];
-  repeated   uint64 unpacked_uint64   =  93 [packed = false];
-  repeated   sint32 unpacked_sint32   =  94 [packed = false];
-  repeated   sint64 unpacked_sint64   =  95 [packed = false];
-  repeated  fixed32 unpacked_fixed32  =  96 [packed = false];
-  repeated  fixed64 unpacked_fixed64  =  97 [packed = false];
-  repeated sfixed32 unpacked_sfixed32 =  98 [packed = false];
-  repeated sfixed64 unpacked_sfixed64 =  99 [packed = false];
-  repeated    float unpacked_float    = 100 [packed = false];
-  repeated   double unpacked_double   = 101 [packed = false];
-  repeated     bool unpacked_bool     = 102 [packed = false];
-  repeated ForeignEnum unpacked_enum  = 103 [packed = false];
+  repeated    int32 repeated_int32    =  1 [packed = false];
+  repeated    int64 repeated_int64    =  2 [packed = false];
+  repeated   uint32 repeated_uint32   =  3 [packed = false];
+  repeated   uint64 repeated_uint64   =  4 [packed = false];
+  repeated   sint32 repeated_sint32   =  5 [packed = false];
+  repeated   sint64 repeated_sint64   =  6 [packed = false];
+  repeated  fixed32 repeated_fixed32  =  7 [packed = false];
+  repeated  fixed64 repeated_fixed64  =  8 [packed = false];
+  repeated sfixed32 repeated_sfixed32 =  9 [packed = false];
+  repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
+  repeated    float repeated_float    = 11 [packed = false];
+  repeated   double repeated_double   = 12 [packed = false];
+  repeated     bool repeated_bool     = 13 [packed = false];
+  repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
 }
 
-message TestRepeatedScalarDifferentTagSizes {
-  // Parsing repeated fixed size values used to fail. This message needs to be
-  // used in order to get a tag of the right size; all of the repeated fields
-  // in TestAllTypes didn't trigger the check.
-  repeated fixed32 repeated_fixed32 = 12;
-  // Check for a varint type, just for good measure.
-  repeated int32   repeated_int32   = 13;
-
-  // These have two-byte tags.
-  repeated fixed64 repeated_fixed64 = 2046;
-  repeated int64   repeated_int64   = 2047;
-
-  // Three byte tags.
-  repeated float   repeated_float   = 262142;
-  repeated uint64  repeated_uint64  = 262143;
+// This proto includes a recusively nested message.
+message NestedTestAllTypes {
+  NestedTestAllTypes child = 1;
+  TestAllTypes payload = 2;
 }
 
-message TestCommentInjectionMessage {
-  // */ <- This should not close the generated doc comment
-  string a = 1;
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  int32 c = 1;
 }
 
-
-// Test that RPC services work.
-message FooRequest  {}
-message FooResponse {}
-
-message FooClientMessage {}
-message FooServerMessage{}
-
-service TestService {
-  rpc Foo(FooRequest) returns (FooResponse);
-  rpc Bar(BarRequest) returns (BarResponse);
+enum ForeignEnum {
+  FOREIGN_ZERO = 0;
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
 }
 
-
-message BarRequest  {}
-message BarResponse {}
+// TestEmptyMessage is used to test behavior of unknown fields.
+message TestEmptyMessage {
+}
 
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 002ea8e..beb4c9e 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -282,10 +282,10 @@
 }
 inline const UnknownField& UnknownFieldSet::field(int index) const {
   GOOGLE_DCHECK(fields_ != NULL);
-  return (*fields_)[index];
+  return (*fields_)[static_cast<size_t>(index)];
 }
 inline UnknownField* UnknownFieldSet::mutable_field(int index) {
-  return &(*fields_)[index];
+  return &(*fields_)[static_cast<size_t>(index)];
 }
 
 inline void UnknownFieldSet::AddLengthDelimited(
@@ -296,7 +296,7 @@
 
 
 
-inline int UnknownField::number() const { return number_; }
+inline int UnknownField::number() const { return static_cast<int>(number_); }
 inline UnknownField::Type UnknownField::type() const {
   return static_cast<Type>(type_);
 }
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index ad560eb..26a7ba4 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -237,7 +237,7 @@
 
   // True iff default_tolerance_ has been explicitly set.
   //
-  // If false, then the default tolerance for flaots and doubles is that which
+  // If false, then the default tolerance for floats and doubles is that which
   // is used by MathUtil::AlmostEquals().
   bool has_default_tolerance_;
 
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index 85cecec..982d640 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -207,6 +207,18 @@
     MergeMessage(&root_, source, options, destination);
   }
 
+  // Add required field path of the message to this tree based on current tree
+  // structure. If a message is present in the tree, add the path of its
+  // required field to the tree. This is to make sure that after trimming a
+  // message with required fields are set, check IsInitialized() will not fail.
+  void AddRequiredFieldPath(const Descriptor* descriptor) {
+    // Do nothing if the tree is empty.
+    if (root_.children.empty()) {
+      return;
+    }
+    AddRequiredFieldPath(&root_, descriptor);
+  }
+
   // Trims all fields not specified by this tree from the given message.
   void TrimMessage(Message* message) {
     // Do nothing if the tree is empty.
@@ -249,6 +261,12 @@
                     const FieldMaskUtil::MergeOptions& options,
                     Message* destination);
 
+  // Add required field path of the message to this tree based on current tree
+  // structure. If a message is present in the tree, add the path of its
+  // required field to the tree. This is to make sure that after trimming a
+  // message with required fields are set, check IsInitialized() will not fail.
+  void AddRequiredFieldPath(Node* node, const Descriptor* descriptor);
+
   // Trims all fields not specified by this sub-tree from the given message.
   void TrimMessage(const Node* node, Message* message);
 
@@ -456,6 +474,41 @@
   }
 }
 
+void FieldMaskTree::AddRequiredFieldPath(
+    Node* node, const Descriptor* descriptor) {
+  const int32 field_count = descriptor->field_count();
+  for (int index = 0; index < field_count; ++index) {
+    const FieldDescriptor* field = descriptor->field(index);
+    if (field->is_required()) {
+      const string& node_name = field->name();
+      Node*& child = node->children[node_name];
+      if (child == NULL) {
+        // Add required field path to the tree
+        child = new Node();
+      } else if (child->children.empty()){
+        // If the required field is in the tree and does not have any children,
+        // do nothing.
+        continue;
+      }
+      // Add required field in the children to the tree if the field is message.
+      if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+        AddRequiredFieldPath(child, field->message_type());
+      }
+    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      std::map<string, Node*>::const_iterator it =
+          node->children.find(field->name());
+      if (it != node->children.end()) {
+        // Add required fields in the children to the
+        // tree if the field is a message and present in the tree.
+        Node* child = it->second;
+        if (!child->children.empty()) {
+          AddRequiredFieldPath(child, field->message_type());
+        }
+      }
+    }
+  }
+}
+
 void FieldMaskTree::TrimMessage(const Node* node, Message* message) {
   GOOGLE_DCHECK(!node->children.empty());
   const Reflection* reflection = message->GetReflection();
@@ -470,7 +523,7 @@
     } else {
       if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
         Node* child = it->second;
-        if (!child->children.empty()) {
+        if (!child->children.empty() && reflection->HasField(*message, field)) {
           TrimMessage(child, reflection->MutableMessage(message, field));
         }
       }
@@ -542,6 +595,20 @@
   tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
 }
 
+void FieldMaskUtil::TrimMessage(const FieldMask& mask, Message* destination,
+                                const TrimOptions& options) {
+  // Build a FieldMaskTree and walk through the tree to merge all specified
+  // fields.
+  FieldMaskTree tree;
+  tree.MergeFromFieldMask(mask);
+  // If keep_required_fields is true, implicitely add required fields of
+  // a message present in the tree to prevent from trimming.
+  if (options.keep_required_fields()) {
+    tree.AddRequiredFieldPath(GOOGLE_CHECK_NOTNULL(destination->GetDescriptor()));
+  }
+  tree.TrimMessage(GOOGLE_CHECK_NOTNULL(destination));
+}
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index ab1f2e9..71c68fe 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -124,10 +124,17 @@
   static void MergeMessageTo(const Message& source, const FieldMask& mask,
                              const MergeOptions& options, Message* destination);
 
+  class TrimOptions;
   // Removes from 'message' any field that is not represented in the given
   // FieldMask. If the FieldMask is empty, does nothing.
   static void TrimMessage(const FieldMask& mask, Message* message);
 
+  // Removes from 'message' any field that is not represented in the given
+  // FieldMask with customized TrimOptions.
+  // If the FieldMask is empty, does nothing.
+  static void TrimMessage(const FieldMask& mask, Message* message,
+                          const TrimOptions& options);
+
  private:
   friend class SnakeCaseCamelCaseTest;
   // Converts a field name from snake_case to camelCase:
@@ -194,6 +201,23 @@
   bool replace_repeated_fields_;
 };
 
+class LIBPROTOBUF_EXPORT FieldMaskUtil::TrimOptions {
+ public:
+  TrimOptions()
+      : keep_required_fields_(false) {}
+  // When trimming message fields, the default behavior is to trim required
+  // fields of the present message if they are not specified in the field mask.
+  // If you instead want to keep required fields of the present message even
+  // they are not speicifed in the field mask, set this flag to true.
+  void set_keep_required_fields(bool value) {
+    keep_required_fields_ = value;
+  }
+  bool keep_required_fields() const { return keep_required_fields_; }
+
+ private:
+  bool keep_required_fields_;
+};
+
 }  // namespace util
 }  // namespace protobuf
 
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
index f952786..24943ed 100644
--- a/src/google/protobuf/util/field_mask_util_test.cc
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -114,6 +114,8 @@
 }
 
 using protobuf_unittest::TestAllTypes;
+using protobuf_unittest::TestRequired;
+using protobuf_unittest::TestRequiredMessage;
 using protobuf_unittest::NestedTestAllTypes;
 using google::protobuf::FieldMask;
 
@@ -618,6 +620,84 @@
   FieldMask empty_mask;
   FieldMaskUtil::TrimMessage(empty_mask, &trimmed_all_types);
   EXPECT_EQ(trimmed_all_types.DebugString(), all_types_msg.DebugString());
+
+  // Test trim required fields with keep_required_fields is set true.
+  FieldMaskUtil::TrimOptions options;
+  TestRequired required_msg_1;
+  required_msg_1.set_a(1234);
+  required_msg_1.set_b(3456);
+  required_msg_1.set_c(5678);
+  TestRequired trimmed_required_msg_1(required_msg_1);
+  FieldMaskUtil::FromString("dummy2", &mask);
+  options.set_keep_required_fields(true);
+  FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
+  EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
+
+  // Test trim required fields with keep_required_fields is set false.
+  required_msg_1.clear_a();
+  required_msg_1.clear_b();
+  required_msg_1.clear_c();
+  options.set_keep_required_fields(false);
+  FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_1, options);
+  EXPECT_EQ(trimmed_required_msg_1.DebugString(), required_msg_1.DebugString());
+
+  // Test trim required message with keep_required_fields is set true.
+  TestRequiredMessage required_msg_2;
+  required_msg_2.mutable_optional_message()->set_a(1234);
+  required_msg_2.mutable_optional_message()->set_b(3456);
+  required_msg_2.mutable_optional_message()->set_c(5678);
+  required_msg_2.mutable_required_message()->set_a(1234);
+  required_msg_2.mutable_required_message()->set_b(3456);
+  required_msg_2.mutable_required_message()->set_c(5678);
+  required_msg_2.mutable_required_message()->set_dummy2(7890);
+  TestRequired* repeated_msg = required_msg_2.add_repeated_message();
+  repeated_msg->set_a(1234);
+  repeated_msg->set_b(3456);
+  repeated_msg->set_c(5678);
+  TestRequiredMessage trimmed_required_msg_2(required_msg_2);
+  FieldMaskUtil::FromString("optional_message.dummy2", &mask);
+  options.set_keep_required_fields(true);
+  required_msg_2.clear_repeated_message();
+  required_msg_2.mutable_required_message()->clear_dummy2();
+  FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
+  EXPECT_EQ(trimmed_required_msg_2.DebugString(),
+            required_msg_2.DebugString());
+
+  FieldMaskUtil::FromString("required_message", &mask);
+  required_msg_2.mutable_required_message()->set_dummy2(7890);
+  trimmed_required_msg_2.mutable_required_message()->set_dummy2(7890);
+  required_msg_2.clear_optional_message();
+  FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
+  EXPECT_EQ(trimmed_required_msg_2.DebugString(),
+            required_msg_2.DebugString());
+
+  // Test trim required message with keep_required_fields is set false.
+  FieldMaskUtil::FromString("required_message.dummy2", &mask);
+  required_msg_2.mutable_required_message()->clear_a();
+  required_msg_2.mutable_required_message()->clear_b();
+  required_msg_2.mutable_required_message()->clear_c();
+  options.set_keep_required_fields(false);
+  FieldMaskUtil::TrimMessage(mask, &trimmed_required_msg_2, options);
+  EXPECT_EQ(trimmed_required_msg_2.DebugString(),
+            required_msg_2.DebugString());
+
+  // Verify that trimming an empty message has no effect. In particular, fields
+  // mentioned in the field mask should not be created or changed.
+  TestAllTypes empty_msg;
+  FieldMaskUtil::FromString(
+      "optional_int32,optional_bytes,optional_nested_message.bb", &mask);
+  FieldMaskUtil::TrimMessage(mask, &empty_msg);
+  EXPECT_FALSE(empty_msg.has_optional_int32());
+  EXPECT_FALSE(empty_msg.has_optional_bytes());
+  EXPECT_FALSE(empty_msg.has_optional_nested_message());
+
+  // Verify trimming of oneof fields. This should work as expected even if
+  // multiple elements of the same oneof are included in the FieldMask.
+  TestAllTypes oneof_msg;
+  oneof_msg.set_oneof_uint32(11);
+  FieldMaskUtil::FromString("oneof_uint32,oneof_nested_message.bb", &mask);
+  FieldMaskUtil::TrimMessage(mask, &oneof_msg);
+  EXPECT_EQ(11, oneof_msg.oneof_uint32());
 }
 
 
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index 5763d0c..95b3a17 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -637,6 +637,7 @@
     current_->AddChild(node.release());
   } else {
     child->set_data(data);
+    child->set_is_placeholder(false);
   }
 }
 
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index ef2cc98..09c6d23 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -172,7 +172,7 @@
     // If this node is a leaf (has data), writes the current node to the
     // ObjectWriter; if not, then recursively writes the children to the
     // ObjectWriter.
-    void WriteTo(ObjectWriter* ow);
+    virtual void WriteTo(ObjectWriter* ow);
 
     // Accessors
     const string& name() const { return name_; }
@@ -262,6 +262,10 @@
   static DataPiece CreateDefaultDataPieceForField(
       const google::protobuf::Field& field, const TypeInfo* typeinfo);
 
+ protected:
+  // Returns a pointer to current Node in tree.
+  Node* current() { return current_; }
+
  private:
   // Populates children of "node" if it is an "any" Node and its real type has
   // been given.
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 025fbd4..02360a1 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -125,6 +125,7 @@
       recursion_depth_(0),
       max_recursion_depth_(kDefaultMaxRecursionDepth),
       render_unknown_fields_(false),
+      render_unknown_enum_values_(true),
       add_trailing_zeros_for_timestamp_and_duration_(false) {
   GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
 }
@@ -142,6 +143,7 @@
       recursion_depth_(0),
       max_recursion_depth_(kDefaultMaxRecursionDepth),
       render_unknown_fields_(false),
+      render_unknown_enum_values_(true),
       add_trailing_zeros_for_timestamp_and_duration_(false) {
   GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL.";
 }
@@ -866,12 +868,6 @@
         break;
       }
 
-      // No need to lookup enum type if we need to render int.
-      if (use_ints_for_enums_) {
-        ow->RenderInt32(field_name, buffer32);
-        break;
-      }
-
       // Get the nested enum type for this field.
       // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
       // up.
@@ -883,14 +879,17 @@
         const google::protobuf::EnumValue* enum_value =
             FindEnumValueByNumber(*en, buffer32);
         if (enum_value != NULL) {
-          if (use_lower_camel_for_enums_)
+          if (use_ints_for_enums_) {
+            ow->RenderInt32(field_name, buffer32);
+          } else if (use_lower_camel_for_enums_) {
             ow->RenderString(field_name, ToCamelCase(enum_value->name()));
-          else
+          } else {
             ow->RenderString(field_name, enum_value->name());
-        } else {
+          }
+        } else if (render_unknown_enum_values_) {
           ow->RenderInt32(field_name, buffer32);
         }
-      } else {
+      } else if (render_unknown_enum_values_) {
         ow->RenderInt32(field_name, buffer32);
       }
       break;
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 58d77c2..b56efdf 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -309,6 +309,9 @@
   // Whether to render unknown fields.
   bool render_unknown_fields_;
 
+  // Whether to render unknown enum values.
+  bool render_unknown_enum_values_;
+
   // Whether to add trailing zeros for timestamp and duration.
   bool add_trailing_zeros_for_timestamp_and_duration_;
 
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 06c9bb6..36bb1ba 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -103,7 +103,8 @@
         ow_(&mock_),
         use_lower_camel_for_enums_(false),
         use_ints_for_enums_(false),
-        add_trailing_zeros_(false) {
+        add_trailing_zeros_(false),
+        render_unknown_enum_values_(true) {
     helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor());
   }
 
@@ -276,6 +277,10 @@
 
   void AddTrailingZeros() { add_trailing_zeros_ = true; }
 
+  void SetRenderUnknownEnumValues(bool value) {
+    render_unknown_enum_values_ = value;
+  }
+
   testing::TypeInfoTestHelper helper_;
 
   ::testing::NiceMock<MockObjectWriter> mock_;
@@ -283,6 +288,7 @@
   bool use_lower_camel_for_enums_;
   bool use_ints_for_enums_;
   bool add_trailing_zeros_;
+  bool render_unknown_enum_values_;
 };
 
 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
@@ -513,12 +519,27 @@
   DoTest(book, Book::descriptor());
 }
 
-TEST_P(ProtostreamObjectSourceTest, UnknownEnum) {
+TEST_P(ProtostreamObjectSourceTest,
+       UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset) {
   Proto3Message message;
   message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
-  ow_.StartObject("")
-      ->RenderInt32("enumValue", 1234)
-      ->EndObject();
+
+  SetRenderUnknownEnumValues(false);
+
+  // Unknown enum values are not output.
+  ow_.StartObject("")->EndObject();
+  DoTest(message, Proto3Message::descriptor());
+}
+
+TEST_P(ProtostreamObjectSourceTest,
+       UnknownEnumAreOutputWhenRenderUnknownEnumValuesIsSet) {
+  Proto3Message message;
+  message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
+
+  SetRenderUnknownEnumValues(true);
+
+  // Unknown enum values are output.
+  ow_.StartObject("")->RenderInt32("enumValue", 1234)->EndObject();
   DoTest(message, Proto3Message::descriptor());
 }
 
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index d4e15bc..97f9681 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -962,7 +962,7 @@
 // conversions as much as possible. Because ToSnakeCase sometimes returns the
 // wrong value.
   google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback(
-      NewPermanentCallback(&RenderOneFieldPath, ow));
+      ::google::protobuf::NewPermanentCallback(&RenderOneFieldPath, ow));
   return DecodeCompactFieldMaskPaths(data.str(), callback.get());
 }
 
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 8cf42e4..11780ee 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -124,7 +124,10 @@
     return type_url.substr(kTypeUrlSize + 1);
   } else {
     size_t idx = type_url.rfind('/');
-    return type_url.substr(idx + 1);
+    if (idx != type_url.npos) {
+      type_url.remove_prefix(idx + 1);
+    }
+    return type_url;
   }
 }
 
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 830850b..d62038a 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -53,6 +53,7 @@
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/text_format.h>
 #include <google/protobuf/util/field_comparator.h>
@@ -150,6 +151,32 @@
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator);
 };
 
+MessageDifferencer::MapEntryKeyComparator::MapEntryKeyComparator(
+    MessageDifferencer* message_differencer)
+    : message_differencer_(message_differencer) {}
+
+bool MessageDifferencer::MapEntryKeyComparator::IsMatch(
+    const Message& message1, const Message& message2,
+    const std::vector<SpecificField>& parent_fields) const {
+  // Map entry has its key in the field with tag 1.  See the comment for
+  // map_entry in MessageOptions.
+  const FieldDescriptor* key = message1.GetDescriptor()->FindFieldByNumber(1);
+  // If key is not present in message1 and we're doing partial comparison or if
+  // map key is explicitly ignored treat the field as set instead,
+  const bool treat_as_set =
+      (message_differencer_->scope() == PARTIAL &&
+       !message1.GetReflection()->HasField(message1, key)) ||
+      message_differencer_->IsIgnored(message1, message2, key, parent_fields);
+
+  std::vector<SpecificField> current_parent_fields(parent_fields);
+  if (treat_as_set) {
+    return message_differencer_->Compare(message1, message2,
+                                         &current_parent_fields);
+  }
+  return message_differencer_->CompareFieldValueUsingParentFields(
+      message1, message2, key, -1, -1, &current_parent_fields);
+}
+
 bool MessageDifferencer::Equals(const Message& message1,
                                 const Message& message2) {
   MessageDifferencer differencer;
@@ -191,8 +218,10 @@
       message_field_comparison_(EQUAL),
       scope_(FULL),
       repeated_field_comparison_(AS_LIST),
+      map_entry_key_comparator_(this),
       report_matches_(false),
-      output_string_(NULL) { }
+      report_moves_(true),
+      output_string_(NULL) {}
 
 MessageDifferencer::~MessageDifferencer() {
   for (int i = 0; i < owned_key_comparators_.size(); ++i) {
@@ -484,8 +513,22 @@
   std::vector<const FieldDescriptor*> message2_fields;
   message2_fields.reserve(1 + message2.GetDescriptor()->field_count());
 
-  reflection1->ListFields(message1, &message1_fields);
-  reflection2->ListFields(message2, &message2_fields);
+  if (descriptor1->options().map_entry()) {
+    if (scope_ == PARTIAL) {
+      reflection1->ListFields(message1, &message1_fields);
+    } else {
+      // Map entry fields are always considered present.
+      for (int i = 0; i < descriptor1->field_count(); i++) {
+        message1_fields.push_back(descriptor1->field(i));
+      }
+    }
+    for (int i = 0; i < descriptor1->field_count(); i++) {
+      message2_fields.push_back(descriptor1->field(i));
+    }
+  } else {
+    reflection1->ListFields(message1, &message1_fields);
+    reflection2->ListFields(message2, &message2_fields);
+  }
 
   // Add sentinel values to deal with the
   // case where the number of the fields in
@@ -783,6 +826,8 @@
         reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
     SpecificField specific_field;
     specific_field.field = repeated_field;
+    specific_field.index = index1;
+    specific_field.new_index = index2;
     current_parent_fields.push_back(specific_field);
     match = key_comparator->IsMatch(m1, m2, current_parent_fields);
   }
@@ -854,7 +899,7 @@
       fieldDifferent = true;
     } else if (reporter_ != NULL &&
                specific_field.index != specific_field.new_index &&
-               !specific_field.field->is_map()) {
+               !specific_field.field->is_map() && report_moves_) {
       parent_fields->push_back(specific_field);
       reporter_->ReportMoved(message1, message2, *parent_fields);
       parent_fields->pop_back();
@@ -945,6 +990,8 @@
 bool MessageDifferencer::CheckPathChanged(
     const std::vector<SpecificField>& field_path) {
   for (int i = 0; i < field_path.size(); ++i) {
+    // Don't check indexes for map entries -- maps are unordered.
+    if (field_path[i].field != NULL && field_path[i].field->is_map()) continue;
     if (field_path[i].index != field_path[i].new_index) return true;
   }
   return false;
@@ -952,7 +999,6 @@
 
 bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) {
   if (!field->is_repeated()) return false;
-  if (field->is_map()) return true;
   if (repeated_field_comparison_ == AS_SET)
     return list_fields_.find(field) == list_fields_.end();
   return (set_fields_.find(field) != set_fields_.end());
@@ -993,12 +1039,18 @@
   return false;
 }
 
-const MessageDifferencer::MapKeyComparator* MessageDifferencer
-    ::GetMapKeyComparator(const FieldDescriptor* field) {
+const MessageDifferencer::MapKeyComparator*
+MessageDifferencer ::GetMapKeyComparator(const FieldDescriptor* field) const {
   if (!field->is_repeated()) return NULL;
-  if (map_field_key_comparator_.find(field) !=
-      map_field_key_comparator_.end()) {
-    return map_field_key_comparator_[field];
+  FieldKeyComparatorMap::const_iterator it =
+      map_field_key_comparator_.find(field);
+  if (it != map_field_key_comparator_.end()) {
+    return it->second;
+  }
+  if (field->is_map()) {
+    // field cannot already be treated as list or set since TreatAsList() and
+    // TreatAsSet() call GetMapKeyComparator() and fail if it returns non-NULL.
+    return &map_entry_key_comparator_;
   }
   return NULL;
 }
@@ -1400,7 +1452,7 @@
       // algorithm will fail to find a maximum matching.
       // Here we use the argumenting path algorithm.
       MaximumMatcher::NodeMatchCallback* callback =
-          NewPermanentCallback(
+          ::google::protobuf::NewPermanentCallback(
               this, &MessageDifferencer::IsMatch,
               repeated_field, key_comparator,
               &message1, &message2, parent_fields);
@@ -1524,6 +1576,12 @@
   }
 }
 
+void MessageDifferencer::StreamReporter::PrintPath(
+    const std::vector<SpecificField>& field_path, bool left_side,
+    const Message& message) {
+  PrintPath(field_path, left_side);
+}
+
 void MessageDifferencer::
 StreamReporter::PrintValue(const Message& message,
                            const std::vector<SpecificField>& field_path,
@@ -1601,7 +1659,7 @@
     const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("added: ");
-  PrintPath(field_path, false);
+  PrintPath(field_path, false, message2);
   printer_->Print(": ");
   PrintValue(message2, field_path, false);
   printer_->Print("\n");  // Print for newlines.
@@ -1612,7 +1670,7 @@
     const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("deleted: ");
-  PrintPath(field_path, true);
+  PrintPath(field_path, true, message1);
   printer_->Print(": ");
   PrintValue(message1, field_path, true);
   printer_->Print("\n");  // Print for newlines
@@ -1636,10 +1694,10 @@
   }
 
   printer_->Print("modified: ");
-  PrintPath(field_path, true);
+  PrintPath(field_path, true, message1);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false);
+    PrintPath(field_path, false, message2);
   }
   printer_->Print(": ");
   PrintValue(message1, field_path, true);
@@ -1653,9 +1711,9 @@
     const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("moved: ");
-  PrintPath(field_path, true);
+  PrintPath(field_path, true, message1);
   printer_->Print(" -> ");
-  PrintPath(field_path, false);
+  PrintPath(field_path, false, message2);
   printer_->Print(" : ");
   PrintValue(message1, field_path, true);
   printer_->Print("\n");  // Print for newlines.
@@ -1666,10 +1724,10 @@
     const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("matched: ");
-  PrintPath(field_path, true);
+  PrintPath(field_path, true, message1);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false);
+    PrintPath(field_path, false, message2);
   }
   printer_->Print(" : ");
   PrintValue(message1, field_path, true);
@@ -1681,10 +1739,10 @@
     const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("ignored: ");
-  PrintPath(field_path, true);
+  PrintPath(field_path, true, message1);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false);
+    PrintPath(field_path, false, message2);
   }
   printer_->Print("\n");  // Print for newlines.
 }
@@ -1693,10 +1751,10 @@
     const Message& message1, const Message& message2,
     const std::vector<SpecificField>& field_path) {
   printer_->Print("ignored: ");
-  PrintPath(field_path, true);
+  PrintPath(field_path, true, message1);
   if (CheckPathChanged(field_path)) {
     printer_->Print(" -> ");
-    PrintPath(field_path, false);
+    PrintPath(field_path, false, message2);
   }
   printer_->Print("\n");  // Print for newlines.
 }
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index 192266b..b7d4de0 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -518,6 +518,13 @@
     report_matches_ = report_matches;
   }
 
+  // Tells the differencer whether or not to report moves (in a set or map
+  // repeated field). This method must be called before Compare. The default for
+  // a new differencer is true.
+  void set_report_moves(bool report_moves) {
+    report_moves_ = report_moves;
+  }
+
   // Sets the scope of the comparison (as defined in the Scope enumeration
   // above) that is used by this differencer when determining which fields to
   // compare between the messages.
@@ -620,6 +627,11 @@
         const std::vector<SpecificField>& field_path);
 
    protected:
+    // Prints the specified path of fields to the buffer.  message is used to
+    // print map keys.
+    virtual void PrintPath(const std::vector<SpecificField>& field_path,
+                           bool left_side, const Message& message);
+
     // Prints the specified path of fields to the buffer.
     virtual void PrintPath(const std::vector<SpecificField>& field_path,
                            bool left_side);
@@ -653,6 +665,18 @@
   // relies on some private methods of MessageDifferencer. That's why this
   // class is declared as a nested class of MessageDifferencer.
   class MultipleFieldsMapKeyComparator;
+
+  // A MapKeyComparator for use with map_entries.
+  class LIBPROTOBUF_EXPORT MapEntryKeyComparator : public MapKeyComparator {
+   public:
+    explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
+    virtual bool IsMatch(const Message& message1, const Message& message2,
+                         const std::vector<SpecificField>& parent_fields) const;
+
+   private:
+    MessageDifferencer* message_differencer_;
+  };
+
   // Returns true if field1's number() is less than field2's.
   static bool FieldBefore(const FieldDescriptor* field1,
                           const FieldDescriptor* field2);
@@ -765,9 +789,10 @@
                              const SpecificField& field,
                              const std::vector<SpecificField>& parent_fields);
 
-  // Returns MapKeyComparator* when this field has been configured to
-  // be treated as a map.  If not, returns NULL.
-  const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field);
+  // Returns MapKeyComparator* when this field has been configured to be treated
+  // as a map or its is_map() return true.  If not, returns NULL.
+  const MapKeyComparator* GetMapKeyComparator(
+      const FieldDescriptor* field) const;
 
   // Attempts to match indices of a repeated field, so that the contained values
   // match. Clears output vectors and sets their values to indices of paired
@@ -817,11 +842,13 @@
   // MapKeyComparator is created for comparison purpose.
   std::vector<MapKeyComparator*> owned_key_comparators_;
   FieldKeyComparatorMap map_field_key_comparator_;
+  MapEntryKeyComparator map_entry_key_comparator_;
   std::vector<IgnoreCriteria*> ignore_criteria_;
 
   FieldSet ignored_fields_;
 
   bool report_matches_;
+  bool report_moves_;
 
   string* output_string_;
 
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index 850b397..75cffd9 100755
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -1558,6 +1558,43 @@
   EXPECT_EQ("ignored: item[0].ra\n", output);
 }
 
+// Compares fields by their index offset by one, so index 0 matches with 1, etc.
+class OffsetByOneMapKeyComparator
+    : public util::MessageDifferencer::MapKeyComparator {
+ public:
+  typedef util::MessageDifferencer::SpecificField SpecificField;
+  virtual bool IsMatch(const Message& message1, const Message& message2,
+                       const std::vector<SpecificField>& parent_fields) const {
+    return parent_fields.back().index + 1 == parent_fields.back().new_index;
+  }
+};
+
+TEST(MessageDifferencerTest, RepeatedFieldMapTest_CustomIndexMapKeyComparator) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+  // Treat "item" as Map, using custom key comparator to determine if two
+  // elements have the same key.
+  protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item();
+  item->set_b("one");
+  item = msg2.add_item();
+  item->set_b("zero");
+  item = msg2.add_item();
+  item->set_b("one");
+  util::MessageDifferencer differencer;
+  OffsetByOneMapKeyComparator key_comparator;
+  differencer.TreatAsMapUsingKeyComparator(GetFieldDescriptor(msg1, "item"),
+                                           &key_comparator);
+  string output;
+  differencer.ReportDifferencesToString(&output);
+  // With the offset by one comparator msg1.item[0] should be compared to
+  // msg2.item[1] and thus be moved, msg2.item[0] should be marked as added.
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ(
+      "moved: item[0] -> item[1] : { b: \"one\" }\n"
+      "added: item[0]: { b: \"zero\" }\n",
+      output);
+}
+
 TEST(MessageDifferencerTest, RepeatedFieldSetTest_Subset) {
   protobuf_unittest::TestDiffMessage msg1;
   protobuf_unittest::TestDiffMessage msg2;
@@ -2806,21 +2843,130 @@
 }
 
 TEST_F(ComparisonTest, MapTest) {
-  repeated_field_as_set();
-
   Map<string, string>& map1 = *map_proto1_.mutable_map_string_string();
-  map1["1"] = "1";
-  map1["2"] = "2";
-  map1["3"] = "3";
+  map1["key1"] = "1";
+  map1["key2"] = "2";
+  map1["key3"] = "3";
   Map<string, string>& map2 = *map_proto2_.mutable_map_string_string();
-  map2["3"] = "0";
-  map2["2"] = "2";
-  map2["1"] = "1";
+  map2["key3"] = "0";
+  map2["key2"] = "2";
+  map2["key1"] = "1";
 
-  EXPECT_EQ(
-      "added: map_string_string: { key: \"3\" value: \"0\" }\n"
-      "deleted: map_string_string: { key: \"3\" value: \"3\" }\n",
-      Run(map_proto1_, map_proto2_));
+  EXPECT_EQ("modified: map_string_string.value: \"3\" -> \"0\"\n",
+            Run(map_proto1_, map_proto2_));
+}
+
+TEST_F(ComparisonTest, MapIgnoreKeyTest) {
+  Map<string, string>& map1 = *map_proto1_.mutable_map_string_string();
+  map1["key1"] = "1";
+  map1["key2"] = "2";
+  map1["key3"] = "3";
+  Map<string, string>& map2 = *map_proto2_.mutable_map_string_string();
+  map2["key4"] = "2";
+  map2["key5"] = "3";
+  map2["key6"] = "1";
+
+  util::MessageDifferencer differencer;
+  differencer.IgnoreField(
+      GetFieldDescriptor(map_proto1_, "map_string_string.key"));
+  EXPECT_TRUE(differencer.Compare(map_proto1_, map_proto2_));
+}
+
+TEST_F(ComparisonTest, MapRoundTripSyncTest) {
+  google::protobuf::TextFormat::Parser parser;
+  unittest::TestMap map_reflection1;
+
+  // By setting via reflection, data exists in repeated field.
+  ASSERT_TRUE(parser.ParseFromString(
+      "map_int32_foreign_message { key: 1 }", &map_reflection1));
+
+  // During copy, data is synced from repeated field to map.
+  unittest::TestMap map_reflection2 = map_reflection1;
+
+  // During comparison, data is synced from map to repeated field.
+  EXPECT_TRUE(
+      util::MessageDifferencer::Equals(map_reflection1, map_reflection2));
+}
+
+TEST_F(ComparisonTest, MapEntryPartialTest) {
+  google::protobuf::TextFormat::Parser parser;
+  unittest::TestMap map1;
+  unittest::TestMap map2;
+
+  string output;
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  differencer.ReportDifferencesToString(&output);
+
+  ASSERT_TRUE(parser.ParseFromString(
+      "map_int32_foreign_message { key: 1 value { c: 1 } }", &map1));
+  ASSERT_TRUE(parser.ParseFromString(
+      "map_int32_foreign_message { key: 1 value { c: 2 }}", &map2));
+  EXPECT_FALSE(differencer.Compare(map1, map2));
+  EXPECT_EQ("modified: map_int32_foreign_message.value.c: 1 -> 2\n", output);
+
+  ASSERT_TRUE(
+      parser.ParseFromString("map_int32_foreign_message { key: 1 }", &map1));
+  EXPECT_TRUE(differencer.Compare(map1, map2));
+}
+
+TEST_F(ComparisonTest, MapEntryPartialEmptyKeyTest) {
+  google::protobuf::TextFormat::Parser parser;
+  unittest::TestMap map1;
+  unittest::TestMap map2;
+  ASSERT_TRUE(parser.ParseFromString("map_int32_foreign_message {}", &map1));
+  ASSERT_TRUE(
+      parser.ParseFromString("map_int32_foreign_message { key: 1 }", &map2));
+
+  util::MessageDifferencer differencer;
+  differencer.set_scope(util::MessageDifferencer::PARTIAL);
+  EXPECT_TRUE(differencer.Compare(map1, map2));
+}
+
+// Considers strings keys as equal if they have equal lengths.
+class LengthMapKeyComparator
+    : public util::MessageDifferencer::MapKeyComparator {
+ public:
+  typedef util::MessageDifferencer::SpecificField SpecificField;
+  virtual bool IsMatch(const Message& message1, const Message& message2,
+                       const std::vector<SpecificField>& parent_fields) const {
+    const Reflection* reflection1 = message1.GetReflection();
+    const Reflection* reflection2 = message2.GetReflection();
+    const FieldDescriptor* key_field =
+        message1.GetDescriptor()->FindFieldByName("key");
+    return reflection1->GetString(message1, key_field).size() ==
+           reflection2->GetString(message2, key_field).size();
+  }
+};
+
+TEST_F(ComparisonTest, MapEntryCustomMapKeyComparator) {
+  google::protobuf::TextFormat::Parser parser;
+  protobuf_unittest::TestMap msg1;
+  protobuf_unittest::TestMap msg2;
+
+  ASSERT_TRUE(parser.ParseFromString(
+      "map_string_foreign_message { key: 'key1' value { c: 1 }}", &msg1));
+  ASSERT_TRUE(parser.ParseFromString(
+      "map_string_foreign_message { key: 'key2' value { c: 1 }}", &msg2));
+
+  util::MessageDifferencer differencer;
+  LengthMapKeyComparator key_comparator;
+  differencer.TreatAsMapUsingKeyComparator(
+      GetFieldDescriptor(msg1, "map_string_foreign_message"), &key_comparator);
+  string output;
+  differencer.ReportDifferencesToString(&output);
+  // Though the above two messages have different keys for their map entries,
+  // they are considered the same by key_comparator because their lengths are
+  // equal.  However, in value comparison, all fields of the message are taken
+  // into consideration, so they are reported as different.
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ("modified: map_string_foreign_message.key: \"key1\" -> \"key2\"\n",
+            output);
+  differencer.IgnoreField(
+      GetFieldDescriptor(msg1, "map_string_foreign_message.key"));
+  output.clear();
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+  EXPECT_EQ("ignored: map_string_foreign_message.key\n", output);
 }
 
 class MatchingTest : public testing::Test {
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 5e9aca5..01ee133 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -46,11 +46,6 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/wire_format_lite.h>
 
-// Do UTF-8 validation on string type in Debug build only
-#ifndef NDEBUG
-#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
-#endif
-
 namespace google {
 namespace protobuf {
   namespace io {
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 7987f7c..359353c 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -47,8 +47,8 @@
 #include <google/protobuf/io/zero_copy_stream.h>
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 
-namespace google {
 
+namespace google {
 namespace protobuf {
 namespace internal {
 
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index ce55f26..3e079ea 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -46,6 +46,11 @@
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/io/coded_stream.h>  // for CodedOutputStream::Varint32Size
 
+// Do UTF-8 validation on string type in Debug build only
+#ifndef NDEBUG
+#define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
+#endif
+
 // Avoid conflict with iOS where <ConditionalMacros.h> #defines TYPE_BOOL.
 //
 // If some one needs the macro TYPE_BOOL in a file that includes this header, it's
@@ -787,7 +792,7 @@
 inline size_t WireFormatLite::TagSize(int field_number,
                                       WireFormatLite::FieldType type) {
   size_t result = io::CodedOutputStream::VarintSize32(
-    field_number << kTagTypeBits);
+    static_cast<uint32>(field_number << kTagTypeBits));
   if (type == TYPE_GROUP) {
     // Groups have both a start and an end tag.
     return result * 2;
@@ -846,20 +851,20 @@
 
 inline uint32 WireFormatLite::ZigZagEncode32(int32 n) {
   // Note:  the right-shift must be arithmetic
-  return (static_cast<uint32>(n) << 1) ^ (n >> 31);
+  return static_cast<uint32>((n << 1) ^ (n >> 31));
 }
 
 inline int32 WireFormatLite::ZigZagDecode32(uint32 n) {
-  return (n >> 1) ^ -static_cast<int32>(n & 1);
+  return static_cast<int32>(n >> 1) ^ -static_cast<int32>(n & 1);
 }
 
 inline uint64 WireFormatLite::ZigZagEncode64(int64 n) {
   // Note:  the right-shift must be arithmetic
-  return (static_cast<uint64>(n) << 1) ^ (n >> 63);
+  return static_cast<uint64>((n << 1) ^ (n >> 63));
 }
 
 inline int64 WireFormatLite::ZigZagDecode64(uint64 n) {
-  return (n >> 1) ^ -static_cast<int64>(n & 1);
+  return static_cast<int64>(n >> 1) ^ -static_cast<int64>(n & 1);
 }
 
 // String is for UTF-8 text only, but, even so, ReadString() can simply
diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
index 0504901..c044def 100644
--- a/src/google/protobuf/wire_format_lite_inl.h
+++ b/src/google/protobuf/wire_format_lite_inl.h
@@ -268,7 +268,7 @@
   if (size > 0) {
     const uint8* buffer = reinterpret_cast<const uint8*>(void_pointer);
     // The number of bytes each type occupies on the wire.
-    const int per_value_size = tag_size + sizeof(value);
+    const int per_value_size = tag_size + static_cast<int>(sizeof(value));
 
     // parentheses around (std::min) prevents macro expansion of min(...)
     int elements_available =
@@ -344,8 +344,8 @@
   int length;
   if (!input->ReadVarintSizeAsInt(&length)) return false;
   const int old_entries = values->size();
-  const int new_entries = length / sizeof(CType);
-  const int new_bytes = new_entries * sizeof(CType);
+  const int new_entries = length / static_cast<int>(sizeof(CType));
+  const int new_bytes = new_entries * static_cast<int>(sizeof(CType));
   if (new_bytes != length) return false;
   // We would *like* to pre-allocate the buffer to write into (for
   // speed), but *must* avoid performing a very large allocation due
@@ -695,8 +695,8 @@
   GOOGLE_DCHECK_GT(n, 0);
 
   const T* ii = value.unsafe_data();
-  const int bytes = n * sizeof(ii[0]);
-  memcpy(target, ii, bytes);
+  const int bytes = n * static_cast<int>(sizeof(ii[0]));
+  memcpy(target, ii, static_cast<size_t>(bytes));
   return target + bytes;
 #else
   return WritePrimitiveNoTagToArray(value, Writer, target);
@@ -954,7 +954,7 @@
     uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
   target = io::CodedOutputStream::WriteVarint32ToArray(
-    value.GetCachedSize(), target);
+    static_cast<uint32>(value.GetCachedSize()), target);
   return value.InternalSerializeWithCachedSizesToArray(deterministic, target);
 }
 
@@ -975,7 +975,9 @@
     bool deterministic, uint8* target) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
   target = io::CodedOutputStream::WriteVarint32ToArray(
-    value.MessageType_WorkAroundCppLookupDefect::GetCachedSize(), target);
+        static_cast<uint32>(
+            value.MessageType_WorkAroundCppLookupDefect::GetCachedSize()),
+        target);
   return value.MessageType_WorkAroundCppLookupDefect::
       InternalSerializeWithCachedSizesToArray(deterministic, target);
 }
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 12c04fd..d76e8aa 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -19,23 +19,50 @@
 
 namespace google {
 namespace protobuf {
-class DoubleValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<DoubleValue> {
+class DoubleValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<DoubleValue>
+     _instance;
 } _DoubleValue_default_instance_;
-class FloatValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<FloatValue> {
+class FloatValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<FloatValue>
+     _instance;
 } _FloatValue_default_instance_;
-class Int64ValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Int64Value> {
+class Int64ValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Int64Value>
+     _instance;
 } _Int64Value_default_instance_;
-class UInt64ValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<UInt64Value> {
+class UInt64ValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<UInt64Value>
+     _instance;
 } _UInt64Value_default_instance_;
-class Int32ValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<Int32Value> {
+class Int32ValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<Int32Value>
+     _instance;
 } _Int32Value_default_instance_;
-class UInt32ValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<UInt32Value> {
+class UInt32ValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<UInt32Value>
+     _instance;
 } _UInt32Value_default_instance_;
-class BoolValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<BoolValue> {
+class BoolValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<BoolValue>
+     _instance;
 } _BoolValue_default_instance_;
-class StringValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<StringValue> {
+class StringValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<StringValue>
+     _instance;
 } _StringValue_default_instance_;
-class BytesValueDefaultTypeInternal : public ::google::protobuf::internal::ExplicitlyConstructed<BytesValue> {
+class BytesValueDefaultTypeInternal {
+public:
+ ::google::protobuf::internal::ExplicitlyConstructed<BytesValue>
+     _instance;
 } _BytesValue_default_instance_;
 
 namespace protobuf_google_2fprotobuf_2fwrappers_2eproto {
@@ -48,28 +75,28 @@
 }  // namespace
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTableField
-    const TableStruct::entries[] = {
+    const TableStruct::entries[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   {0, 0, 0, ::google::protobuf::internal::kInvalidMask, 0, 0},
 };
 
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::AuxillaryParseTableField
-    const TableStruct::aux[] = {
+    const TableStruct::aux[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ::google::protobuf::internal::AuxillaryParseTableField(),
 };
 PROTOBUF_CONSTEXPR_VAR ::google::protobuf::internal::ParseTable const
-    TableStruct::schema[] = {
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
-  { NULL, NULL, 0, -1, -1, false },
+    TableStruct::schema[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
+  { NULL, NULL, 0, -1, -1, -1, -1, NULL, false },
 };
 
-const ::google::protobuf::uint32 TableStruct::offsets[] = {
+const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   ~0u,  // no _has_bits_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DoubleValue, _internal_metadata_),
   ~0u,  // no _extensions_
@@ -125,8 +152,7 @@
   ~0u,  // no _weak_field_map_
   GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(BytesValue, value_),
 };
-
-static const ::google::protobuf::internal::MigrationSchema schemas[] = {
+static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
   { 0, -1, sizeof(DoubleValue)},
   { 6, -1, sizeof(FloatValue)},
   { 12, -1, sizeof(Int64Value)},
@@ -172,50 +198,38 @@
 }
 
 }  // namespace
-
-void TableStruct::Shutdown() {
-  _DoubleValue_default_instance_.Shutdown();
-  delete file_level_metadata[0].reflection;
-  _FloatValue_default_instance_.Shutdown();
-  delete file_level_metadata[1].reflection;
-  _Int64Value_default_instance_.Shutdown();
-  delete file_level_metadata[2].reflection;
-  _UInt64Value_default_instance_.Shutdown();
-  delete file_level_metadata[3].reflection;
-  _Int32Value_default_instance_.Shutdown();
-  delete file_level_metadata[4].reflection;
-  _UInt32Value_default_instance_.Shutdown();
-  delete file_level_metadata[5].reflection;
-  _BoolValue_default_instance_.Shutdown();
-  delete file_level_metadata[6].reflection;
-  _StringValue_default_instance_.Shutdown();
-  delete file_level_metadata[7].reflection;
-  _BytesValue_default_instance_.Shutdown();
-  delete file_level_metadata[8].reflection;
-}
-
 void TableStruct::InitDefaultsImpl() {
   GOOGLE_PROTOBUF_VERIFY_VERSION;
 
   ::google::protobuf::internal::InitProtobufDefaults();
-  _DoubleValue_default_instance_.DefaultConstruct();
-  _FloatValue_default_instance_.DefaultConstruct();
-  _Int64Value_default_instance_.DefaultConstruct();
-  _UInt64Value_default_instance_.DefaultConstruct();
-  _Int32Value_default_instance_.DefaultConstruct();
-  _UInt32Value_default_instance_.DefaultConstruct();
-  _BoolValue_default_instance_.DefaultConstruct();
-  _StringValue_default_instance_.DefaultConstruct();
-  _BytesValue_default_instance_.DefaultConstruct();
-}
+  _DoubleValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_DoubleValue_default_instance_);_FloatValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_FloatValue_default_instance_);_Int64Value_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Int64Value_default_instance_);_UInt64Value_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_UInt64Value_default_instance_);_Int32Value_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_Int32Value_default_instance_);_UInt32Value_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_UInt32Value_default_instance_);_BoolValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_BoolValue_default_instance_);_StringValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_StringValue_default_instance_);_BytesValue_default_instance_._instance.DefaultConstruct();
+  ::google::protobuf::internal::OnShutdownDestroyMessage(
+      &_BytesValue_default_instance_);}
 
 void InitDefaults() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &TableStruct::InitDefaultsImpl);
 }
+namespace {
 void AddDescriptorsImpl() {
   InitDefaults();
-  static const char descriptor[] = {
+  static const char descriptor[] GOOGLE_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = {
       "\n\036google/protobuf/wrappers.proto\022\017google"
       ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\""
       "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val"
@@ -233,14 +247,14 @@
       descriptor, 447);
   ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
     "google/protobuf/wrappers.proto", &protobuf_RegisterTypes);
-  ::google::protobuf::internal::OnShutdown(&TableStruct::Shutdown);
 }
+} // anonymous namespace
 
 void AddDescriptors() {
   static GOOGLE_PROTOBUF_DECLARE_ONCE(once);
   ::google::protobuf::GoogleOnceInit(&once, &AddDescriptorsImpl);
 }
-// Force AddDescriptors() to be called at static initialization time.
+// Force AddDescriptors() to be called at dynamic initialization time.
 struct StaticDescriptorInitializer {
   StaticDescriptorInitializer() {
     AddDescriptors();
@@ -267,9 +281,7 @@
 DoubleValue::DoubleValue(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DoubleValue)
@@ -295,6 +307,7 @@
 
 void DoubleValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -328,7 +341,12 @@
 
 void DoubleValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool DoubleValue::MergePartialFromCodedStream(
@@ -344,7 +362,7 @@
       // double value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(9u)) {
+            static_cast< ::google::protobuf::uint8>(9u /* 9 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>(
@@ -357,12 +375,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -387,11 +404,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteDouble(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.DoubleValue)
 }
 
 ::google::protobuf::uint8* DoubleValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DoubleValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -401,6 +423,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DoubleValue)
   return target;
 }
@@ -409,6 +435,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // double value = 1;
   if (this->value() != 0) {
     total_size += 1 + 8;
@@ -486,8 +517,10 @@
   InternalSwap(other);
 }
 void DoubleValue::InternalSwap(DoubleValue* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata DoubleValue::GetMetadata() const {
@@ -531,9 +564,7 @@
 FloatValue::FloatValue(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FloatValue)
@@ -559,6 +590,7 @@
 
 void FloatValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -592,7 +624,12 @@
 
 void FloatValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool FloatValue::MergePartialFromCodedStream(
@@ -608,7 +645,7 @@
       // float value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(13u)) {
+            static_cast< ::google::protobuf::uint8>(13u /* 13 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    float, ::google::protobuf::internal::WireFormatLite::TYPE_FLOAT>(
@@ -621,12 +658,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -651,11 +687,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteFloat(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.FloatValue)
 }
 
 ::google::protobuf::uint8* FloatValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FloatValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -665,6 +706,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteFloatToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FloatValue)
   return target;
 }
@@ -673,6 +718,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // float value = 1;
   if (this->value() != 0) {
     total_size += 1 + 4;
@@ -750,8 +800,10 @@
   InternalSwap(other);
 }
 void FloatValue::InternalSwap(FloatValue* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata FloatValue::GetMetadata() const {
@@ -795,9 +847,7 @@
 Int64Value::Int64Value(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Int64Value)
@@ -823,6 +873,7 @@
 
 void Int64Value::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -856,7 +907,12 @@
 
 void Int64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = GOOGLE_LONGLONG(0);
+  _internal_metadata_.Clear();
 }
 
 bool Int64Value::MergePartialFromCodedStream(
@@ -872,7 +928,7 @@
       // int64 value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>(
@@ -885,12 +941,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -915,11 +970,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Int64Value)
 }
 
 ::google::protobuf::uint8* Int64Value::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int64Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -929,6 +989,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int64Value)
   return target;
 }
@@ -937,6 +1001,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // int64 value = 1;
   if (this->value() != 0) {
     total_size += 1 +
@@ -1016,8 +1085,10 @@
   InternalSwap(other);
 }
 void Int64Value::InternalSwap(Int64Value* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Int64Value::GetMetadata() const {
@@ -1061,9 +1132,7 @@
 UInt64Value::UInt64Value(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt64Value)
@@ -1089,6 +1158,7 @@
 
 void UInt64Value::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -1122,7 +1192,12 @@
 
 void UInt64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = GOOGLE_ULONGLONG(0);
+  _internal_metadata_.Clear();
 }
 
 bool UInt64Value::MergePartialFromCodedStream(
@@ -1138,7 +1213,7 @@
       // uint64 value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>(
@@ -1151,12 +1226,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1181,11 +1255,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteUInt64(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.UInt64Value)
 }
 
 ::google::protobuf::uint8* UInt64Value::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt64Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1195,6 +1274,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt64Value)
   return target;
 }
@@ -1203,6 +1286,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // uint64 value = 1;
   if (this->value() != 0) {
     total_size += 1 +
@@ -1282,8 +1370,10 @@
   InternalSwap(other);
 }
 void UInt64Value::InternalSwap(UInt64Value* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata UInt64Value::GetMetadata() const {
@@ -1327,9 +1417,7 @@
 Int32Value::Int32Value(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Int32Value)
@@ -1355,6 +1443,7 @@
 
 void Int32Value::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -1388,7 +1477,12 @@
 
 void Int32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = 0;
+  _internal_metadata_.Clear();
 }
 
 bool Int32Value::MergePartialFromCodedStream(
@@ -1404,7 +1498,7 @@
       // int32 value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>(
@@ -1417,12 +1511,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1447,11 +1540,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.Int32Value)
 }
 
 ::google::protobuf::uint8* Int32Value::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int32Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1461,6 +1559,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Int32Value)
   return target;
 }
@@ -1469,6 +1571,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // int32 value = 1;
   if (this->value() != 0) {
     total_size += 1 +
@@ -1548,8 +1655,10 @@
   InternalSwap(other);
 }
 void Int32Value::InternalSwap(Int32Value* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata Int32Value::GetMetadata() const {
@@ -1593,9 +1702,7 @@
 UInt32Value::UInt32Value(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt32Value)
@@ -1621,6 +1728,7 @@
 
 void UInt32Value::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -1654,7 +1762,12 @@
 
 void UInt32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = 0u;
+  _internal_metadata_.Clear();
 }
 
 bool UInt32Value::MergePartialFromCodedStream(
@@ -1670,7 +1783,7 @@
       // uint32 value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
@@ -1683,12 +1796,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1713,11 +1825,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.UInt32Value)
 }
 
 ::google::protobuf::uint8* UInt32Value::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt32Value)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1727,6 +1844,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UInt32Value)
   return target;
 }
@@ -1735,6 +1856,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // uint32 value = 1;
   if (this->value() != 0) {
     total_size += 1 +
@@ -1814,8 +1940,10 @@
   InternalSwap(other);
 }
 void UInt32Value::InternalSwap(UInt32Value* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata UInt32Value::GetMetadata() const {
@@ -1859,9 +1987,7 @@
 BoolValue::BoolValue(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.BoolValue)
@@ -1887,6 +2013,7 @@
 
 void BoolValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -1920,7 +2047,12 @@
 
 void BoolValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_ = false;
+  _internal_metadata_.Clear();
 }
 
 bool BoolValue::MergePartialFromCodedStream(
@@ -1936,7 +2068,7 @@
       // bool value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(8u)) {
+            static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) {
 
           DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                    bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
@@ -1949,12 +2081,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -1979,11 +2110,16 @@
     ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.BoolValue)
 }
 
 ::google::protobuf::uint8* BoolValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BoolValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -1993,6 +2129,10 @@
     target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BoolValue)
   return target;
 }
@@ -2001,6 +2141,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // bool value = 1;
   if (this->value() != 0) {
     total_size += 1 + 1;
@@ -2078,8 +2223,10 @@
   InternalSwap(other);
 }
 void BoolValue::InternalSwap(BoolValue* other) {
-  std::swap(value_, other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  using std::swap;
+  swap(value_, other->value_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata BoolValue::GetMetadata() const {
@@ -2123,9 +2270,7 @@
 StringValue::StringValue(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.StringValue)
@@ -2155,6 +2300,7 @@
 
 void StringValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -2189,7 +2335,12 @@
 
 void StringValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  _internal_metadata_.Clear();
 }
 
 bool StringValue::MergePartialFromCodedStream(
@@ -2205,11 +2356,11 @@
       // string value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                 input, this->mutable_value()));
           DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-            this->value().data(), this->value().length(),
+            this->value().data(), static_cast<int>(this->value().length()),
             ::google::protobuf::internal::WireFormatLite::PARSE,
             "google.protobuf.StringValue.value"));
         } else {
@@ -2220,12 +2371,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -2248,18 +2398,23 @@
   // string value = 1;
   if (this->value().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->value().data(), this->value().length(),
+      this->value().data(), static_cast<int>(this->value().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.StringValue.value");
     ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
       1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.StringValue)
 }
 
 ::google::protobuf::uint8* StringValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2267,7 +2422,7 @@
   // string value = 1;
   if (this->value().size() > 0) {
     ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
-      this->value().data(), this->value().length(),
+      this->value().data(), static_cast<int>(this->value().length()),
       ::google::protobuf::internal::WireFormatLite::SERIALIZE,
       "google.protobuf.StringValue.value");
     target =
@@ -2275,6 +2430,10 @@
         1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.StringValue)
   return target;
 }
@@ -2283,6 +2442,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // string value = 1;
   if (this->value().size() > 0) {
     total_size += 1 +
@@ -2362,8 +2526,10 @@
   InternalSwap(other);
 }
 void StringValue::InternalSwap(StringValue* other) {
+  using std::swap;
   value_.Swap(&other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata StringValue::GetMetadata() const {
@@ -2387,6 +2553,14 @@
   value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
 }
+#if LANG_CXX11
+void StringValue::set_value(::std::string&& value) {
+  
+  value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.StringValue.value)
+}
+#endif
 void StringValue::set_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -2460,9 +2634,7 @@
 BytesValue::BytesValue(::google::protobuf::Arena* arena)
   : ::google::protobuf::Message(),
   _internal_metadata_(arena) {
-#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   protobuf_google_2fprotobuf_2fwrappers_2eproto::InitDefaults();
-#endif  // GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
   SharedCtor();
   RegisterArenaDtor(arena);
   // @@protoc_insertion_point(arena_constructor:google.protobuf.BytesValue)
@@ -2492,6 +2664,7 @@
 
 void BytesValue::SharedDtor() {
   ::google::protobuf::Arena* arena = GetArenaNoVirtual();
+  GOOGLE_DCHECK(arena == NULL);
   if (arena != NULL) {
     return;
   }
@@ -2526,7 +2699,12 @@
 
 void BytesValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue)
+  ::google::protobuf::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
   value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+  _internal_metadata_.Clear();
 }
 
 bool BytesValue::MergePartialFromCodedStream(
@@ -2542,7 +2720,7 @@
       // bytes value = 1;
       case 1: {
         if (static_cast< ::google::protobuf::uint8>(tag) ==
-            static_cast< ::google::protobuf::uint8>(10u)) {
+            static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) {
           DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
                 input, this->mutable_value()));
         } else {
@@ -2553,12 +2731,11 @@
 
       default: {
       handle_unusual:
-        if (tag == 0 ||
-            ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
-            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+        if (tag == 0) {
           goto success;
         }
-        DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, _internal_metadata_.mutable_unknown_fields()));
         break;
       }
     }
@@ -2584,11 +2761,16 @@
       1, this->value(), output);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), output);
+  }
   // @@protoc_insertion_point(serialize_end:google.protobuf.BytesValue)
 }
 
 ::google::protobuf::uint8* BytesValue::InternalSerializeWithCachedSizesToArray(
     bool deterministic, ::google::protobuf::uint8* target) const {
+  (void)deterministic; // Unused
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BytesValue)
   ::google::protobuf::uint32 cached_has_bits = 0;
   (void) cached_has_bits;
@@ -2600,6 +2782,10 @@
         1, this->value(), target);
   }
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()), target);
+  }
   // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.BytesValue)
   return target;
 }
@@ -2608,6 +2794,11 @@
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue)
   size_t total_size = 0;
 
+  if ((_internal_metadata_.have_unknown_fields() &&  ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        (::google::protobuf::internal::GetProto3PreserveUnknownsDefault()   ? _internal_metadata_.unknown_fields()   : _internal_metadata_.default_instance()));
+  }
   // bytes value = 1;
   if (this->value().size() > 0) {
     total_size += 1 +
@@ -2687,8 +2878,10 @@
   InternalSwap(other);
 }
 void BytesValue::InternalSwap(BytesValue* other) {
+  using std::swap;
   value_.Swap(&other->value_);
-  std::swap(_cached_size_, other->_cached_size_);
+  _internal_metadata_.Swap(&other->_internal_metadata_);
+  swap(_cached_size_, other->_cached_size_);
 }
 
 ::google::protobuf::Metadata BytesValue::GetMetadata() const {
@@ -2712,6 +2905,14 @@
   value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
 }
+#if LANG_CXX11
+void BytesValue::set_value(::std::string&& value) {
+  
+  value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.BytesValue.value)
+}
+#endif
 void BytesValue::set_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 4202541..29d6b73 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -8,12 +8,12 @@
 
 #include <google/protobuf/stubs/common.h>
 
-#if GOOGLE_PROTOBUF_VERSION < 3003000
+#if GOOGLE_PROTOBUF_VERSION < 3004000
 #error This file was generated by a newer version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please update
 #error your headers.
 #endif
-#if 3003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#if 3004000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers.  Please
 #error regenerate this file with a newer version of protoc.
@@ -72,8 +72,9 @@
   static const ::google::protobuf::internal::AuxillaryParseTableField aux[];
   static const ::google::protobuf::internal::ParseTable schema[];
   static const ::google::protobuf::uint32 offsets[];
+  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
+  static const ::google::protobuf::internal::SerializationTable serialization_table[];
   static void InitDefaultsImpl();
-  static void Shutdown();
 };
 void LIBPROTOBUF_EXPORT AddDescriptors();
 void LIBPROTOBUF_EXPORT InitDefaults();
@@ -92,7 +93,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  DoubleValue(DoubleValue&& from) noexcept
+    : DoubleValue() {
+    *this = ::std::move(from);
+  }
 
+  inline DoubleValue& operator=(DoubleValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -111,6 +126,9 @@
 
   void UnsafeArenaSwap(DoubleValue* other);
   void Swap(DoubleValue* other);
+  friend void swap(DoubleValue& a, DoubleValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -167,7 +185,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   double value_;
@@ -187,7 +205,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  FloatValue(FloatValue&& from) noexcept
+    : FloatValue() {
+    *this = ::std::move(from);
+  }
 
+  inline FloatValue& operator=(FloatValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -206,6 +238,9 @@
 
   void UnsafeArenaSwap(FloatValue* other);
   void Swap(FloatValue* other);
+  friend void swap(FloatValue& a, FloatValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -262,7 +297,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   float value_;
@@ -282,7 +317,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Int64Value(Int64Value&& from) noexcept
+    : Int64Value() {
+    *this = ::std::move(from);
+  }
 
+  inline Int64Value& operator=(Int64Value&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -301,6 +350,9 @@
 
   void UnsafeArenaSwap(Int64Value* other);
   void Swap(Int64Value* other);
+  friend void swap(Int64Value& a, Int64Value& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -357,7 +409,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::int64 value_;
@@ -377,7 +429,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  UInt64Value(UInt64Value&& from) noexcept
+    : UInt64Value() {
+    *this = ::std::move(from);
+  }
 
+  inline UInt64Value& operator=(UInt64Value&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -396,6 +462,9 @@
 
   void UnsafeArenaSwap(UInt64Value* other);
   void Swap(UInt64Value* other);
+  friend void swap(UInt64Value& a, UInt64Value& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -452,7 +521,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::uint64 value_;
@@ -472,7 +541,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  Int32Value(Int32Value&& from) noexcept
+    : Int32Value() {
+    *this = ::std::move(from);
+  }
 
+  inline Int32Value& operator=(Int32Value&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -491,6 +574,9 @@
 
   void UnsafeArenaSwap(Int32Value* other);
   void Swap(Int32Value* other);
+  friend void swap(Int32Value& a, Int32Value& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -547,7 +633,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::int32 value_;
@@ -567,7 +653,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  UInt32Value(UInt32Value&& from) noexcept
+    : UInt32Value() {
+    *this = ::std::move(from);
+  }
 
+  inline UInt32Value& operator=(UInt32Value&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -586,6 +686,9 @@
 
   void UnsafeArenaSwap(UInt32Value* other);
   void Swap(UInt32Value* other);
+  friend void swap(UInt32Value& a, UInt32Value& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -642,7 +745,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::uint32 value_;
@@ -662,7 +765,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  BoolValue(BoolValue&& from) noexcept
+    : BoolValue() {
+    *this = ::std::move(from);
+  }
 
+  inline BoolValue& operator=(BoolValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -681,6 +798,9 @@
 
   void UnsafeArenaSwap(BoolValue* other);
   void Swap(BoolValue* other);
+  friend void swap(BoolValue& a, BoolValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -737,7 +857,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   bool value_;
@@ -757,7 +877,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  StringValue(StringValue&& from) noexcept
+    : StringValue() {
+    *this = ::std::move(from);
+  }
 
+  inline StringValue& operator=(StringValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -776,6 +910,9 @@
 
   void UnsafeArenaSwap(StringValue* other);
   void Swap(StringValue* other);
+  friend void swap(StringValue& a, StringValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -827,6 +964,9 @@
   static const int kValueFieldNumber = 1;
   const ::std::string& value() const;
   void set_value(const ::std::string& value);
+  #if LANG_CXX11
+  void set_value(::std::string&& value);
+  #endif
   void set_value(const char* value);
   void set_value(const char* value, size_t size);
   ::std::string* mutable_value();
@@ -840,7 +980,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::internal::ArenaStringPtr value_;
@@ -860,7 +1000,21 @@
     CopyFrom(from);
     return *this;
   }
+  #if LANG_CXX11
+  BytesValue(BytesValue&& from) noexcept
+    : BytesValue() {
+    *this = ::std::move(from);
+  }
 
+  inline BytesValue& operator=(BytesValue&& from) noexcept {
+    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+  #endif
   inline ::google::protobuf::Arena* GetArena() const PROTOBUF_FINAL {
     return GetArenaNoVirtual();
   }
@@ -879,6 +1033,9 @@
 
   void UnsafeArenaSwap(BytesValue* other);
   void Swap(BytesValue* other);
+  friend void swap(BytesValue& a, BytesValue& b) {
+    a.Swap(&b);
+  }
 
   // implements Message ----------------------------------------------
 
@@ -930,6 +1087,9 @@
   static const int kValueFieldNumber = 1;
   const ::std::string& value() const;
   void set_value(const ::std::string& value);
+  #if LANG_CXX11
+  void set_value(::std::string&& value);
+  #endif
   void set_value(const char* value);
   void set_value(const void* value, size_t size);
   ::std::string* mutable_value();
@@ -943,7 +1103,7 @@
  private:
 
   ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
-  friend class ::google::protobuf::Arena;
+  template <typename T> friend class ::google::protobuf::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   ::google::protobuf::internal::ArenaStringPtr value_;
@@ -956,6 +1116,10 @@
 // ===================================================================
 
 #if !PROTOBUF_INLINE_NOT_IN_HEADERS
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
 // DoubleValue
 
 // double value = 1;
@@ -1097,6 +1261,14 @@
   value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
 }
+#if LANG_CXX11
+inline void StringValue::set_value(::std::string&& value) {
+  
+  value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.StringValue.value)
+}
+#endif
 inline void StringValue::set_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1168,6 +1340,14 @@
   value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, GetArenaNoVirtual());
   // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
 }
+#if LANG_CXX11
+inline void BytesValue::set_value(::std::string&& value) {
+  
+  value_.Set(
+    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual());
+  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.BytesValue.value)
+}
+#endif
 inline void BytesValue::set_value(const char* value) {
   GOOGLE_DCHECK(value != NULL);
   
@@ -1222,6 +1402,9 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.BytesValue.value)
 }
 
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
 #endif  // !PROTOBUF_INLINE_NOT_IN_HEADERS
 // -------------------------------------------------------------------
 
diff --git a/tests.sh b/tests.sh
index 710389b..5aba663 100755
--- a/tests.sh
+++ b/tests.sh
@@ -63,6 +63,7 @@
   # List all files that should be included in the distribution package.
   git ls-files | grep "^\(java\|python\|objectivec\|csharp\|js\|ruby\|php\|cmake\|examples\)" |\
     grep -v ".gitignore" | grep -v "java/compatibility_tests" |\
+    grep -v "cmake/protobuf.*\.pc\.cmake" |\
     grep -v "python/compatibility_tests" | grep -v "csharp/compatibility_tests" > dist.lst
   # Unzip the dist tar file.
   DIST=`ls *.tar.gz`
@@ -233,9 +234,10 @@
     sudo apt-get install -y python-software-properties # for apt-add-repository
     sudo apt-add-repository -y ppa:fkrull/deadsnakes
     sudo apt-get update -qq
-    sudo apt-get install -y python2.6 python2.6-dev
     sudo apt-get install -y python3.3 python3.3-dev
     sudo apt-get install -y python3.4 python3.4-dev
+    sudo apt-get install -y python3.5 python3.5-dev
+    sudo apt-get install -y python3.6 python3.6-dev
   fi
 }
 
@@ -277,7 +279,7 @@
   cd python
   # Only test Python 2.6/3.x on Linux
   if [ $(uname -s) == "Linux" ]; then
-    envlist=py\{26,27,33,34\}-python
+    envlist=py\{27,33,34,35,36\}-python
   else
     envlist=py27-python
   fi
@@ -291,10 +293,9 @@
   export LD_LIBRARY_PATH=../src/.libs # for Linux
   export DYLD_LIBRARY_PATH=../src/.libs # for OS X
   cd python
-  # Only test Python 2.6/3.x on Linux
+  # Only test Python 3.x on Linux
   if [ $(uname -s) == "Linux" ]; then
-    # py26 is currently disabled due to json_format
-    envlist=py\{27,33,34\}-cpp
+    envlist=py\{27,33,34,35,36\}-cpp
   else
     envlist=py27-cpp
   fi
@@ -346,7 +347,16 @@
   # Generate test file
   rm -rf generated
   mkdir generated
-  ../../src/protoc --php_out=generated proto/test.proto proto/test_include.proto proto/test_no_namespace.proto proto/test_prefix.proto
+  ../../src/protoc --php_out=generated   \
+    proto/test.proto                     \
+    proto/test_include.proto             \
+    proto/test_no_namespace.proto        \
+    proto/test_prefix.proto              \
+    proto/test_php_namespace.proto       \
+    proto/test_empty_php_namespace.proto \
+    proto/test_service.proto             \
+    proto/test_service_namespace.proto   \
+    proto/test_descriptors.proto
   pushd ../../src
   ./protoc --php_out=../php/tests/generated google/protobuf/empty.proto
   ./protoc --php_out=../php/tests/generated -I../php/tests -I. ../php/tests/proto/test_import_descriptor_proto.proto
@@ -397,27 +407,30 @@
   phpunit
   popd
   pushd conformance
-  # TODO(teboring): Add it back
-  # make test_php
+  make test_php
   popd
 }
 
 build_php5.5_c() {
   use_php 5.5
   wget https://phar.phpunit.de/phpunit-4.8.0.phar -O /usr/bin/phpunit
-  cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  # make test_php_c
+  pushd php/tests
+  /bin/bash ./test.sh
   popd
+  # TODO(teboring): Add it back
+  # pushd conformance
+  # make test_php_c
+  # popd
 }
 
 build_php5.5_zts_c() {
   use_php_zts 5.5
   wget https://phar.phpunit.de/phpunit-4.8.0.phar -O /usr/bin/phpunit
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  # make test_php_c
-  popd
+  # TODO(teboring): Add it back
+  # pushd conformance
+  # make test_php_zts_c
+  # popd
 }
 
 build_php5.6() {
@@ -429,8 +442,7 @@
   phpunit
   popd
   pushd conformance
-  # TODO(teboring): Add it back
-  # make test_php
+  make test_php
   popd
 }
 
@@ -438,18 +450,20 @@
   use_php 5.6
   wget https://phar.phpunit.de/phpunit-5.7.0.phar -O /usr/bin/phpunit
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
+  # TODO(teboring): Add it back
+  # pushd conformance
   # make test_php_c
-  popd
+  # popd
 }
 
 build_php5.6_zts_c() {
   use_php_zts 5.6
   wget https://phar.phpunit.de/phpunit-5.7.0.phar -O /usr/bin/phpunit
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  # make test_php_c
-  popd
+  # TODO(teboring): Add it back
+  # pushd conformance
+  # make test_php_zts_c
+  # popd
 }
 
 build_php5.6_mac() {
@@ -471,9 +485,10 @@
 
   # Test
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
+  # TODO(teboring): Add it back
+  # pushd conformance
   # make test_php_c
-  popd
+  # popd
 }
 
 build_php7.0() {
@@ -485,8 +500,7 @@
   phpunit
   popd
   pushd conformance
-  # TODO(teboring): Add it back
-  # make test_php
+  make test_php
   popd
 }
 
@@ -494,18 +508,20 @@
   use_php 7.0
   wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
+  # TODO(teboring): Add it back
+  # pushd conformance
   # make test_php_c
-  popd
+  # popd
 }
 
 build_php7.0_zts_c() {
   use_php_zts 7.0
   wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
-  # make test_php_c
-  popd
+  # TODO(teboring): Add it back.
+  # pushd conformance
+  # make test_php_zts_c
+  # popd
 }
 
 build_php7.0_mac() {
@@ -527,9 +543,10 @@
 
   # Test
   cd php/tests && /bin/bash ./test.sh && cd ../..
-  pushd conformance
+  # TODO(teboring): Add it back
+  # pushd conformance
   # make test_php_c
-  popd
+  # popd
 }
 
 build_php_compatibility() {
@@ -537,16 +554,51 @@
   php/tests/compatibility_test.sh
 }
 
+build_php7.1() {
+  use_php 7.1
+  pushd php
+  rm -rf vendor
+  cp -r /usr/local/vendor-7.1 vendor
+  wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
+  phpunit
+  popd
+  pushd conformance
+  # TODO(teboring): Add it back
+  # make test_php
+  popd
+}
+
+build_php7.1_c() {
+  use_php 7.1
+  wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
+  cd php/tests && /bin/bash ./test.sh && cd ../..
+  pushd conformance
+  # make test_php_c
+  popd
+}
+
+build_php7.1_zts_c() {
+  use_php_zts 7.1
+  wget https://phar.phpunit.de/phpunit-5.6.0.phar -O /usr/bin/phpunit
+  cd php/tests && /bin/bash ./test.sh && cd ../..
+  pushd conformance
+  # make test_php_c
+  popd
+}
+
 build_php_all_32() {
   build_php5.5
   build_php5.6
   build_php7.0
+  build_php7.1
   build_php5.5_c
   build_php5.6_c
   build_php7.0_c
+  build_php7.1_c
   build_php5.5_zts_c
   build_php5.6_zts_c
   build_php7.0_zts_c
+  build_php7.1_zts_c
 }
 
 build_php_all() {
@@ -593,6 +645,8 @@
             php7.0   |
             php7.0_c |
             php_compatibility |
+            php7.1   |
+            php7.1_c |
             php_all)
 "
   exit 1