Merge pull request #6133 from haon4/fix_update_pbh

Make sure to return the updated line when modifying .pb.h file
diff --git a/BUILD b/BUILD
index 8078b7e..f8ad0c5 100644
--- a/BUILD
+++ b/BUILD
@@ -999,3 +999,105 @@
     default_runtime = "",
     protoc = ":protoc",
 )
+
+################################################################################
+# Conformance tests
+################################################################################
+
+proto_library(
+    name = "test_messages_proto2_proto",
+    srcs = ["src/google/protobuf/test_messages_proto2.proto"],
+    visibility = ["//visibility:public"],
+)
+
+proto_library(
+    name = "test_messages_proto3_proto",
+    srcs = ["src/google/protobuf/test_messages_proto3.proto"],
+    deps = [
+        ":any_proto",
+        ":duration_proto",
+        ":field_mask_proto",
+        ":struct_proto",
+        ":timestamp_proto",
+        ":wrappers_proto",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+cc_proto_library(
+    name = "test_messages_proto2_proto_cc",
+    srcs = ["src/google/protobuf/test_messages_proto2.proto"],
+)
+
+cc_proto_library(
+    name = "test_messages_proto3_proto_cc",
+    srcs = ["src/google/protobuf/test_messages_proto3.proto"],
+    deps = [
+        ":cc_wkt_protos",
+    ],
+)
+
+proto_library(
+    name = "conformance_proto",
+    srcs = ["conformance/conformance.proto"],
+    visibility = ["//visibility:public"],
+)
+
+cc_proto_library(
+    name = "conformance_proto_cc",
+    srcs = ["conformance/conformance.proto"],
+)
+
+cc_library(
+    name = "jsoncpp",
+    hdrs = ["conformance/third_party/jsoncpp/json.h"],
+    srcs = ["conformance/third_party/jsoncpp/jsoncpp.cpp"],
+    includes = ["conformance"],
+)
+
+cc_library(
+    name = "conformance_test",
+    srcs = [
+        "conformance/conformance_test.cc",
+        "conformance/conformance_test_runner.cc",
+    ],
+    hdrs = [
+        "conformance/conformance_test.h",
+    ],
+    deps = [":conformance_proto_cc"],
+    includes = ["conformance", "src"],
+)
+
+cc_library(
+    name = "binary_json_conformance_suite",
+    srcs = ["conformance/binary_json_conformance_suite.cc"],
+    hdrs = ["conformance/binary_json_conformance_suite.h"],
+    deps = [
+        ":conformance_test",
+        ":jsoncpp",
+        ":test_messages_proto2_proto_cc",
+        ":test_messages_proto3_proto_cc",
+    ],
+)
+
+cc_library(
+    name = "text_format_conformance_suite",
+    srcs = ["conformance/text_format_conformance_suite.cc"],
+    hdrs = ["conformance/text_format_conformance_suite.h"],
+    deps = [
+        ":conformance_test",
+        ":test_messages_proto2_proto_cc",
+        ":test_messages_proto3_proto_cc",
+    ],
+)
+
+cc_library(
+    name = "conformance_test_runner",
+    srcs = ["conformance/conformance_test_main.cc"],
+    deps = [
+        ":binary_json_conformance_suite",
+        ":conformance_test",
+        ":text_format_conformance_suite",
+    ],
+    visibility = ["//visibility:public"],
+)
diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java
index 0fbd419..a20829e 100644
--- a/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -2119,11 +2119,12 @@
   /**
    * All descriptors implement this to make it easier to implement tools like {@code
    * DescriptorPool}.
-   *
-   * <p>This class is public so that the methods it exposes can be called from outside of this
-   * package. However, it should only be subclassed from nested classes of Descriptors.
    */
   public abstract static class GenericDescriptor {
+
+    // Private constructor to prevent subclasses outside of com.google.protobuf.Descriptors
+    private GenericDescriptor() {}
+
     public abstract Message toProto();
 
     public abstract String getName();
@@ -2593,20 +2594,23 @@
   }
 
   /** Describes an oneof of a message type. */
-  public static final class OneofDescriptor {
+  public static final class OneofDescriptor extends GenericDescriptor {
     /** Get the index of this descriptor within its parent. */
     public int getIndex() {
       return index;
     }
 
+    @Override
     public String getName() {
       return proto.getName();
     }
 
+    @Override
     public FileDescriptor getFile() {
       return file;
     }
 
+    @Override
     public String getFullName() {
       return fullName;
     }
@@ -2632,6 +2636,11 @@
       return fields[index];
     }
 
+    @Override
+    public OneofDescriptorProto toProto() {
+      return proto;
+    }
+
     private void setProto(final OneofDescriptorProto proto) {
       this.proto = proto;
     }
diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
index f294df3..e031839 100644
--- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -60,7 +60,7 @@
  * <p>Fundamentally the Rope algorithm represents the collection of pieces as a binary tree. BAP95
  * uses a Fibonacci bound relating depth to a minimum sequence length, sequences that are too short
  * relative to their depth cause a tree rebalance. More precisely, a tree of depth d is "balanced"
- * in the terminology of BAP95 if its length is at least F(d+2), where F(n) is the n-the Fibonacci
+ * in the terminology of BAP95 if its length is at least F(d+2), where F(n) is the n-th Fibonacci
  * number. Thus for depths 0, 1, 2, 3, 4, 5,... we have minimum lengths 1, 2, 3, 5, 8, 13,...
  *
  * @author carlanton@google.com (Carl Haverl)
diff --git a/js/binary/decoder_test.js b/js/binary/decoder_test.js
index b19e1d1..15a71d7 100644
--- a/js/binary/decoder_test.js
+++ b/js/binary/decoder_test.js
@@ -255,7 +255,6 @@
 
   /**
    * 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.
diff --git a/protobuf.pc.in b/protobuf.pc.in
index 282fef3..4e88b51 100644
--- a/protobuf.pc.in
+++ b/protobuf.pc.in
@@ -8,5 +8,5 @@
 Version: @VERSION@
 Libs: -L${libdir} -lprotobuf @PTHREAD_LIBS@
 Libs.private: @LIBS@
-Cflags: -I${includedir} @PTHREAD_CFLAGS@ @CXXFLAGS@
+Cflags: -I${includedir} @PTHREAD_CFLAGS@
 Conflicts: protobuf-lite
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index 42f7bcb..7309ac2 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -164,7 +164,10 @@
           warn_msg = ('Conflict register for file "' + file_name +
                       '": ' + desc_name +
                       ' is already defined in file "' +
-                      old_file + '"')
+                      old_file + '". Please fix the conflict by adding '
+                      'package name on the proto file, or use different '
+                      'name for the duplication. This warning will '
+                      'turn into error soon.')
           if isinstance(desc, descriptor.EnumValueDescriptor):
             warn_msg += ('\nNote: enum values appear as '
                          'siblings of the enum type instead of '
diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py
index 4d11662..7d7fe15 100644
--- a/python/google/protobuf/internal/well_known_types.py
+++ b/python/google/protobuf/internal/well_known_types.py
@@ -67,6 +67,8 @@
 class Any(object):
   """Class for Any Message type."""
 
+  __slots__ = ()
+
   def Pack(self, msg, type_url_prefix='type.googleapis.com/',
            deterministic=None):
     """Packs the specified message into current Any message."""
@@ -100,6 +102,8 @@
 class Timestamp(object):
   """Class for Timestamp message type."""
 
+  __slots__ = ()
+
   def ToJsonString(self):
     """Converts Timestamp to RFC 3339 date string format.
 
@@ -250,6 +254,8 @@
 class Duration(object):
   """Class for Duration message type."""
 
+  __slots__ = ()
+
   def ToJsonString(self):
     """Converts Duration to string format.
 
@@ -407,6 +413,8 @@
 class FieldMask(object):
   """Class for FieldMask message type."""
 
+  __slots__ = ()
+
   def ToJsonString(self):
     """Converts FieldMask to string according to proto3 JSON spec."""
     camelcase_paths = []
@@ -563,6 +571,8 @@
   In the tree, each leaf node represents a field path.
   """
 
+  __slots__ = ('_root',)
+
   def __init__(self, field_mask=None):
     """Initializes the tree by FieldMask."""
     self._root = {}
@@ -743,7 +753,7 @@
 class Struct(object):
   """Class for Struct message type."""
 
-  __slots__ = []
+  __slots__ = ()
 
   def __getitem__(self, key):
     return _GetStructValue(self.fields[key])
@@ -796,6 +806,8 @@
 class ListValue(object):
   """Class for ListValue message type."""
 
+  __slots__ = ()
+
   def __len__(self):
     return len(self.values)
 
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index eea20a1..778773b 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -56,7 +56,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Any_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fany_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index c979b56..bc07c60 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -129,7 +129,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 8bc1f40..63276de 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -812,7 +812,8 @@
   // built into real descriptors at initialization time.
   const std::string protodef_name =
       UniqueName("descriptor_table_protodef", file_, options_);
-  format("const char $1$[] =\n", protodef_name);
+  format("const char $1$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =\n",
+         protodef_name);
   format.Indent();
   FileDescriptorProto file_proto;
   file_->CopyTo(&file_proto);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 74a2440..1a01922 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -1535,7 +1535,7 @@
   format.Outdent();
   format("};");
   GOOGLE_DCHECK(!need_to_emit_cached_size);
-}
+}  // NOLINT(readability/fn_size)
 
 void MessageGenerator::GenerateInlineMethods(io::Printer* printer) {
   if (IsMapEntryMessage(descriptor_)) return;
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 18e3d08..c356f15 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -367,7 +367,9 @@
       "    synchronized ($classname$.class) {\n"
       "      parser = PARSER;\n"
       "      if (parser == null) {\n"
-      "        parser = new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n"
+      "        parser =\n"
+      "            new DefaultInstanceBasedParser<$classname$>(\n"
+      "                DEFAULT_INSTANCE);\n"
       "        PARSER = parser;\n"
       "      }\n"
       "    }\n"
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 4cb497f..7b0d9e6 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -163,7 +163,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 059498b..2503923 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -100,7 +100,7 @@
     const FileDescriptor* package_file_descriptor;
   };
 
-  inline Symbol() : type(NULL_SYMBOL) { descriptor = NULL; }
+  inline Symbol() : type(NULL_SYMBOL) { descriptor = nullptr; }
   inline bool IsNull() const { return type == NULL_SYMBOL; }
   inline bool IsType() const { return type == MESSAGE || type == ENUM; }
   inline bool IsAggregate() const {
@@ -127,7 +127,7 @@
   const FileDescriptor* GetFile() const {
     switch (type) {
       case NULL_SYMBOL:
-        return NULL;
+        return nullptr;
       case MESSAGE:
         return descriptor->file();
       case FIELD:
@@ -145,7 +145,7 @@
       case PACKAGE:
         return package_file_descriptor;
     }
-    return NULL;
+    return nullptr;
   }
 };
 
@@ -229,7 +229,7 @@
       return "unknown";
   }
   GOOGLE_LOG(FATAL) << "can't reach here.";
-  return NULL;
+  return nullptr;
 }
 
 static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
@@ -561,14 +561,14 @@
 
   // The stack of files which are currently being built.  Used to detect
   // cyclic dependencies when loading files from a DescriptorDatabase.  Not
-  // used when fallback_database_ == NULL.
+  // used when fallback_database_ == nullptr.
   std::vector<std::string> pending_files_;
 
   // A set of files which we have tried to load from the fallback database
   // and encountered errors.  We will not attempt to load them again during
   // execution of the current public API call, but for compatibility with
   // legacy clients, this is cleared at the beginning of each public API call.
-  // Not used when fallback_database_ == NULL.
+  // Not used when fallback_database_ == nullptr.
   HASH_SET<std::string> known_bad_files_;
 
   // A set of symbols which we have tried to load from the fallback database
@@ -594,7 +594,7 @@
   // stuff into the header.  Yay C++.
   Symbol FindByNameHelper(const DescriptorPool* pool, const std::string& name);
 
-  // These return NULL if not found.
+  // These return nullptr if not found.
   inline const FileDescriptor* FindFile(const std::string& key) const;
   inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
                                               int number) const;
@@ -631,6 +631,9 @@
   // The string is initialized to the given value for convenience.
   std::string* AllocateString(const std::string& value);
 
+  // Allocate empty string which will be destroyed when the pool is destroyed.
+  std::string* AllocateEmptyString();
+
   // Allocate a internal::call_once which will be destroyed when the pool is
   // destroyed.
   internal::once_flag* AllocateOnceDynamic();
@@ -640,7 +643,7 @@
   // in those cases we have to pass a dummy pointer of the right type as the
   // parameter instead of specifying the type explicitly.
   template <typename Type>
-  Type* AllocateMessage(Type* dummy = NULL);
+  Type* AllocateMessage(Type* dummy = nullptr);
 
   // Allocate a FileDescriptorTables object.
   FileDescriptorTables* AllocateFileTables();
@@ -718,7 +721,7 @@
                                        const std::string& name,
                                        const Symbol::Type type) const;
 
-  // These return NULL if not found.
+  // These return nullptr if not found.
   inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
                                                   int number) const;
   inline const FieldDescriptor* FindFieldByLowercaseName(
@@ -753,7 +756,7 @@
       std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
 
   // Returns the location denoted by the specified path through info,
-  // or NULL if not found.
+  // or nullptr if not found.
   // The value of info must be that of the corresponding FileDescriptor.
   // (Conceptually a pure function, but stateful as an optimisation.)
   const SourceCodeInfo_Location* GetSourceLocation(
@@ -901,7 +904,7 @@
 
 inline Symbol DescriptorPool::Tables::FindSymbol(const std::string& key) const {
   const Symbol* result = FindOrNull(symbols_by_name_, key.c_str());
-  if (result == NULL) {
+  if (result == nullptr) {
     return kNullSymbol;
   } else {
     return *result;
@@ -912,7 +915,7 @@
     const void* parent, const std::string& name) const {
   const Symbol* result = FindOrNull(
       symbols_by_parent_, PointerStringPair(parent, name.c_str()));
-  if (result == NULL) {
+  if (result == nullptr) {
     return kNullSymbol;
   } else {
     return *result;
@@ -930,13 +933,13 @@
 Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
                                                 const std::string& name) {
   MutexLockMaybe lock(pool->mutex_);
-  if (pool->fallback_database_ != NULL) {
+  if (pool->fallback_database_ != nullptr) {
     known_bad_symbols_.clear();
     known_bad_files_.clear();
   }
   Symbol result = FindSymbol(name);
 
-  if (result.IsNull() && pool->underlay_ != NULL) {
+  if (result.IsNull() && pool->underlay_ != nullptr) {
     // Symbol not found; check the underlay.
     result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
   }
@@ -964,7 +967,7 @@
 const void* FileDescriptorTables::FindParentForFieldsByMap(
     const FieldDescriptor* field) const {
   if (field->is_extension()) {
-    if (field->extension_scope() == NULL) {
+    if (field->extension_scope() == nullptr) {
       return field->file();
     } else {
       return field->extension_scope();
@@ -1035,7 +1038,7 @@
   {
     const EnumValueDescriptor* desc = FindPtrOrNull(
         enum_values_by_number_, std::make_pair(parent, number));
-    if (desc != NULL) {
+    if (desc != nullptr) {
       return desc;
     }
   }
@@ -1044,7 +1047,7 @@
     ReaderMutexLock l(&unknown_enum_values_mu_);
     const EnumValueDescriptor* desc = FindPtrOrNull(
         unknown_enum_values_by_number_, std::make_pair(parent, number));
-    if (desc != NULL) {
+    if (desc != nullptr) {
       return desc;
     }
   }
@@ -1054,7 +1057,7 @@
     WriterMutexLock l(&unknown_enum_values_mu_);
     const EnumValueDescriptor* desc = FindPtrOrNull(
         unknown_enum_values_by_number_, std::make_pair(parent, number));
-    if (desc != NULL) {
+    if (desc != nullptr) {
       return desc;
     }
 
@@ -1195,6 +1198,12 @@
   return result;
 }
 
+std::string* DescriptorPool::Tables::AllocateEmptyString() {
+  std::string* result = new std::string();
+  strings_.push_back(result);
+  return result;
+}
+
 internal::once_flag* DescriptorPool::Tables::AllocateOnceDynamic() {
   internal::once_flag* result = new internal::once_flag();
   once_dynamics_.push_back(result);
@@ -1219,7 +1228,7 @@
   // sophisticated way?  Probably not for the open source release, but for
   // internal use we could easily plug in one of our existing memory pool
   // allocators...
-  if (size == 0) return NULL;
+  if (size == 0) return nullptr;
 
   void* result = operator new(size);
   allocations_.push_back(result);
@@ -1249,10 +1258,10 @@
 DescriptorPool::ErrorCollector::~ErrorCollector() {}
 
 DescriptorPool::DescriptorPool()
-    : mutex_(NULL),
-      fallback_database_(NULL),
-      default_error_collector_(NULL),
-      underlay_(NULL),
+    : mutex_(nullptr),
+      fallback_database_(nullptr),
+      default_error_collector_(nullptr),
+      underlay_(nullptr),
       tables_(new Tables),
       enforce_dependencies_(true),
       lazily_build_dependencies_(false),
@@ -1265,7 +1274,7 @@
     : mutex_(new internal::WrappedMutex),
       fallback_database_(fallback_database),
       default_error_collector_(error_collector),
-      underlay_(NULL),
+      underlay_(nullptr),
       tables_(new Tables),
       enforce_dependencies_(true),
       lazily_build_dependencies_(false),
@@ -1274,9 +1283,9 @@
       disallow_enforce_utf8_(false) {}
 
 DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
-    : mutex_(NULL),
-      fallback_database_(NULL),
-      default_error_collector_(NULL),
+    : mutex_(nullptr),
+      fallback_database_(nullptr),
+      default_error_collector_(nullptr),
       underlay_(underlay),
       tables_(new Tables),
       enforce_dependencies_(true),
@@ -1286,7 +1295,7 @@
       disallow_enforce_utf8_(false) {}
 
 DescriptorPool::~DescriptorPool() {
-  if (mutex_ != NULL) delete mutex_;
+  if (mutex_ != nullptr) delete mutex_;
 }
 
 // DescriptorPool::BuildFile() defined later.
@@ -1306,7 +1315,7 @@
 
 bool DescriptorPool::InternalIsFileLoaded(const std::string& filename) const {
   MutexLockMaybe lock(mutex_);
-  return tables_->FindFile(filename) != NULL;
+  return tables_->FindFile(filename) != nullptr;
 }
 
 // generated_pool ====================================================
@@ -1380,48 +1389,48 @@
 const FileDescriptor* DescriptorPool::FindFileByName(
     const std::string& name) const {
   MutexLockMaybe lock(mutex_);
-  if (fallback_database_ != NULL) {
+  if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
   }
   const FileDescriptor* result = tables_->FindFile(name);
-  if (result != NULL) return result;
-  if (underlay_ != NULL) {
+  if (result != nullptr) return result;
+  if (underlay_ != nullptr) {
     result = underlay_->FindFileByName(name);
-    if (result != NULL) return result;
+    if (result != nullptr) return result;
   }
   if (TryFindFileInFallbackDatabase(name)) {
     result = tables_->FindFile(name);
-    if (result != NULL) return result;
+    if (result != nullptr) return result;
   }
-  return NULL;
+  return nullptr;
 }
 
 const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
     const std::string& symbol_name) const {
   MutexLockMaybe lock(mutex_);
-  if (fallback_database_ != NULL) {
+  if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
   }
   Symbol result = tables_->FindSymbol(symbol_name);
   if (!result.IsNull()) return result.GetFile();
-  if (underlay_ != NULL) {
+  if (underlay_ != nullptr) {
     const FileDescriptor* file_result =
         underlay_->FindFileContainingSymbol(symbol_name);
-    if (file_result != NULL) return file_result;
+    if (file_result != nullptr) return file_result;
   }
   if (TryFindSymbolInFallbackDatabase(symbol_name)) {
     result = tables_->FindSymbol(symbol_name);
     if (!result.IsNull()) return result.GetFile();
   }
-  return NULL;
+  return nullptr;
 }
 
 const Descriptor* DescriptorPool::FindMessageTypeByName(
     const std::string& name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
-  return (result.type == Symbol::MESSAGE) ? result.descriptor : NULL;
+  return (result.type == Symbol::MESSAGE) ? result.descriptor : nullptr;
 }
 
 const FieldDescriptor* DescriptorPool::FindFieldByName(
@@ -1431,7 +1440,7 @@
       !result.field_descriptor->is_extension()) {
     return result.field_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1441,93 +1450,120 @@
   if (result.type == Symbol::FIELD && result.field_descriptor->is_extension()) {
     return result.field_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
 const OneofDescriptor* DescriptorPool::FindOneofByName(
     const std::string& name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
-  return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL;
+  return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : nullptr;
 }
 
 const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
     const std::string& name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
-  return (result.type == Symbol::ENUM) ? result.enum_descriptor : NULL;
+  return (result.type == Symbol::ENUM) ? result.enum_descriptor : nullptr;
 }
 
 const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
     const std::string& name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
   return (result.type == Symbol::ENUM_VALUE) ? result.enum_value_descriptor
-                                             : NULL;
+                                             : nullptr;
 }
 
 const ServiceDescriptor* DescriptorPool::FindServiceByName(
     const std::string& name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
-  return (result.type == Symbol::SERVICE) ? result.service_descriptor : NULL;
+  return (result.type == Symbol::SERVICE) ? result.service_descriptor : nullptr;
 }
 
 const MethodDescriptor* DescriptorPool::FindMethodByName(
     const std::string& name) const {
   Symbol result = tables_->FindByNameHelper(this, name);
-  return (result.type == Symbol::METHOD) ? result.method_descriptor : NULL;
+  return (result.type == Symbol::METHOD) ? result.method_descriptor : nullptr;
 }
 
 const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
     const Descriptor* extendee, int number) const {
   // A faster path to reduce lock contention in finding extensions, assuming
   // most extensions will be cache hit.
-  if (mutex_ != NULL) {
+  if (mutex_ != nullptr) {
     ReaderMutexLock lock(mutex_);
     const FieldDescriptor* result = tables_->FindExtension(extendee, number);
-    if (result != NULL) {
+    if (result != nullptr) {
       return result;
     }
   }
   MutexLockMaybe lock(mutex_);
-  if (fallback_database_ != NULL) {
+  if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
   }
   const FieldDescriptor* result = tables_->FindExtension(extendee, number);
-  if (result != NULL) {
+  if (result != nullptr) {
     return result;
   }
-  if (underlay_ != NULL) {
+  if (underlay_ != nullptr) {
     result = underlay_->FindExtensionByNumber(extendee, number);
-    if (result != NULL) return result;
+    if (result != nullptr) return result;
   }
   if (TryFindExtensionInFallbackDatabase(extendee, number)) {
     result = tables_->FindExtension(extendee, number);
-    if (result != NULL) {
+    if (result != nullptr) {
       return result;
     }
   }
-  return NULL;
+  return nullptr;
+}
+
+const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
+    const Descriptor* extendee, const std::string& printable_name) const {
+  if (extendee->extension_range_count() == 0) return nullptr;
+  const FieldDescriptor* result = FindExtensionByName(printable_name);
+  if (result != nullptr && result->containing_type() == extendee) {
+    return result;
+  }
+  if (extendee->options().message_set_wire_format()) {
+    // MessageSet extensions may be identified by type name.
+    const Descriptor* type = FindMessageTypeByName(printable_name);
+    if (type != nullptr) {
+      // Look for a matching extension in the foreign type's scope.
+      const int type_extension_count = type->extension_count();
+      for (int i = 0; i < type_extension_count; i++) {
+        const FieldDescriptor* extension = type->extension(i);
+        if (extension->containing_type() == extendee &&
+            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
+            extension->is_optional() && extension->message_type() == type) {
+          // Found it.
+          return extension;
+        }
+      }
+    }
+  }
+  return nullptr;
 }
 
 void DescriptorPool::FindAllExtensions(
     const Descriptor* extendee,
     std::vector<const FieldDescriptor*>* out) const {
   MutexLockMaybe lock(mutex_);
-  if (fallback_database_ != NULL) {
+  if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
   }
 
   // Initialize tables_->extensions_ from the fallback database first
   // (but do this only once per descriptor).
-  if (fallback_database_ != NULL &&
+  if (fallback_database_ != nullptr &&
       tables_->extensions_loaded_from_db_.count(extendee) == 0) {
     std::vector<int> numbers;
     if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
                                                     &numbers)) {
       for (int i = 0; i < numbers.size(); ++i) {
         int number = numbers[i];
-        if (tables_->FindExtension(extendee, number) == NULL) {
+        if (tables_->FindExtension(extendee, number) == nullptr) {
           TryFindExtensionInFallbackDatabase(extendee, number);
         }
       }
@@ -1536,7 +1572,7 @@
   }
 
   tables_->FindAllExtensions(extendee, out);
-  if (underlay_ != NULL) {
+  if (underlay_ != nullptr) {
     underlay_->FindAllExtensions(extendee, out);
   }
 }
@@ -1546,8 +1582,8 @@
 
 const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const {
   const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key);
-  if (result == NULL || result->is_extension()) {
-    return NULL;
+  if (result == nullptr || result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1557,8 +1593,8 @@
     const std::string& key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByLowercaseName(this, key);
-  if (result == NULL || result->is_extension()) {
-    return NULL;
+  if (result == nullptr || result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1568,8 +1604,8 @@
     const std::string& key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByCamelcaseName(this, key);
-  if (result == NULL || result->is_extension()) {
-    return NULL;
+  if (result == nullptr || result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1582,7 +1618,7 @@
   if (!result.IsNull() && !result.field_descriptor->is_extension()) {
     return result.field_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1593,7 +1629,7 @@
   if (!result.IsNull()) {
     return result.oneof_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1604,7 +1640,7 @@
   if (!result.IsNull() && result.field_descriptor->is_extension()) {
     return result.field_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1612,8 +1648,8 @@
     const std::string& key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByLowercaseName(this, key);
-  if (result == NULL || !result->is_extension()) {
-    return NULL;
+  if (result == nullptr || !result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1623,8 +1659,8 @@
     const std::string& key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByCamelcaseName(this, key);
-  if (result == NULL || !result->is_extension()) {
-    return NULL;
+  if (result == nullptr || !result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1637,7 +1673,7 @@
   if (!result.IsNull()) {
     return result.descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1648,7 +1684,7 @@
   if (!result.IsNull()) {
     return result.enum_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1659,7 +1695,7 @@
   if (!result.IsNull()) {
     return result.enum_value_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1670,7 +1706,7 @@
   if (!result.IsNull()) {
     return result.enum_value_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1690,7 +1726,7 @@
   if (!result.IsNull()) {
     return result.method_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1700,7 +1736,7 @@
   if (!result.IsNull()) {
     return result.descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1710,7 +1746,7 @@
   if (!result.IsNull()) {
     return result.enum_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1721,7 +1757,7 @@
   if (!result.IsNull()) {
     return result.enum_value_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1731,7 +1767,7 @@
   if (!result.IsNull()) {
     return result.service_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -1741,15 +1777,15 @@
   if (!result.IsNull() && result.field_descriptor->is_extension()) {
     return result.field_descriptor;
   } else {
-    return NULL;
+    return nullptr;
   }
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
     const std::string& key) const {
   const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
-  if (result == NULL || !result->is_extension()) {
-    return NULL;
+  if (result == nullptr || !result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1758,8 +1794,8 @@
 const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
     const std::string& key) const {
   const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
-  if (result == NULL || !result->is_extension()) {
-    return NULL;
+  if (result == nullptr || !result->is_extension()) {
+    return nullptr;
   } else {
     return result;
   }
@@ -1784,7 +1820,7 @@
       return extension_range(i);
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber(
@@ -1795,7 +1831,7 @@
       return reserved_range(i);
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 const EnumDescriptor::ReservedRange*
@@ -1807,20 +1843,20 @@
       return reserved_range(i);
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 // -------------------------------------------------------------------
 
 bool DescriptorPool::TryFindFileInFallbackDatabase(
     const std::string& name) const {
-  if (fallback_database_ == NULL) return false;
+  if (fallback_database_ == nullptr) return false;
 
   if (tables_->known_bad_files_.count(name) > 0) return false;
 
   FileDescriptorProto file_proto;
   if (!fallback_database_->FindFileByName(name, &file_proto) ||
-      BuildFileFromDatabase(file_proto) == NULL) {
+      BuildFileFromDatabase(file_proto) == nullptr) {
     tables_->known_bad_files_.insert(name);
     return false;
   }
@@ -1842,7 +1878,7 @@
       return true;
     }
   }
-  if (underlay_ != NULL) {
+  if (underlay_ != nullptr) {
     // Check to see if any prefix of this symbol exists in the underlay.
     return underlay_->IsSubSymbolOfBuiltType(name);
   }
@@ -1851,7 +1887,7 @@
 
 bool DescriptorPool::TryFindSymbolInFallbackDatabase(
     const std::string& name) const {
-  if (fallback_database_ == NULL) return false;
+  if (fallback_database_ == nullptr) return false;
 
   if (tables_->known_bad_symbols_.count(name) > 0) return false;
 
@@ -1880,10 +1916,10 @@
       // Check if we've already built this file. If so, it apparently doesn't
       // contain the symbol we're looking for.  Some DescriptorDatabases
       // return false positives.
-      || tables_->FindFile(file_proto.name()) != NULL
+      || tables_->FindFile(file_proto.name()) != nullptr
 
       // Build the file.
-      || BuildFileFromDatabase(file_proto) == NULL) {
+      || BuildFileFromDatabase(file_proto) == nullptr) {
     tables_->known_bad_symbols_.insert(name);
     return false;
   }
@@ -1893,7 +1929,7 @@
 
 bool DescriptorPool::TryFindExtensionInFallbackDatabase(
     const Descriptor* containing_type, int field_number) const {
-  if (fallback_database_ == NULL) return false;
+  if (fallback_database_ == nullptr) return false;
 
   FileDescriptorProto file_proto;
   if (!fallback_database_->FindFileContainingExtension(
@@ -1901,14 +1937,14 @@
     return false;
   }
 
-  if (tables_->FindFile(file_proto.name()) != NULL) {
+  if (tables_->FindFile(file_proto.name()) != nullptr) {
     // We've already loaded this file, and it apparently doesn't contain the
     // extension we're looking for.  Some DescriptorDatabases return false
     // positives.
     return false;
   }
 
-  if (BuildFileFromDatabase(file_proto) == NULL) {
+  if (BuildFileFromDatabase(file_proto) == nullptr) {
     return false;
   }
 
@@ -2123,7 +2159,7 @@
     proto->set_default_value(DefaultValueAsString(false));
   }
 
-  if (containing_oneof() != NULL && !is_extension()) {
+  if (containing_oneof() != nullptr && !is_extension()) {
     proto->set_oneof_index(containing_oneof()->index());
   }
 
@@ -2268,7 +2304,7 @@
   } else {
     const Descriptor* option_descriptor =
         pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
-    if (option_descriptor == NULL) {
+    if (option_descriptor == nullptr) {
       // descriptor.proto is not in the pool. This means no custom options are
       // used so we are safe to proceed with the compiled options message type.
       return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
@@ -2459,7 +2495,7 @@
     contents.append("\n");
   }
 
-  const Descriptor* containing_type = NULL;
+  const Descriptor* containing_type = nullptr;
   for (int i = 0; i < extension_count(); i++) {
     if (extension(i)->containing_type() != containing_type) {
       if (i > 0) contents.append("}\n\n");
@@ -2535,7 +2571,7 @@
     enum_type(i)->DebugString(depth, contents, debug_string_options);
   }
   for (int i = 0; i < field_count(); i++) {
-    if (field(i)->containing_oneof() == NULL) {
+    if (field(i)->containing_oneof() == nullptr) {
       field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents,
                             debug_string_options);
     } else if (field(i)->containing_oneof()->field(0) == field(i)) {
@@ -2552,7 +2588,7 @@
   }
 
   // Group extensions by what they extend, so they can be printed out together.
-  const Descriptor* containing_type = NULL;
+  const Descriptor* containing_type = nullptr;
   for (int i = 0; i < extension_count(); i++) {
     if (extension(i)->containing_type() != containing_type) {
       if (i > 0) strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
@@ -2946,9 +2982,9 @@
 bool FieldDescriptor::is_packed() const {
   if (!is_packable()) return false;
   if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
-    return (options_ != NULL) && options_->packed();
+    return (options_ != nullptr) && options_->packed();
   } else {
-    return options_ == NULL || !options_->has_packed() || options_->packed();
+    return options_ == nullptr || !options_->has_packed() || options_->packed();
   }
 }
 
@@ -3008,7 +3044,7 @@
 
 void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
   if (is_extension()) {
-    if (extension_scope() == NULL) {
+    if (extension_scope() == nullptr) {
       output->push_back(FileDescriptorProto::kExtensionFieldNumber);
       output->push_back(index());
     } else {
@@ -3250,6 +3286,12 @@
       const typename DescriptorT::OptionsType& orig_options,
       DescriptorT* descriptor, const std::vector<int>& options_path);
 
+  // Allocate string on the string pool and initialize it to full proto name.
+  // Full proto name is "scope.proto_name" if scope is non-empty and
+  // "proto_name" otherwise.
+  std::string* AllocateNameString(const std::string& scope,
+                                  const std::string& proto_name);
+
   // These methods all have the same signature for the sake of the BUILD_ARRAY
   // macro, below.
   void BuildMessage(const DescriptorProto& proto, const Descriptor* parent,
@@ -3318,8 +3360,8 @@
   class OptionInterpreter {
    public:
     // Creates an interpreter that operates in the context of the pool of the
-    // specified builder, which must not be NULL. We don't take ownership of the
-    // builder.
+    // specified builder, which must not be nullptr. We don't take ownership of
+    // the builder.
     explicit OptionInterpreter(DescriptorBuilder* builder);
 
     ~OptionInterpreter();
@@ -3406,16 +3448,16 @@
       return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
     }
 
-    // We interpret against this builder's pool. Is never NULL. We don't own
+    // We interpret against this builder's pool. Is never nullptr. We don't own
     // this pointer.
     DescriptorBuilder* builder_;
 
-    // The options we're currently interpreting, or NULL if we're not in a call
-    // to InterpretOptions.
+    // The options we're currently interpreting, or nullptr if we're not in a
+    // call to InterpretOptions.
     const OptionsToInterpret* options_to_interpret_;
 
     // The option we're currently interpreting within options_to_interpret_, or
-    // NULL if we're not in a call to InterpretOptions(). This points to a
+    // nullptr if we're not in a call to InterpretOptions(). This points to a
     // submessage of the original option, not the mutable copy. Therefore we
     // can use it to find locations recorded by the parser.
     const UninterpretedOption* uninterpreted_option_;
@@ -3457,7 +3499,7 @@
     return descriptor->is_placeholder_;
   }
   static inline void assert_mutex_held(const DescriptorPool* pool) {
-    if (pool->mutex_ != NULL) {
+    if (pool->mutex_ != nullptr) {
       pool->mutex_->AssertHeld();
     }
   }
@@ -3505,23 +3547,23 @@
 
 const FileDescriptor* DescriptorPool::BuildFile(
     const FileDescriptorProto& proto) {
-  GOOGLE_CHECK(fallback_database_ == NULL)
+  GOOGLE_CHECK(fallback_database_ == nullptr)
       << "Cannot call BuildFile on a DescriptorPool that uses a "
          "DescriptorDatabase.  You must instead find a way to get your file "
          "into the underlying database.";
-  GOOGLE_CHECK(mutex_ == NULL);  // Implied by the above GOOGLE_CHECK.
+  GOOGLE_CHECK(mutex_ == nullptr);  // Implied by the above GOOGLE_CHECK.
   tables_->known_bad_symbols_.clear();
   tables_->known_bad_files_.clear();
-  return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto);
+  return DescriptorBuilder(this, tables_.get(), nullptr).BuildFile(proto);
 }
 
 const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
     const FileDescriptorProto& proto, ErrorCollector* error_collector) {
-  GOOGLE_CHECK(fallback_database_ == NULL)
+  GOOGLE_CHECK(fallback_database_ == nullptr)
       << "Cannot call BuildFile on a DescriptorPool that uses a "
          "DescriptorDatabase.  You must instead find a way to get your file "
          "into the underlying database.";
-  GOOGLE_CHECK(mutex_ == NULL);  // Implied by the above GOOGLE_CHECK.
+  GOOGLE_CHECK(mutex_ == nullptr);  // Implied by the above GOOGLE_CHECK.
   tables_->known_bad_symbols_.clear();
   tables_->known_bad_files_.clear();
   return DescriptorBuilder(this, tables_.get(), error_collector)
@@ -3532,12 +3574,12 @@
     const FileDescriptorProto& proto) const {
   mutex_->AssertHeld();
   if (tables_->known_bad_files_.count(proto.name()) > 0) {
-    return NULL;
+    return nullptr;
   }
   const FileDescriptor* result =
       DescriptorBuilder(this, tables_.get(), default_error_collector_)
           .BuildFile(proto);
-  if (result == NULL) {
+  if (result == nullptr) {
     tables_->known_bad_files_.insert(proto.name());
   }
   return result;
@@ -3550,7 +3592,7 @@
       tables_(tables),
       error_collector_(error_collector),
       had_errors_(false),
-      possible_undeclared_dependency_(NULL),
+      possible_undeclared_dependency_(nullptr),
       undefine_resolved_name_("") {}
 
 DescriptorBuilder::~DescriptorBuilder() {}
@@ -3559,7 +3601,7 @@
     const std::string& element_name, const Message& descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location,
     const std::string& error) {
-  if (error_collector_ == NULL) {
+  if (error_collector_ == nullptr) {
     if (!had_errors_) {
       GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
                  << "\":";
@@ -3582,12 +3624,12 @@
     const std::string& element_name, const Message& descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location,
     const std::string& undefined_symbol) {
-  if (possible_undeclared_dependency_ == NULL &&
+  if (possible_undeclared_dependency_ == nullptr &&
       undefine_resolved_name_.empty()) {
     AddError(element_name, descriptor, location,
              "\"" + undefined_symbol + "\" is not defined.");
   } else {
-    if (possible_undeclared_dependency_ != NULL) {
+    if (possible_undeclared_dependency_ != nullptr) {
       AddError(element_name, descriptor, location,
                "\"" + possible_undeclared_dependency_name_ +
                    "\" seems to be defined in \"" +
@@ -3614,7 +3656,7 @@
     const std::string& element_name, const Message& descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location,
     const std::string& error) {
-  if (error_collector_ == NULL) {
+  if (error_collector_ == nullptr) {
     GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
   } else {
     error_collector_->AddWarning(filename_, element_name, &descriptor, location,
@@ -3630,8 +3672,8 @@
 }
 
 void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
-  if (file == NULL || !dependencies_.insert(file).second) return;
-  for (int i = 0; file != NULL && i < file->public_dependency_count(); i++) {
+  if (file == nullptr || !dependencies_.insert(file).second) return;
+  for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
     RecordPublicDependencies(file->public_dependency(i));
   }
 }
@@ -3640,10 +3682,10 @@
     const DescriptorPool* pool, const std::string& name, bool build_it) {
   // If we are looking at an underlay, we must lock its mutex_, since we are
   // accessing the underlay's tables_ directly.
-  MutexLockMaybe lock((pool == pool_) ? NULL : pool->mutex_);
+  MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
 
   Symbol result = pool->tables_->FindSymbol(name);
-  if (result.IsNull() && pool->underlay_ != NULL) {
+  if (result.IsNull() && pool->underlay_ != nullptr) {
     // Symbol not found; check the underlay.
     result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
   }
@@ -3699,8 +3741,8 @@
     for (std::set<const FileDescriptor*>::const_iterator it =
              dependencies_.begin();
          it != dependencies_.end(); ++it) {
-      // Note:  A dependency may be NULL if it was not found or had errors.
-      if (*it != NULL && IsInPackage(*it, name)) return result;
+      // Note:  A dependency may be nullptr if it was not found or had errors.
+      if (*it != nullptr && IsInPackage(*it, name)) return result;
     }
   }
 
@@ -3712,7 +3754,7 @@
 Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
     const std::string& name, const std::string& relative_to,
     ResolveMode resolve_mode, bool build_it) {
-  possible_undeclared_dependency_ = NULL;
+  possible_undeclared_dependency_ = nullptr;
   undefine_resolved_name_.clear();
 
   if (!name.empty() && name[0] == '.') {
@@ -3945,7 +3987,7 @@
   placeholder->is_placeholder_ = true;
   placeholder->syntax_ = FileDescriptor::SYNTAX_PROTO2;
   placeholder->finished_building_ = true;
-  // All other fields are zero or NULL.
+  // All other fields are zero or nullptr.
 
   return placeholder;
 }
@@ -3953,9 +3995,9 @@
 bool DescriptorBuilder::AddSymbol(const std::string& full_name,
                                   const void* parent, const std::string& name,
                                   const Message& proto, Symbol symbol) {
-  // If the caller passed NULL for the parent, the symbol is at file scope.
+  // If the caller passed nullptr for the parent, the symbol is at file scope.
   // Use its file as the parent instead.
-  if (parent == NULL) parent = file_;
+  if (parent == nullptr) parent = file_;
 
   if (tables_->AddSymbol(full_name, symbol)) {
     if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
@@ -4076,7 +4118,7 @@
   // GCC.  Otherwise, the following two lines could be replaced with:
   //   typename DescriptorT::OptionsType* options =
   //       tables_->AllocateMessage<typename DescriptorT::OptionsType>();
-  typename DescriptorT::OptionsType* const dummy = NULL;
+  typename DescriptorT::OptionsType* const dummy = nullptr;
   typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
 
   if (!orig_options.IsInitialized()) {
@@ -4143,7 +4185,7 @@
 void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
                                        int index) {
   std::string message;
-  if (pool_->fallback_database_ == NULL) {
+  if (pool_->fallback_database_ == nullptr) {
     message = "Import \"" + proto.dependency(index) + "\" has not been loaded.";
   } else {
     message = "Import \"" + proto.dependency(index) +
@@ -4178,7 +4220,7 @@
   //   This is fine, because this idempotency "feature" really only exists to
   //   accommodate one hack in the proto1->proto2 migration layer.
   const FileDescriptor* existing_file = tables_->FindFile(filename_);
-  if (existing_file != NULL) {
+  if (existing_file != nullptr) {
     // File already in pool.  Compare the existing one to the input.
     if (ExistingFileMatchesProto(existing_file, proto)) {
       // They're identical.  Return the existing descriptor.
@@ -4200,7 +4242,7 @@
   for (int i = 0; i < tables_->pending_files_.size(); i++) {
     if (tables_->pending_files_[i] == proto.name()) {
       AddRecursiveImportError(proto, i);
-      return NULL;
+      return nullptr;
     }
   }
 
@@ -4208,12 +4250,13 @@
   // attempt to load all dependencies now, before checkpointing tables_.  This
   // avoids confusion with recursive checkpoints.
   if (!pool_->lazily_build_dependencies_) {
-    if (pool_->fallback_database_ != NULL) {
+    if (pool_->fallback_database_ != nullptr) {
       tables_->pending_files_.push_back(proto.name());
       for (int i = 0; i < proto.dependency_size(); i++) {
-        if (tables_->FindFile(proto.dependency(i)) == NULL &&
-            (pool_->underlay_ == NULL ||
-             pool_->underlay_->FindFileByName(proto.dependency(i)) == NULL)) {
+        if (tables_->FindFile(proto.dependency(i)) == nullptr &&
+            (pool_->underlay_ == nullptr ||
+             pool_->underlay_->FindFileByName(proto.dependency(i)) ==
+                 nullptr)) {
           // We don't care what this returns since we'll find out below anyway.
           pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
         }
@@ -4292,7 +4335,7 @@
              "A file with this name is already in the pool.");
     // Bail out early so that if this is actually the exact same file, we
     // don't end up reporting that every single symbol is already defined.
-    return NULL;
+    return nullptr;
   }
   if (!result->package().empty()) {
     AddPackage(result->package(), proto, result);
@@ -4312,8 +4355,8 @@
              sizeof(*result->dependencies_names_) * proto.dependency_size());
     }
   } else {
-    result->dependencies_once_ = NULL;
-    result->dependencies_names_ = NULL;
+    result->dependencies_once_ = nullptr;
+    result->dependencies_names_ = nullptr;
   }
   unused_dependency_.clear();
   std::set<int> weak_deps;
@@ -4326,7 +4369,7 @@
     }
 
     const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
-    if (dependency == NULL && pool_->underlay_ != NULL) {
+    if (dependency == nullptr && pool_->underlay_ != nullptr) {
       dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
     }
 
@@ -4334,10 +4377,10 @@
       // Recursive import.  dependency/result is not fully initialized, and it's
       // dangerous to try to do anything with it.  The recursive import error
       // will be detected and reported in DescriptorBuilder::BuildFile().
-      return NULL;
+      return nullptr;
     }
 
-    if (dependency == NULL) {
+    if (dependency == nullptr) {
       if (!pool_->lazily_build_dependencies_) {
         if (pool_->allow_unknown_ ||
             (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
@@ -4415,14 +4458,14 @@
   result->weak_dependency_count_ = weak_dependency_count;
 
   // Convert children.
-  BUILD_ARRAY(proto, result, message_type, BuildMessage, NULL);
-  BUILD_ARRAY(proto, result, enum_type, BuildEnum, NULL);
-  BUILD_ARRAY(proto, result, service, BuildService, NULL);
-  BUILD_ARRAY(proto, result, extension, BuildExtension, NULL);
+  BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr);
+  BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr);
+  BUILD_ARRAY(proto, result, service, BuildService, nullptr);
+  BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr);
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result);
   }
@@ -4470,22 +4513,31 @@
   }
 
   if (had_errors_) {
-    return NULL;
+    return nullptr;
   } else {
     return result;
   }
 }
 
 
+std::string* DescriptorBuilder::AllocateNameString(
+    const std::string& scope, const std::string& proto_name) {
+  std::string* full_name;
+  if (scope.empty()) {
+    full_name = tables_->AllocateString(proto_name);
+  } else {
+    full_name = tables_->AllocateEmptyString();
+    *full_name = StrCat(scope, ".", proto_name);
+  }
+  return full_name;
+}
+
 void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
                                      const Descriptor* parent,
                                      Descriptor* result) {
   const std::string& scope =
-      (parent == NULL) ? file_->package() : parent->full_name();
-  std::string* full_name = tables_->AllocateString(scope);
-  if (!full_name->empty()) full_name->append(1, '.');
-  full_name->append(proto.name());
-
+      (parent == nullptr) ? file_->package() : parent->full_name();
+  std::string* full_name = AllocateNameString(scope, proto.name());
   ValidateSymbolName(proto.name(), *full_name, proto);
 
   result->name_ = tables_->AllocateString(proto.name());
@@ -4516,7 +4568,7 @@
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     DescriptorProto::kOptionsFieldNumber);
@@ -4616,11 +4668,8 @@
                                               FieldDescriptor* result,
                                               bool is_extension) {
   const std::string& scope =
-      (parent == NULL) ? file_->package() : parent->full_name();
-  std::string* full_name = tables_->AllocateString(scope);
-  if (!full_name->empty()) full_name->append(1, '.');
-  full_name->append(proto.name());
-
+      (parent == nullptr) ? file_->package() : parent->full_name();
+  std::string* full_name = AllocateNameString(scope, proto.name());
   ValidateSymbolName(proto.name(), *full_name, proto);
 
   result->name_ = tables_->AllocateString(proto.name());
@@ -4676,14 +4725,14 @@
   }
 
   // Some of these may be filled in when cross-linking.
-  result->containing_type_ = NULL;
-  result->extension_scope_ = NULL;
-  result->message_type_ = NULL;
-  result->enum_type_ = NULL;
-  result->type_name_ = NULL;
-  result->type_once_ = NULL;
-  result->default_value_enum_ = NULL;
-  result->default_value_enum_name_ = NULL;
+  result->containing_type_ = nullptr;
+  result->extension_scope_ = nullptr;
+  result->message_type_ = nullptr;
+  result->enum_type_ = nullptr;
+  result->type_name_ = nullptr;
+  result->type_once_ = nullptr;
+  result->default_value_enum_ = nullptr;
+  result->default_value_enum_name_ = nullptr;
 
   result->has_default_value_ = proto.has_default_value();
   if (proto.has_default_value() && result->is_repeated()) {
@@ -4694,7 +4743,7 @@
 
   if (proto.has_type()) {
     if (proto.has_default_value()) {
-      char* end_pos = NULL;
+      char* end_pos = nullptr;
       switch (result->cpp_type()) {
         case FieldDescriptor::CPPTYPE_INT32:
           result->default_value_int32_ =
@@ -4755,7 +4804,7 @@
           break;
         case FieldDescriptor::CPPTYPE_ENUM:
           // This will be filled in when cross-linking.
-          result->default_value_enum_ = NULL;
+          result->default_value_enum_ = nullptr;
           break;
         case FieldDescriptor::CPPTYPE_STRING:
           if (result->type() == FieldDescriptor::TYPE_BYTES) {
@@ -4774,10 +4823,10 @@
           break;
       }
 
-      if (end_pos != NULL) {
-        // end_pos is only set non-NULL by the parsers for numeric types, above.
-        // This checks that the default was non-empty and had no extra junk
-        // after the end of the number.
+      if (end_pos != nullptr) {
+        // end_pos is only set non-null by the parsers for numeric types,
+        // above. This checks that the default was non-empty and had no extra
+        // junk after the end of the number.
         if (proto.default_value().empty() || *end_pos != '\0') {
           AddError(result->full_name(), proto,
                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
@@ -4811,7 +4860,7 @@
           break;
         case FieldDescriptor::CPPTYPE_ENUM:
           // This will be filled in when cross-linking.
-          result->default_value_enum_ = NULL;
+          result->default_value_enum_ = nullptr;
           break;
         case FieldDescriptor::CPPTYPE_STRING:
           result->default_value_string_ = &internal::GetEmptyString();
@@ -4863,7 +4912,7 @@
     }
 
     // Fill in later (maybe).
-    result->containing_oneof_ = NULL;
+    result->containing_oneof_ = nullptr;
   } else {
     if (proto.has_extendee()) {
       AddError(result->full_name(), proto,
@@ -4881,18 +4930,18 @@
                  strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
                                      "out of range for type \"$1\".",
                                      proto.oneof_index(), parent->name()));
-        result->containing_oneof_ = NULL;
+        result->containing_oneof_ = nullptr;
       } else {
         result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
       }
     } else {
-      result->containing_oneof_ = NULL;
+      result->containing_oneof_ = nullptr;
     }
   }
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     FieldDescriptorProto::kOptionsFieldNumber);
@@ -4923,7 +4972,7 @@
   }
 
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     std::vector<int> options_path;
     parent->GetLocationPath(&options_path);
@@ -4965,10 +5014,8 @@
 void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
                                    Descriptor* parent,
                                    OneofDescriptor* result) {
-  std::string* full_name = tables_->AllocateString(parent->full_name());
-  full_name->append(1, '.');
-  full_name->append(proto.name());
-
+  std::string* full_name =
+      AllocateNameString(parent->full_name(), proto.name());
   ValidateSymbolName(proto.name(), *full_name, proto);
 
   result->name_ = tables_->AllocateString(proto.name());
@@ -4978,11 +5025,11 @@
 
   // We need to fill these in later.
   result->field_count_ = 0;
-  result->fields_ = NULL;
+  result->fields_ = nullptr;
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     OneofDescriptorProto::kOptionsFieldNumber);
@@ -5061,11 +5108,8 @@
                                   const Descriptor* parent,
                                   EnumDescriptor* result) {
   const std::string& scope =
-      (parent == NULL) ? file_->package() : parent->full_name();
-  std::string* full_name = tables_->AllocateString(scope);
-  if (!full_name->empty()) full_name->append(1, '.');
-  full_name->append(proto.name());
-
+      (parent == nullptr) ? file_->package() : parent->full_name();
+  std::string* full_name = AllocateNameString(scope, proto.name());
   ValidateSymbolName(proto.name(), *full_name, proto);
 
   result->name_ = tables_->AllocateString(proto.name());
@@ -5099,7 +5143,7 @@
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     EnumDescriptorProto::kOptionsFieldNumber);
@@ -5166,8 +5210,10 @@
 
   // Note:  full_name for enum values is a sibling to the parent's name, not a
   //   child of it.
-  std::string* full_name = tables_->AllocateString(*parent->full_name_);
-  full_name->resize(full_name->size() - parent->name_->size());
+  std::string* full_name = tables_->AllocateEmptyString();
+  size_t scope_len = parent->full_name_->size() - parent->name_->size();
+  full_name->reserve(scope_len + result->name_->size());
+  full_name->append(parent->full_name_->data(), scope_len);
   full_name->append(*result->name_);
   result->full_name_ = full_name;
 
@@ -5175,7 +5221,7 @@
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     EnumValueDescriptorProto::kOptionsFieldNumber);
@@ -5200,7 +5246,7 @@
     // but it did conflict with some other symbol defined in the enum type's
     // scope.  Let's print an additional error to explain this.
     std::string outer_scope;
-    if (parent->containing_type() == NULL) {
+    if (parent->containing_type() == nullptr) {
       outer_scope = file_->package();
     } else {
       outer_scope = parent->containing_type()->full_name();
@@ -5229,10 +5275,7 @@
 void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
                                      const void* /* dummy */,
                                      ServiceDescriptor* result) {
-  std::string* full_name = tables_->AllocateString(file_->package());
-  if (!full_name->empty()) full_name->append(1, '.');
-  full_name->append(proto.name());
-
+  std::string* full_name = AllocateNameString(file_->package(), proto.name());
   ValidateSymbolName(proto.name(), *full_name, proto);
 
   result->name_ = tables_->AllocateString(proto.name());
@@ -5243,13 +5286,14 @@
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     ServiceDescriptorProto::kOptionsFieldNumber);
   }
 
-  AddSymbol(result->full_name(), NULL, result->name(), proto, Symbol(result));
+  AddSymbol(result->full_name(), nullptr, result->name(), proto,
+            Symbol(result));
 }
 
 void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
@@ -5258,9 +5302,8 @@
   result->name_ = tables_->AllocateString(proto.name());
   result->service_ = parent;
 
-  std::string* full_name = tables_->AllocateString(parent->full_name());
-  full_name->append(1, '.');
-  full_name->append(*result->name_);
+  std::string* full_name =
+      AllocateNameString(parent->full_name(), *result->name_);
   result->full_name_ = full_name;
 
   ValidateSymbolName(proto.name(), *full_name, proto);
@@ -5271,7 +5314,7 @@
 
   // Copy options.
   if (!proto.has_options()) {
-    result->options_ = NULL;  // Will set to default_instance later.
+    result->options_ = nullptr;  // Will set to default_instance later.
   } else {
     AllocateOptions(proto.options(), result,
                     MethodDescriptorProto::kOptionsFieldNumber);
@@ -5289,7 +5332,7 @@
 
 void DescriptorBuilder::CrossLinkFile(FileDescriptor* file,
                                       const FileDescriptorProto& proto) {
-  if (file->options_ == NULL) {
+  if (file->options_ == nullptr) {
     file->options_ = &FileOptions::default_instance();
   }
 
@@ -5312,7 +5355,7 @@
 
 void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
                                          const DescriptorProto& proto) {
-  if (message->options_ == NULL) {
+  if (message->options_ == nullptr) {
     message->options_ = &MessageOptions::default_instance();
   }
 
@@ -5342,7 +5385,7 @@
   // First count the number of fields per oneof.
   for (int i = 0; i < message->field_count(); i++) {
     const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
-    if (oneof_decl != NULL) {
+    if (oneof_decl != nullptr) {
       // Make sure fields belonging to the same oneof are defined consecutively.
       // This enables optimizations in codegens and reflection libraries to
       // skip fields in the oneof group, as only one of the field can be set.
@@ -5379,7 +5422,7 @@
         oneof_decl->field_count_);
     oneof_decl->field_count_ = 0;
 
-    if (oneof_decl->options_ == NULL) {
+    if (oneof_decl->options_ == nullptr) {
       oneof_decl->options_ = &OneofOptions::default_instance();
     }
   }
@@ -5387,7 +5430,7 @@
   // Then fill them in.
   for (int i = 0; i < message->field_count(); i++) {
     const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
-    if (oneof_decl != NULL) {
+    if (oneof_decl != nullptr) {
       OneofDescriptor* mutable_oneof_decl =
           &message->oneof_decls_[oneof_decl->index()];
       message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_;
@@ -5400,14 +5443,14 @@
 void DescriptorBuilder::CrossLinkExtensionRange(
     Descriptor::ExtensionRange* range,
     const DescriptorProto::ExtensionRange& proto) {
-  if (range->options_ == NULL) {
+  if (range->options_ == nullptr) {
     range->options_ = &ExtensionRangeOptions::default_instance();
   }
 }
 
 void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
                                        const FieldDescriptorProto& proto) {
-  if (field->options_ == NULL) {
+  if (field->options_ == nullptr) {
     field->options_ = &FieldOptions::default_instance();
   }
 
@@ -5435,7 +5478,7 @@
         field->containing_type()->FindExtensionRangeContainingNumber(
             field->number());
 
-    if (extension_range == NULL) {
+    if (extension_range == nullptr) {
       AddError(field->full_name(), proto,
                DescriptorPool::ErrorCollector::NUMBER,
                strings::Substitute("\"$0\" does not declare $1 as an "
@@ -5445,7 +5488,7 @@
     }
   }
 
-  if (field->containing_oneof() != NULL) {
+  if (field->containing_oneof() != nullptr) {
     if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
       // Note that this error will never happen when parsing .proto files.
       // It can only happen if you manually construct a FileDescriptorProto
@@ -5614,7 +5657,7 @@
     const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber(
         field->containing_type(), field->number());
     std::string containing_type_name =
-        field->containing_type() == NULL
+        field->containing_type() == nullptr
             ? "unknown"
             : field->containing_type()->full_name();
     if (field->is_extension()) {
@@ -5638,7 +5681,7 @@
         const FieldDescriptor* conflicting_field =
             tables_->FindExtension(field->containing_type(), field->number());
         std::string containing_type_name =
-            field->containing_type() == NULL
+            field->containing_type() == nullptr
                 ? "unknown"
                 : field->containing_type()->full_name();
         std::string error_msg = strings::Substitute(
@@ -5659,7 +5702,7 @@
 
 void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type,
                                       const EnumDescriptorProto& proto) {
-  if (enum_type->options_ == NULL) {
+  if (enum_type->options_ == nullptr) {
     enum_type->options_ = &EnumOptions::default_instance();
   }
 
@@ -5671,14 +5714,14 @@
 void DescriptorBuilder::CrossLinkEnumValue(
     EnumValueDescriptor* enum_value,
     const EnumValueDescriptorProto& /* proto */) {
-  if (enum_value->options_ == NULL) {
+  if (enum_value->options_ == nullptr) {
     enum_value->options_ = &EnumValueOptions::default_instance();
   }
 }
 
 void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service,
                                          const ServiceDescriptorProto& proto) {
-  if (service->options_ == NULL) {
+  if (service->options_ == nullptr) {
     service->options_ = &ServiceOptions::default_instance();
   }
 
@@ -5689,7 +5732,7 @@
 
 void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method,
                                         const MethodDescriptorProto& proto) {
-  if (method->options_ == NULL) {
+  if (method->options_ == nullptr) {
     method->options_ = &MethodOptions::default_instance();
   }
 
@@ -5747,7 +5790,8 @@
 static bool IsLite(const FileDescriptor* file) {
   // TODO(kenton):  I don't even remember how many of these conditions are
   //   actually possible.  I'm just being super-safe.
-  return file != NULL && &file->options() != &FileOptions::default_instance() &&
+  return file != nullptr &&
+         &file->options() != &FileOptions::default_instance() &&
          file->options().optimize_for() == FileOptions::LITE_RUNTIME;
 }
 
@@ -5938,7 +5982,7 @@
 
   // Note:  Default instance may not yet be initialized here, so we have to
   //   avoid reading from it.
-  if (field->containing_type_ != NULL &&
+  if (field->containing_type_ != nullptr &&
       &field->containing_type()->options() !=
           &MessageOptions::default_instance() &&
       field->containing_type()->options().message_set_wire_format()) {
@@ -5956,7 +6000,7 @@
   }
 
   // Lite extensions can only be of Lite types.
-  if (IsLite(field->file()) && field->containing_type_ != NULL &&
+  if (IsLite(field->file()) && field->containing_type_ != nullptr &&
       !IsLite(field->containing_type()->file())) {
     AddError(field->full_name(), proto,
              DescriptorPool::ErrorCollector::EXTENDEE,
@@ -6034,7 +6078,7 @@
     AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
              "Files with optimize_for = LITE_RUNTIME cannot define services "
              "unless you set both options cc_generic_services and "
-             "java_generic_sevices to false.");
+             "java_generic_services to false.");
   }
 
   VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
@@ -6235,7 +6279,7 @@
   // and clear them, since we're about to interpret them.
   const FieldDescriptor* uninterpreted_options_field =
       options->GetDescriptor()->FindFieldByName("uninterpreted_option");
-  GOOGLE_CHECK(uninterpreted_options_field != NULL)
+  GOOGLE_CHECK(uninterpreted_options_field != nullptr)
       << "No field named \"uninterpreted_option\" in the Options proto.";
   options->GetReflection()->ClearField(options, uninterpreted_options_field);
 
@@ -6246,7 +6290,7 @@
   const FieldDescriptor* original_uninterpreted_options_field =
       original_options->GetDescriptor()->FindFieldByName(
           "uninterpreted_option");
-  GOOGLE_CHECK(original_uninterpreted_options_field != NULL)
+  GOOGLE_CHECK(original_uninterpreted_options_field != nullptr)
       << "No field named \"uninterpreted_option\" in the Options proto.";
 
   const int num_uninterpreted_options =
@@ -6266,8 +6310,8 @@
     src_path.pop_back();
   }
   // Reset these, so we don't have any dangling pointers.
-  uninterpreted_option_ = NULL;
-  options_to_interpret_ = NULL;
+  uninterpreted_option_ = nullptr;
+  options_to_interpret_ = nullptr;
 
   if (!failed) {
     // InterpretSingleOption() added the interpreted options in the
@@ -6318,7 +6362,7 @@
         "\"uninterpreted_option\".");
   }
 
-  const Descriptor* options_descriptor = NULL;
+  const Descriptor* options_descriptor = nullptr;
   // Get the options message's descriptor from the builder's pool, so that we
   // get the version that knows about any extension options declared in the file
   // we're currently building. The descriptor should be there as long as the
@@ -6348,7 +6392,7 @@
   // through in |intermediate_fields|. As we go, we reconstruct the full option
   // name in |debug_msg_name|, for use in error messages.
   const Descriptor* descriptor = options_descriptor;
-  const FieldDescriptor* field = NULL;
+  const FieldDescriptor* field = nullptr;
   std::vector<const FieldDescriptor*> intermediate_fields;
   std::string debug_msg_name = "";
 
@@ -6381,7 +6425,7 @@
       field = descriptor->FindFieldByName(name_part);
     }
 
-    if (field == NULL) {
+    if (field == nullptr) {
       if (get_allow_unknown(builder_->pool_)) {
         // We can't find the option, but AllowUnknownDependencies() is enabled,
         // so we will just leave it as uninterpreted.
@@ -6609,7 +6653,7 @@
     const UninterpretedOption& uninterpreted_option, Message* options) {
   const FieldDescriptor* field =
       options->GetDescriptor()->FindFieldByName("uninterpreted_option");
-  GOOGLE_CHECK(field != NULL);
+  GOOGLE_CHECK(field != nullptr);
 
   options->GetReflection()
       ->AddMessage(options, field)
@@ -6824,7 +6868,7 @@
       }
       const EnumDescriptor* enum_type = option_field->enum_type();
       const std::string& value_name = uninterpreted_option_->identifier_value();
-      const EnumValueDescriptor* enum_value = NULL;
+      const EnumValueDescriptor* enum_value = nullptr;
 
       if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
         // Note that the enum value's fully-qualified name is a sibling of the
@@ -6857,7 +6901,7 @@
         enum_value = enum_type->FindValueByName(value_name);
       }
 
-      if (enum_value == NULL) {
+      if (enum_value == nullptr) {
         return AddValueError("Enum type \"" +
                              option_field->enum_type()->full_name() +
                              "\" has no value named \"" + value_name +
@@ -6929,7 +6973,7 @@
         }
       }
     }
-    return NULL;
+    return nullptr;
   }
 };
 
@@ -6972,7 +7016,7 @@
 
   const Descriptor* type = option_field->message_type();
   std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
-  GOOGLE_CHECK(dynamic.get() != NULL)
+  GOOGLE_CHECK(dynamic.get() != nullptr)
       << "Could not create an instance of " << option_field->DebugString();
 
   AggregateErrorCollector collector;
@@ -7201,6 +7245,15 @@
   return default_value_enum_;
 }
 
+const std::string& FieldDescriptor::PrintableNameForExtension() const {
+  const bool is_message_set_extension =
+      is_extension() &&
+      containing_type()->options().message_set_wire_format() &&
+      type() == FieldDescriptor::TYPE_MESSAGE && is_optional() &&
+      extension_scope() == message_type();
+  return is_message_set_extension ? message_type()->full_name() : full_name();
+}
+
 void FileDescriptor::InternalDependenciesOnceInit() const {
   GOOGLE_CHECK(finished_building_ == true);
   for (int i = 0; i < dependency_count(); i++) {
@@ -7216,7 +7269,7 @@
 
 const FileDescriptor* FileDescriptor::dependency(int index) const {
   if (dependencies_once_) {
-    // Do once init for all indicies, as it's unlikely only a single index would
+    // Do once init for all indices, as it's unlikely only a single index would
     // be called, and saves on internal::call_once allocations.
     internal::call_once(*dependencies_once_,
                         FileDescriptor::DependenciesOnceInit, this);
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 7a873f0..a51d93b 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -113,6 +113,7 @@
 
 // Defined in message.h
 class Message;
+class Reflection;
 
 // Defined in descriptor.cc
 class DescriptorBuilder;
@@ -122,11 +123,6 @@
 // Defined in unknown_field_set.h.
 class UnknownField;
 
-// Defined in generated_message_reflection.h.
-namespace internal {
-class GeneratedMessageReflection;
-}  // namespace internal
-
 // Defined in command_line_interface.cc
 namespace compiler {
 class CommandLineInterface;
@@ -188,10 +184,10 @@
   // Init function to be called at init time of a descriptor containing
   // a LazyDescriptor.
   void Init() {
-    descriptor_ = NULL;
-    name_ = NULL;
-    once_ = NULL;
-    file_ = NULL;
+    descriptor_ = nullptr;
+    name_ = nullptr;
+    once_ = nullptr;
+    file_ = nullptr;
   }
 
   // Sets the value of the descriptor if it is known during the descriptor
@@ -250,11 +246,11 @@
   // type array.
   int index() const;
 
-  // The .proto file in which this message type was defined.  Never NULL.
+  // The .proto file in which this message type was defined.  Never nullptr.
   const FileDescriptor* file() const;
 
   // If this Descriptor describes a nested type, this returns the type
-  // in which it is nested.  Otherwise, returns NULL.
+  // in which it is nested.  Otherwise, returns nullptr.
   const Descriptor* containing_type() const;
 
   // Get options for this message type.  These are specified in the .proto file
@@ -289,10 +285,10 @@
   // These are returned in the order they were defined in the .proto file.
   const FieldDescriptor* field(int index) const;
 
-  // Looks up a field by declared tag number.  Returns NULL if no such field
+  // Looks up a field by declared tag number.  Returns nullptr if no such field
   // exists.
   const FieldDescriptor* FindFieldByNumber(int number) const;
-  // Looks up a field by name.  Returns NULL if no such field exists.
+  // Looks up a field by name.  Returns nullptr if no such field exists.
   const FieldDescriptor* FindFieldByName(const std::string& name) const;
 
   // Looks up a field by lowercased name (as returned by lowercase_name()).
@@ -314,7 +310,7 @@
   // These are returned in the order they were defined in the .proto file.
   const OneofDescriptor* oneof_decl(int index) const;
 
-  // Looks up a oneof by name.  Returns NULL if no such oneof exists.
+  // Looks up a oneof by name.  Returns nullptr if no such oneof exists.
   const OneofDescriptor* FindOneofByName(const std::string& name) const;
 
   // Nested type stuff -----------------------------------------------
@@ -325,7 +321,7 @@
   // These are returned in the order they were defined in the .proto file.
   const Descriptor* nested_type(int index) const;
 
-  // Looks up a nested type by name.  Returns NULL if no such nested type
+  // Looks up a nested type by name.  Returns nullptr if no such nested type
   // exists.
   const Descriptor* FindNestedTypeByName(const std::string& name) const;
 
@@ -337,11 +333,12 @@
   // These are returned in the order they were defined in the .proto file.
   const EnumDescriptor* enum_type(int index) const;
 
-  // Looks up an enum type by name.  Returns NULL if no such enum type exists.
+  // Looks up an enum type by name.  Returns nullptr if no such enum type
+  // exists.
   const EnumDescriptor* FindEnumTypeByName(const std::string& name) const;
 
   // Looks up an enum value by name, among all enum types in this message.
-  // Returns NULL if no such value exists.
+  // Returns nullptr if no such value exists.
   const EnumValueDescriptor* FindEnumValueByName(const std::string& name) const;
 
   // Extensions ------------------------------------------------------
@@ -372,7 +369,7 @@
   // Returns true if the number is in one of the extension ranges.
   bool IsExtensionNumber(int number) const;
 
-  // Returns NULL if no extension range contains the given number.
+  // Returns nullptr if no extension range contains the given number.
   const ExtensionRange* FindExtensionRangeContainingNumber(int number) const;
 
   // The number of extensions -- extending *other* messages -- that were
@@ -414,7 +411,7 @@
   // Returns true if the number is in one of the reserved ranges.
   bool IsReservedNumber(int number) const;
 
-  // Returns NULL if no reserved range contains the given number.
+  // Returns nullptr if no reserved range contains the given number.
   const ReservedRange* FindReservedRangeContainingNumber(int number) const;
 
   // The number of reserved field names in this message type.
@@ -512,10 +509,8 @@
 // - Get the Descriptor or FileDescriptor for its containing scope, then
 //   call Descriptor::FindExtensionByName() or
 //   FileDescriptor::FindExtensionByName().
-// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber().
-// - Given a Reflection for a message object, call
-//   Reflection::FindKnownExtensionByName() or
-//   Reflection::FindKnownExtensionByNumber().
+// - Given a DescriptorPool, call DescriptorPool::FindExtensionByNumber() or
+//   DescriptorPool::FindExtensionByPrintableName().
 // Use DescriptorPool to construct your own descriptors.
 class PROTOBUF_EXPORT FieldDescriptor {
  public:
@@ -669,18 +664,18 @@
   // Get the field default value if cpp_type() == CPPTYPE_ENUM.  If no
   // explicit default was defined, the default is the first value defined
   // in the enum type (all enum types are required to have at least one value).
-  // This never returns NULL.
+  // This never returns nullptr.
   const EnumValueDescriptor* default_value_enum() const;
   // Get the field default value if cpp_type() == CPPTYPE_STRING.  If no
   // explicit default was defined, the default is the empty string.
   const std::string& default_value_string() const;
 
   // The Descriptor for the message of which this is a field.  For extensions,
-  // this is the extended type.  Never NULL.
+  // this is the extended type.  Never nullptr.
   const Descriptor* containing_type() const;
 
   // If the field is a member of a oneof, this is the one, otherwise this is
-  // NULL.
+  // nullptr.
   const OneofDescriptor* containing_oneof() const;
 
   // If the field is a member of a oneof, returns the index in that oneof.
@@ -688,7 +683,7 @@
 
   // An extension may be declared within the scope of another message.  If this
   // field is an extension (is_extension() is true), then extension_scope()
-  // returns that message, or NULL if the extension was declared at global
+  // returns that message, or nullptr if the extension was declared at global
   // scope.  If this is not an extension, extension_scope() is undefined (may
   // assert-fail).
   const Descriptor* extension_scope() const;
@@ -728,6 +723,21 @@
   // Return true iff [packed = true] is valid for fields of this type.
   static inline bool IsTypePackable(Type field_type);
 
+  // Returns full_name() except if the field is a MessageSet extension,
+  // in which case it returns the full_name() of the containing message type
+  // for backwards compatibility with proto1.
+  //
+  // A MessageSet extension is defined as an optional message extension
+  // whose containing type has the message_set_wire_format option set.
+  // This should be true of extensions of google.protobuf.bridge.MessageSet;
+  // by convention, such extensions are named "message_set_extension".
+  //
+  // The opposite operation (looking up an extension's FieldDescriptor given
+  // its printable name) can be accomplished with
+  //     message->file()->pool()->FindExtensionByPrintableName(message, name)
+  // where the extension extends "message".
+  const std::string& PrintableNameForExtension() const;
+
   // Source Location ---------------------------------------------------
 
   // Updates |*out_location| to the source location of the complete
@@ -840,7 +850,7 @@
   // Index of this oneof within the message's oneof array.
   int index() const;
 
-  // The .proto file in which this oneof was defined.  Never NULL.
+  // The .proto file in which this oneof was defined.  Never nullptr.
   const FileDescriptor* file() const;
   // The Descriptor for the message containing this oneof.
   const Descriptor* containing_type() const;
@@ -918,7 +928,7 @@
   // Index of this enum within the file or containing message's enum array.
   int index() const;
 
-  // The .proto file in which this enum type was defined.  Never NULL.
+  // The .proto file in which this enum type was defined.  Never nullptr.
   const FileDescriptor* file() const;
 
   // The number of values for this EnumDescriptor.  Guaranteed to be greater
@@ -928,14 +938,14 @@
   // These are returned in the order they were defined in the .proto file.
   const EnumValueDescriptor* value(int index) const;
 
-  // Looks up a value by name.  Returns NULL if no such value exists.
+  // Looks up a value by name.  Returns nullptr if no such value exists.
   const EnumValueDescriptor* FindValueByName(const std::string& name) const;
-  // Looks up a value by number.  Returns NULL if no such value exists.  If
+  // Looks up a value by number.  Returns nullptr if no such value exists.  If
   // multiple values have this number, the first one defined is returned.
   const EnumValueDescriptor* FindValueByNumber(int number) const;
 
   // If this enum type is nested in a message type, this is that message type.
-  // Otherwise, NULL.
+  // Otherwise, nullptr.
   const Descriptor* containing_type() const;
 
   // Get options for this enum type.  These are specified in the .proto file by
@@ -976,7 +986,7 @@
   // Returns true if the number is in one of the reserved ranges.
   bool IsReservedNumber(int number) const;
 
-  // Returns NULL if no reserved range contains the given number.
+  // Returns nullptr if no reserved range contains the given number.
   const EnumDescriptor::ReservedRange* FindReservedRangeContainingNumber(
       int number) const;
 
@@ -1008,9 +1018,9 @@
   // unknown. If a new descriptor is created, this is done in a thread-safe way,
   // and future calls will return the same value descriptor pointer.
   //
-  // This is private but is used by GeneratedMessageReflection (which is
-  // friended below) to return a valid EnumValueDescriptor from GetEnum() when
-  // this feature is enabled.
+  // This is private but is used by Reflection (which is friended below) to
+  // return a valid EnumValueDescriptor from GetEnum() when this feature is
+  // enabled.
   const EnumValueDescriptor* FindValueByNumberCreatingIfUnknown(
       int number) const;
 
@@ -1053,7 +1063,7 @@
   friend class EnumValueDescriptor;
   friend class FileDescriptor;
   friend class DescriptorPool;
-  friend class internal::GeneratedMessageReflection;
+  friend class Reflection;
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
 };
 
@@ -1077,9 +1087,9 @@
   // with C++ scoping rules for enums.
   const std::string& full_name() const;
 
-  // The .proto file in which this value was defined.  Never NULL.
+  // The .proto file in which this value was defined.  Never nullptr.
   const FileDescriptor* file() const;
-  // The type of this value.  Never NULL.
+  // The type of this value.  Never nullptr.
   const EnumDescriptor* type() const;
 
   // Get options for this enum value.  These are specified in the .proto file by
@@ -1150,7 +1160,7 @@
   // Index of this service within the file's services array.
   int index() const;
 
-  // The .proto file in which this service was defined.  Never NULL.
+  // The .proto file in which this service was defined.  Never nullptr.
   const FileDescriptor* file() const;
 
   // Get options for this service type.  These are specified in the .proto file
@@ -1232,9 +1242,9 @@
   // Index within the service's Descriptor.
   int index() const;
 
-  // The .proto file in which this method was defined.  Never NULL.
+  // The .proto file in which this method was defined.  Never nullptr.
   const FileDescriptor* file() const;
-  // Gets the service to which this method belongs.  Never NULL.
+  // Gets the service to which this method belongs.  Never nullptr.
   const ServiceDescriptor* service() const;
 
   // Gets the type of protocol message which this method accepts as input.
@@ -1319,7 +1329,7 @@
   const std::string& package() const;
 
   // The DescriptorPool in which this FileDescriptor and all its contents were
-  // allocated.  Never NULL.
+  // allocated.  Never nullptr.
   const DescriptorPool* pool() const;
 
   // The number of files imported by this one.
@@ -1386,16 +1396,17 @@
   Syntax syntax() const;
   static const char* SyntaxName(Syntax syntax);
 
-  // Find a top-level message type by name.  Returns NULL if not found.
+  // Find a top-level message type by name.  Returns nullptr if not found.
   const Descriptor* FindMessageTypeByName(const std::string& name) const;
-  // Find a top-level enum type by name.  Returns NULL if not found.
+  // Find a top-level enum type by name.  Returns nullptr if not found.
   const EnumDescriptor* FindEnumTypeByName(const std::string& name) const;
-  // Find an enum value defined in any top-level enum by name.  Returns NULL if
-  // not found.
+  // Find an enum value defined in any top-level enum by name.  Returns nullptr
+  // if not found.
   const EnumValueDescriptor* FindEnumValueByName(const std::string& name) const;
-  // Find a service definition by name.  Returns NULL if not found.
+  // Find a service definition by name.  Returns nullptr if not found.
   const ServiceDescriptor* FindServiceByName(const std::string& name) const;
-  // Find a top-level extension definition by name.  Returns NULL if not found.
+  // Find a top-level extension definition by name.  Returns nullptr if not
+  // found.
   const FieldDescriptor* FindExtensionByName(const std::string& name) const;
   // Similar to FindExtensionByName(), but searches by lowercased-name.  See
   // Descriptor::FindFieldByLowercaseName().
@@ -1555,7 +1566,7 @@
   //   in subsequent lookups in the DescriptorPool.
   class ErrorCollector;
   explicit DescriptorPool(DescriptorDatabase* fallback_database,
-                          ErrorCollector* error_collector = NULL);
+                          ErrorCollector* error_collector = nullptr);
 
   ~DescriptorPool();
 
@@ -1565,20 +1576,20 @@
   static const DescriptorPool* generated_pool();
 
 
-  // Find a FileDescriptor in the pool by file name.  Returns NULL if not
+  // Find a FileDescriptor in the pool by file name.  Returns nullptr if not
   // found.
   const FileDescriptor* FindFileByName(const std::string& name) const;
 
   // Find the FileDescriptor in the pool which defines the given symbol.
   // If any of the Find*ByName() methods below would succeed, then this is
   // equivalent to calling that method and calling the result's file() method.
-  // Otherwise this returns NULL.
+  // Otherwise this returns nullptr.
   const FileDescriptor* FindFileContainingSymbol(
       const std::string& symbol_name) const;
 
   // Looking up descriptors ------------------------------------------
   // These find descriptors by fully-qualified name.  These will find both
-  // top-level descriptors and nested descriptors.  They return NULL if not
+  // top-level descriptors and nested descriptors.  They return nullptr if not
   // found.
 
   const Descriptor* FindMessageTypeByName(const std::string& name) const;
@@ -1595,6 +1606,14 @@
   const FieldDescriptor* FindExtensionByNumber(const Descriptor* extendee,
                                                int number) const;
 
+  // Finds an extension of the given type by its printable name.
+  // See comments above PrintableNameForExtension() for the definition of
+  // "printable name".  The extendee must be a member of this DescriptorPool
+  // or one of its underlays.  Returns nullptr if there is no known message
+  // extension with the given printable name.
+  const FieldDescriptor* FindExtensionByPrintableName(
+      const Descriptor* extendee, const std::string& printable_name) const;
+
   // Finds extensions of extendee. The extensions will be appended to
   // out in an undefined order. Only extensions defined directly in
   // this DescriptorPool or one of its underlays are guaranteed to be
@@ -1658,7 +1677,7 @@
 
   // Convert the FileDescriptorProto to real descriptors and place them in
   // this DescriptorPool.  All dependencies of the file must already be in
-  // the pool.  Returns the resulting FileDescriptor, or NULL if there were
+  // the pool.  Returns the resulting FileDescriptor, or nullptr if there were
   // problems with the input (e.g. the message was invalid, or dependencies
   // were missing).  Details about the errors are written to GOOGLE_LOG(ERROR).
   const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
@@ -1824,8 +1843,8 @@
   Symbol NewPlaceholderWithMutexHeld(const std::string& name,
                                      PlaceholderType placeholder_type) const;
 
-  // If fallback_database_ is NULL, this is NULL.  Otherwise, this is a mutex
-  // which must be locked while accessing tables_.
+  // If fallback_database_ is nullptr, this is nullptr.  Otherwise, this is a
+  // mutex which must be locked while accessing tables_.
   internal::WrappedMutex* mutex_;
 
   // See constructor.
@@ -1989,11 +2008,11 @@
 // A few accessors differ from the macros...
 
 inline bool Descriptor::IsExtensionNumber(int number) const {
-  return FindExtensionRangeContainingNumber(number) != NULL;
+  return FindExtensionRangeContainingNumber(number) != nullptr;
 }
 
 inline bool Descriptor::IsReservedNumber(int number) const {
-  return FindReservedRangeContainingNumber(number) != NULL;
+  return FindReservedRangeContainingNumber(number) != nullptr;
 }
 
 inline bool Descriptor::IsReservedName(const std::string& name) const {
@@ -2012,7 +2031,7 @@
 }
 
 inline bool EnumDescriptor::IsReservedNumber(int number) const {
-  return FindReservedRangeContainingNumber(number) != NULL;
+  return FindReservedRangeContainingNumber(number) != nullptr;
 }
 
 inline bool EnumDescriptor::IsReservedName(const std::string& name) const {
@@ -2062,7 +2081,7 @@
 inline int FieldDescriptor::index() const {
   if (!is_extension_) {
     return static_cast<int>(this - containing_type()->fields_);
-  } else if (extension_scope_ != NULL) {
+  } else if (extension_scope_ != nullptr) {
     return static_cast<int>(this - extension_scope_->extensions_);
   } else {
     return static_cast<int>(this - file_->extensions_);
@@ -2070,7 +2089,7 @@
 }
 
 inline int Descriptor::index() const {
-  if (containing_type_ == NULL) {
+  if (containing_type_ == nullptr) {
     return static_cast<int>(this - file_->message_types_);
   } else {
     return static_cast<int>(this - containing_type_->nested_types_);
@@ -2086,7 +2105,7 @@
 }
 
 inline int EnumDescriptor::index() const {
-  if (containing_type_ == NULL) {
+  if (containing_type_ == nullptr) {
     return static_cast<int>(this - file_->enum_types_);
   } else {
     return static_cast<int>(this - containing_type_->enum_types_);
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 6924023..892b9c9 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -1012,7 +1012,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index d5d794f..548956e 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -369,6 +369,7 @@
 
 
 
+
   // 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).
@@ -496,6 +497,7 @@
   reserved 8;  // javalite_serializable
   reserved 9;  // javanano_as_lite
 
+
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 9f0b118..568e983 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -206,7 +206,7 @@
   void AddError(const std::string& filename, const std::string& element_name,
                 const Message* descriptor, ErrorLocation location,
                 const std::string& message) {
-    const char* location_name = NULL;
+    const char* location_name = nullptr;
     switch (location) {
       case NAME:
         location_name = "NAME";
@@ -251,7 +251,7 @@
   void AddWarning(const std::string& filename, const std::string& element_name,
                   const Message* descriptor, ErrorLocation location,
                   const std::string& message) {
-    const char* location_name = NULL;
+    const char* location_name = nullptr;
     switch (location) {
       case NAME:
         location_name = "NAME";
@@ -343,13 +343,13 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     bar_file_ = pool_.BuildFile(bar_file);
-    ASSERT_TRUE(bar_file_ != NULL);
+    ASSERT_TRUE(bar_file_ != nullptr);
 
     baz_file_ = pool_.BuildFile(baz_file);
-    ASSERT_TRUE(baz_file_ != NULL);
+    ASSERT_TRUE(baz_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->message_type_count());
     foo_message_ = foo_file_->message_type(0);
@@ -414,67 +414,67 @@
   EXPECT_EQ(foo_message_, foo_file_->FindMessageTypeByName("FooMessage"));
   EXPECT_EQ(bar_message_, bar_file_->FindMessageTypeByName("BarMessage"));
 
-  EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == NULL);
-  EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == NULL);
-  EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == NULL);
+  EXPECT_TRUE(foo_file_->FindMessageTypeByName("BarMessage") == nullptr);
+  EXPECT_TRUE(bar_file_->FindMessageTypeByName("FooMessage") == nullptr);
+  EXPECT_TRUE(baz_file_->FindMessageTypeByName("FooMessage") == nullptr);
 
-  EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == NULL);
-  EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == NULL);
+  EXPECT_TRUE(foo_file_->FindMessageTypeByName("NoSuchMessage") == nullptr);
+  EXPECT_TRUE(foo_file_->FindMessageTypeByName("FooEnum") == nullptr);
 }
 
 TEST_F(FileDescriptorTest, FindEnumTypeByName) {
   EXPECT_EQ(foo_enum_, foo_file_->FindEnumTypeByName("FooEnum"));
   EXPECT_EQ(bar_enum_, bar_file_->FindEnumTypeByName("BarEnum"));
 
-  EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == NULL);
-  EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == NULL);
-  EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == NULL);
+  EXPECT_TRUE(foo_file_->FindEnumTypeByName("BarEnum") == nullptr);
+  EXPECT_TRUE(bar_file_->FindEnumTypeByName("FooEnum") == nullptr);
+  EXPECT_TRUE(baz_file_->FindEnumTypeByName("FooEnum") == nullptr);
 
-  EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == NULL);
-  EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == NULL);
+  EXPECT_TRUE(foo_file_->FindEnumTypeByName("NoSuchEnum") == nullptr);
+  EXPECT_TRUE(foo_file_->FindEnumTypeByName("FooMessage") == nullptr);
 }
 
 TEST_F(FileDescriptorTest, FindEnumValueByName) {
   EXPECT_EQ(foo_enum_value_, foo_file_->FindEnumValueByName("FOO_ENUM_VALUE"));
   EXPECT_EQ(bar_enum_value_, bar_file_->FindEnumValueByName("BAR_ENUM_VALUE"));
 
-  EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == NULL);
-  EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
-  EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == NULL);
+  EXPECT_TRUE(foo_file_->FindEnumValueByName("BAR_ENUM_VALUE") == nullptr);
+  EXPECT_TRUE(bar_file_->FindEnumValueByName("FOO_ENUM_VALUE") == nullptr);
+  EXPECT_TRUE(baz_file_->FindEnumValueByName("FOO_ENUM_VALUE") == nullptr);
 
-  EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == NULL);
+  EXPECT_TRUE(foo_file_->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(foo_file_->FindEnumValueByName("FooMessage") == nullptr);
 }
 
 TEST_F(FileDescriptorTest, FindServiceByName) {
   EXPECT_EQ(foo_service_, foo_file_->FindServiceByName("FooService"));
   EXPECT_EQ(bar_service_, bar_file_->FindServiceByName("BarService"));
 
-  EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == NULL);
-  EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == NULL);
-  EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == NULL);
+  EXPECT_TRUE(foo_file_->FindServiceByName("BarService") == nullptr);
+  EXPECT_TRUE(bar_file_->FindServiceByName("FooService") == nullptr);
+  EXPECT_TRUE(baz_file_->FindServiceByName("FooService") == nullptr);
 
-  EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == NULL);
-  EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == NULL);
+  EXPECT_TRUE(foo_file_->FindServiceByName("NoSuchService") == nullptr);
+  EXPECT_TRUE(foo_file_->FindServiceByName("FooMessage") == nullptr);
 }
 
 TEST_F(FileDescriptorTest, FindExtensionByName) {
   EXPECT_EQ(foo_extension_, foo_file_->FindExtensionByName("foo_extension"));
   EXPECT_EQ(bar_extension_, bar_file_->FindExtensionByName("bar_extension"));
 
-  EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == NULL);
-  EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == NULL);
-  EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == NULL);
+  EXPECT_TRUE(foo_file_->FindExtensionByName("bar_extension") == nullptr);
+  EXPECT_TRUE(bar_file_->FindExtensionByName("foo_extension") == nullptr);
+  EXPECT_TRUE(baz_file_->FindExtensionByName("foo_extension") == nullptr);
 
-  EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == NULL);
-  EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == NULL);
+  EXPECT_TRUE(foo_file_->FindExtensionByName("no_such_extension") == nullptr);
+  EXPECT_TRUE(foo_file_->FindExtensionByName("FooMessage") == nullptr);
 }
 
 TEST_F(FileDescriptorTest, FindExtensionByNumber) {
   EXPECT_EQ(foo_extension_, pool_.FindExtensionByNumber(foo_message_, 1));
   EXPECT_EQ(bar_extension_, pool_.FindExtensionByNumber(bar_message_, 1));
 
-  EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == NULL);
+  EXPECT_TRUE(pool_.FindExtensionByNumber(foo_message_, 2) == nullptr);
 }
 
 
@@ -487,7 +487,7 @@
 
   // But if we change the file then it won't work.
   file.set_package("some.other.package");
-  EXPECT_TRUE(pool_.BuildFile(file) == NULL);
+  EXPECT_TRUE(pool_.BuildFile(file) == nullptr);
 }
 
 TEST_F(FileDescriptorTest, BuildAgainWithSyntax) {
@@ -498,7 +498,7 @@
   proto_syntax2.set_syntax("proto2");
 
   const FileDescriptor* proto2_descriptor = pool_.BuildFile(proto_syntax2);
-  EXPECT_TRUE(proto2_descriptor != NULL);
+  EXPECT_TRUE(proto2_descriptor != nullptr);
   EXPECT_EQ(proto2_descriptor, pool_.BuildFile(proto_syntax2));
 
   FileDescriptorProto implicit_proto2;
@@ -506,7 +506,7 @@
 
   const FileDescriptor* implicit_proto2_descriptor =
       pool_.BuildFile(implicit_proto2);
-  EXPECT_TRUE(implicit_proto2_descriptor != NULL);
+  EXPECT_TRUE(implicit_proto2_descriptor != nullptr);
   // We get the same FileDescriptor back if syntax param is explicitly
   // specified.
   implicit_proto2.set_syntax("proto2");
@@ -517,7 +517,7 @@
   proto_syntax3.set_syntax("proto3");
 
   const FileDescriptor* proto3_descriptor = pool_.BuildFile(proto_syntax3);
-  EXPECT_TRUE(proto3_descriptor != NULL);
+  EXPECT_TRUE(proto3_descriptor != nullptr);
   EXPECT_EQ(proto3_descriptor, pool_.BuildFile(proto_syntax3));
 }
 
@@ -530,7 +530,7 @@
     proto.set_syntax("proto2");
     DescriptorPool pool;
     const FileDescriptor* file = pool.BuildFile(proto);
-    EXPECT_TRUE(file != NULL);
+    EXPECT_TRUE(file != nullptr);
     EXPECT_EQ(FileDescriptor::SYNTAX_PROTO2, file->syntax());
     FileDescriptorProto other;
     file->CopyTo(&other);
@@ -541,7 +541,7 @@
     proto.set_syntax("proto3");
     DescriptorPool pool;
     const FileDescriptor* file = pool.BuildFile(proto);
-    EXPECT_TRUE(file != NULL);
+    EXPECT_TRUE(file != nullptr);
     EXPECT_EQ(FileDescriptor::SYNTAX_PROTO3, file->syntax());
     FileDescriptorProto other;
     file->CopyTo(&other);
@@ -603,7 +603,7 @@
     ASSERT_EQ("", error_collector.last_error());
     proto.set_name(name);
     const FileDescriptor* descriptor = pool.BuildFile(proto);
-    ASSERT_TRUE(descriptor != NULL) << proto.DebugString();
+    ASSERT_TRUE(descriptor != nullptr) << proto.DebugString();
     EXPECT_EQ(content, descriptor->DebugString());
   }
 }
@@ -726,16 +726,16 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     bar_file_ = pool_.BuildFile(bar_file);
-    ASSERT_TRUE(bar_file_ != NULL);
+    ASSERT_TRUE(bar_file_ != nullptr);
 
     map_file_ = pool_.BuildFile(map_file);
-    ASSERT_TRUE(map_file_ != NULL);
+    ASSERT_TRUE(map_file_ != nullptr);
 
     json_file_ = pool_.BuildFile(json_file);
-    ASSERT_TRUE(json_file_ != NULL);
+    ASSERT_TRUE(json_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->enum_type_count());
     enum_ = foo_file_->enum_type(0);
@@ -810,8 +810,8 @@
 }
 
 TEST_F(DescriptorTest, ContainingType) {
-  EXPECT_TRUE(message_->containing_type() == NULL);
-  EXPECT_TRUE(message2_->containing_type() == NULL);
+  EXPECT_TRUE(message_->containing_type() == nullptr);
+  EXPECT_TRUE(message2_->containing_type() == nullptr);
 }
 
 TEST_F(DescriptorTest, FieldsByIndex) {
@@ -832,14 +832,14 @@
   EXPECT_EQ(bar_, message_->FindFieldByName("bar"));
   EXPECT_EQ(baz_, message_->FindFieldByName("baz"));
   EXPECT_EQ(qux_, message_->FindFieldByName("qux"));
-  EXPECT_TRUE(message_->FindFieldByName("no_such_field") == NULL);
-  EXPECT_TRUE(message_->FindFieldByName("quux") == NULL);
+  EXPECT_TRUE(message_->FindFieldByName("no_such_field") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByName("quux") == nullptr);
 
   EXPECT_EQ(foo2_, message2_->FindFieldByName("foo"));
   EXPECT_EQ(bar2_, message2_->FindFieldByName("bar"));
   EXPECT_EQ(quux2_, message2_->FindFieldByName("quux"));
-  EXPECT_TRUE(message2_->FindFieldByName("baz") == NULL);
-  EXPECT_TRUE(message2_->FindFieldByName("qux") == NULL);
+  EXPECT_TRUE(message2_->FindFieldByName("baz") == nullptr);
+  EXPECT_TRUE(message2_->FindFieldByName("qux") == nullptr);
 }
 
 TEST_F(DescriptorTest, FindFieldByNumber) {
@@ -847,14 +847,14 @@
   EXPECT_EQ(bar_, message_->FindFieldByNumber(6));
   EXPECT_EQ(baz_, message_->FindFieldByNumber(500000000));
   EXPECT_EQ(qux_, message_->FindFieldByNumber(15));
-  EXPECT_TRUE(message_->FindFieldByNumber(837592) == NULL);
-  EXPECT_TRUE(message_->FindFieldByNumber(2) == NULL);
+  EXPECT_TRUE(message_->FindFieldByNumber(837592) == nullptr);
+  EXPECT_TRUE(message_->FindFieldByNumber(2) == nullptr);
 
   EXPECT_EQ(foo2_, message2_->FindFieldByNumber(1));
   EXPECT_EQ(bar2_, message2_->FindFieldByNumber(2));
   EXPECT_EQ(quux2_, message2_->FindFieldByNumber(6));
-  EXPECT_TRUE(message2_->FindFieldByNumber(15) == NULL);
-  EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == NULL);
+  EXPECT_TRUE(message2_->FindFieldByNumber(15) == nullptr);
+  EXPECT_TRUE(message2_->FindFieldByNumber(500000000) == nullptr);
 }
 
 TEST_F(DescriptorTest, FieldName) {
@@ -875,6 +875,34 @@
   EXPECT_EQ("corge.grault.TestMessage2.quux", quux2_->full_name());
 }
 
+TEST_F(DescriptorTest, PrintableNameIsFullNameForNonExtensionFields) {
+  EXPECT_EQ("TestMessage.foo", foo_->PrintableNameForExtension());
+  EXPECT_EQ("TestMessage.bar", bar_->PrintableNameForExtension());
+  EXPECT_EQ("TestMessage.baz", baz_->PrintableNameForExtension());
+  EXPECT_EQ("TestMessage.qux", qux_->PrintableNameForExtension());
+
+  EXPECT_EQ("corge.grault.TestMessage2.foo",
+            foo2_->PrintableNameForExtension());
+  EXPECT_EQ("corge.grault.TestMessage2.bar",
+            bar2_->PrintableNameForExtension());
+  EXPECT_EQ("corge.grault.TestMessage2.quux",
+            quux2_->PrintableNameForExtension());
+}
+
+TEST_F(DescriptorTest, PrintableNameIsFullNameForNonMessageSetExtension) {
+  EXPECT_EQ("protobuf_unittest.Aggregate.nested",
+            protobuf_unittest::Aggregate::descriptor()
+                ->FindExtensionByName("nested")
+                ->PrintableNameForExtension());
+}
+
+TEST_F(DescriptorTest, PrintableNameIsExtendingTypeForMessageSetExtension) {
+  EXPECT_EQ("protobuf_unittest.AggregateMessageSetElement",
+            protobuf_unittest::AggregateMessageSetElement::descriptor()
+                ->FindExtensionByName("message_set_extension")
+                ->PrintableNameForExtension());
+}
+
 TEST_F(DescriptorTest, FieldJsonName) {
   EXPECT_EQ("fieldName1", message4_->field(0)->json_name());
   EXPECT_EQ("fieldName2", message4_->field(1)->json_name());
@@ -990,17 +1018,17 @@
 }
 
 TEST_F(DescriptorTest, FieldMessageType) {
-  EXPECT_TRUE(foo_->message_type() == NULL);
-  EXPECT_TRUE(bar_->message_type() == NULL);
+  EXPECT_TRUE(foo_->message_type() == nullptr);
+  EXPECT_TRUE(bar_->message_type() == nullptr);
 
   EXPECT_EQ(foreign_, baz_->message_type());
   EXPECT_EQ(foreign_, qux_->message_type());
 }
 
 TEST_F(DescriptorTest, FieldEnumType) {
-  EXPECT_TRUE(foo_->enum_type() == NULL);
-  EXPECT_TRUE(baz_->enum_type() == NULL);
-  EXPECT_TRUE(qux_->enum_type() == NULL);
+  EXPECT_TRUE(foo_->enum_type() == nullptr);
+  EXPECT_TRUE(baz_->enum_type() == nullptr);
+  EXPECT_TRUE(qux_->enum_type() == nullptr);
 
   EXPECT_EQ(enum_, bar_->enum_type());
 }
@@ -1050,7 +1078,7 @@
 
     // Build the descriptors and get the pointers.
     baz_file_ = pool_.BuildFile(baz_file);
-    ASSERT_TRUE(baz_file_ != NULL);
+    ASSERT_TRUE(baz_file_ != nullptr);
 
     ASSERT_EQ(1, baz_file_->message_type_count());
     oneof_message_ = baz_file_->message_type(0);
@@ -1087,7 +1115,7 @@
   ASSERT_EQ(2, oneof_->field_count());
   EXPECT_EQ(b_, oneof_->field(0));
   EXPECT_EQ(c_, oneof_->field(1));
-  EXPECT_TRUE(a_->containing_oneof() == NULL);
+  EXPECT_TRUE(a_->containing_oneof() == nullptr);
   EXPECT_EQ(oneof_, b_->containing_oneof());
   EXPECT_EQ(oneof_, c_->containing_oneof());
 }
@@ -1095,7 +1123,7 @@
 TEST_F(OneofDescriptorTest, FindByName) {
   EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo"));
   EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar"));
-  EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL);
+  EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == nullptr);
 }
 
 // ===================================================================
@@ -1155,7 +1183,7 @@
                  FieldDescriptorProto::TYPE_INT32);
 
     file_ = pool_.BuildFile(file);
-    ASSERT_TRUE(file_ != NULL);
+    ASSERT_TRUE(file_ != nullptr);
     ASSERT_EQ(2, file_->message_type_count());
     message_ = file_->message_type(1);
     ASSERT_EQ("TestMessage", message_->name());
@@ -1213,10 +1241,10 @@
   EXPECT_EQ(message_->field(0), message_->FindFieldByLowercaseName("foo_foo"));
   EXPECT_EQ(message_->field(1), message_->FindFieldByLowercaseName("foobar"));
   EXPECT_EQ(message_->field(2), message_->FindFieldByLowercaseName("foobaz"));
-  EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == NULL);
-  EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == NULL);
-  EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == NULL);
-  EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == NULL);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("FooBar") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("fooBaz") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("bar_foo") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByLowercaseName("nosuchfield") == nullptr);
 
   EXPECT_EQ(message_->extension(0),
             message_->FindExtensionByLowercaseName("bar_foo"));
@@ -1224,28 +1252,28 @@
             message_->FindExtensionByLowercaseName("barbar"));
   EXPECT_EQ(message_->extension(2),
             message_->FindExtensionByLowercaseName("barbaz"));
-  EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("BarBar") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("barBaz") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("foo_foo") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByLowercaseName("nosuchfield") == nullptr);
 
   EXPECT_EQ(file_->extension(0),
             file_->FindExtensionByLowercaseName("baz_foo"));
   EXPECT_EQ(file_->extension(1), file_->FindExtensionByLowercaseName("bazbar"));
   EXPECT_EQ(file_->extension(2), file_->FindExtensionByLowercaseName("bazbaz"));
-  EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == NULL);
-  EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == NULL);
-  EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == NULL);
+  EXPECT_TRUE(file_->FindExtensionByLowercaseName("BazBar") == nullptr);
+  EXPECT_TRUE(file_->FindExtensionByLowercaseName("bazBaz") == nullptr);
+  EXPECT_TRUE(file_->FindExtensionByLowercaseName("nosuchfield") == nullptr);
 }
 
 TEST_F(StylizedFieldNamesTest, FindByCamelcaseName) {
   EXPECT_EQ(message_->field(0), message_->FindFieldByCamelcaseName("fooFoo"));
   EXPECT_EQ(message_->field(1), message_->FindFieldByCamelcaseName("fooBar"));
   EXPECT_EQ(message_->field(2), message_->FindFieldByCamelcaseName("fooBaz"));
-  EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == NULL);
-  EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == NULL);
-  EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == NULL);
-  EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == NULL);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("foo_foo") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("FooBar") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("barFoo") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByCamelcaseName("nosuchfield") == nullptr);
 
   EXPECT_EQ(message_->extension(0),
             message_->FindExtensionByCamelcaseName("barFoo"));
@@ -1253,17 +1281,17 @@
             message_->FindExtensionByCamelcaseName("barBar"));
   EXPECT_EQ(message_->extension(2),
             message_->FindExtensionByCamelcaseName("barBaz"));
-  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("bar_foo") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("BarBar") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("fooFoo") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByCamelcaseName("nosuchfield") == nullptr);
 
   EXPECT_EQ(file_->extension(0), file_->FindExtensionByCamelcaseName("bazFoo"));
   EXPECT_EQ(file_->extension(1), file_->FindExtensionByCamelcaseName("bazBar"));
   EXPECT_EQ(file_->extension(2), file_->FindExtensionByCamelcaseName("bazBaz"));
-  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == NULL);
-  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == NULL);
-  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == NULL);
+  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("baz_foo") == nullptr);
+  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("BazBar") == nullptr);
+  EXPECT_TRUE(file_->FindExtensionByCamelcaseName("nosuchfield") == nullptr);
 }
 
 // ===================================================================
@@ -1310,10 +1338,10 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     bar_file_ = pool_.BuildFile(bar_file);
-    ASSERT_TRUE(bar_file_ != NULL);
+    ASSERT_TRUE(bar_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->enum_type_count());
     enum_ = foo_file_->enum_type(0);
@@ -1356,8 +1384,8 @@
 }
 
 TEST_F(EnumDescriptorTest, ContainingType) {
-  EXPECT_TRUE(enum_->containing_type() == NULL);
-  EXPECT_TRUE(enum2_->containing_type() == NULL);
+  EXPECT_TRUE(enum_->containing_type() == nullptr);
+  EXPECT_TRUE(enum2_->containing_type() == nullptr);
 }
 
 TEST_F(EnumDescriptorTest, ValuesByIndex) {
@@ -1372,9 +1400,9 @@
   EXPECT_EQ(foo2_, enum2_->FindValueByName("FOO"));
   EXPECT_EQ(baz2_, enum2_->FindValueByName("BAZ"));
 
-  EXPECT_TRUE(enum_->FindValueByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(enum_->FindValueByName("BAZ") == NULL);
-  EXPECT_TRUE(enum2_->FindValueByName("BAR") == NULL);
+  EXPECT_TRUE(enum_->FindValueByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(enum_->FindValueByName("BAZ") == nullptr);
+  EXPECT_TRUE(enum2_->FindValueByName("BAR") == nullptr);
 }
 
 TEST_F(EnumDescriptorTest, FindValueByNumber) {
@@ -1383,9 +1411,9 @@
   EXPECT_EQ(foo2_, enum2_->FindValueByNumber(1));
   EXPECT_EQ(baz2_, enum2_->FindValueByNumber(3));
 
-  EXPECT_TRUE(enum_->FindValueByNumber(416) == NULL);
-  EXPECT_TRUE(enum_->FindValueByNumber(3) == NULL);
-  EXPECT_TRUE(enum2_->FindValueByNumber(2) == NULL);
+  EXPECT_TRUE(enum_->FindValueByNumber(416) == nullptr);
+  EXPECT_TRUE(enum_->FindValueByNumber(3) == nullptr);
+  EXPECT_TRUE(enum2_->FindValueByNumber(2) == nullptr);
 }
 
 TEST_F(EnumDescriptorTest, ValueName) {
@@ -1469,10 +1497,10 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     bar_file_ = pool_.BuildFile(bar_file);
-    ASSERT_TRUE(bar_file_ != NULL);
+    ASSERT_TRUE(bar_file_ != nullptr);
 
     ASSERT_EQ(6, foo_file_->message_type_count());
     foo_request_ = foo_file_->message_type(0);
@@ -1541,9 +1569,9 @@
   EXPECT_EQ(foo2_, service2_->FindMethodByName("Foo"));
   EXPECT_EQ(baz2_, service2_->FindMethodByName("Baz"));
 
-  EXPECT_TRUE(service_->FindMethodByName("NoSuchMethod") == NULL);
-  EXPECT_TRUE(service_->FindMethodByName("Baz") == NULL);
-  EXPECT_TRUE(service2_->FindMethodByName("Bar") == NULL);
+  EXPECT_TRUE(service_->FindMethodByName("NoSuchMethod") == nullptr);
+  EXPECT_TRUE(service_->FindMethodByName("Baz") == nullptr);
+  EXPECT_TRUE(service2_->FindMethodByName("Bar") == nullptr);
 }
 
 TEST_F(ServiceDescriptorTest, MethodName) {
@@ -1635,10 +1663,10 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     bar_file_ = pool_.BuildFile(bar_file);
-    ASSERT_TRUE(bar_file_ != NULL);
+    ASSERT_TRUE(bar_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->message_type_count());
     message_ = foo_file_->message_type(0);
@@ -1722,10 +1750,10 @@
 }
 
 TEST_F(NestedDescriptorTest, FindFieldByNameDoesntFindNestedTypes) {
-  EXPECT_TRUE(message_->FindFieldByName("Foo") == NULL);
-  EXPECT_TRUE(message_->FindFieldByName("Qux") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByName("Foo") == NULL);
-  EXPECT_TRUE(message_->FindExtensionByName("Qux") == NULL);
+  EXPECT_TRUE(message_->FindFieldByName("Foo") == nullptr);
+  EXPECT_TRUE(message_->FindFieldByName("Qux") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByName("Foo") == nullptr);
+  EXPECT_TRUE(message_->FindExtensionByName("Qux") == nullptr);
 }
 
 TEST_F(NestedDescriptorTest, FindNestedTypeByName) {
@@ -1734,11 +1762,11 @@
   EXPECT_EQ(foo2_, message2_->FindNestedTypeByName("Foo"));
   EXPECT_EQ(baz2_, message2_->FindNestedTypeByName("Baz"));
 
-  EXPECT_TRUE(message_->FindNestedTypeByName("NoSuchType") == NULL);
-  EXPECT_TRUE(message_->FindNestedTypeByName("Baz") == NULL);
-  EXPECT_TRUE(message2_->FindNestedTypeByName("Bar") == NULL);
+  EXPECT_TRUE(message_->FindNestedTypeByName("NoSuchType") == nullptr);
+  EXPECT_TRUE(message_->FindNestedTypeByName("Baz") == nullptr);
+  EXPECT_TRUE(message2_->FindNestedTypeByName("Bar") == nullptr);
 
-  EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == NULL);
+  EXPECT_TRUE(message_->FindNestedTypeByName("Qux") == nullptr);
 }
 
 TEST_F(NestedDescriptorTest, EnumName) {
@@ -1772,11 +1800,11 @@
   EXPECT_EQ(qux2_, message2_->FindEnumTypeByName("Qux"));
   EXPECT_EQ(quux2_, message2_->FindEnumTypeByName("Quux"));
 
-  EXPECT_TRUE(message_->FindEnumTypeByName("NoSuchType") == NULL);
-  EXPECT_TRUE(message_->FindEnumTypeByName("Quux") == NULL);
-  EXPECT_TRUE(message2_->FindEnumTypeByName("Baz") == NULL);
+  EXPECT_TRUE(message_->FindEnumTypeByName("NoSuchType") == nullptr);
+  EXPECT_TRUE(message_->FindEnumTypeByName("Quux") == nullptr);
+  EXPECT_TRUE(message2_->FindEnumTypeByName("Baz") == nullptr);
 
-  EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == NULL);
+  EXPECT_TRUE(message_->FindEnumTypeByName("Foo") == nullptr);
 }
 
 TEST_F(NestedDescriptorTest, FindEnumValueByName) {
@@ -1785,11 +1813,11 @@
   EXPECT_EQ(a2_, message2_->FindEnumValueByName("A"));
   EXPECT_EQ(c2_, message2_->FindEnumValueByName("C"));
 
-  EXPECT_TRUE(message_->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(message_->FindEnumValueByName("C") == NULL);
-  EXPECT_TRUE(message2_->FindEnumValueByName("B") == NULL);
+  EXPECT_TRUE(message_->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(message_->FindEnumValueByName("C") == nullptr);
+  EXPECT_TRUE(message2_->FindEnumValueByName("B") == nullptr);
 
-  EXPECT_TRUE(message_->FindEnumValueByName("Foo") == NULL);
+  EXPECT_TRUE(message_->FindEnumValueByName("Foo") == nullptr);
 }
 
 // ===================================================================
@@ -1845,7 +1873,7 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->enum_type_count());
     baz_ = foo_file_->enum_type(0);
@@ -1916,8 +1944,8 @@
   EXPECT_EQ(foo_, bar_->extension(0)->containing_type());
   EXPECT_EQ(foo_, bar_->extension(1)->containing_type());
 
-  EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == NULL);
-  EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == NULL);
+  EXPECT_TRUE(foo_file_->extension(0)->extension_scope() == nullptr);
+  EXPECT_TRUE(foo_file_->extension(1)->extension_scope() == nullptr);
   EXPECT_EQ(bar_, bar_->extension(0)->extension_scope());
   EXPECT_EQ(bar_, bar_->extension(1)->extension_scope());
 };
@@ -1941,9 +1969,38 @@
   EXPECT_EQ(bar_->extension(0), bar_->FindExtensionByName("foo_message"));
   EXPECT_EQ(bar_->extension(1), bar_->FindExtensionByName("foo_group"));
 
-  EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == NULL);
-  EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == NULL);
-  EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == NULL);
+  EXPECT_TRUE(bar_->FindExtensionByName("no_such_extension") == nullptr);
+  EXPECT_TRUE(foo_->FindExtensionByName("foo_int32") == nullptr);
+  EXPECT_TRUE(foo_->FindExtensionByName("foo_message") == nullptr);
+}
+
+TEST_F(ExtensionDescriptorTest, FindExtensionByPrintableName) {
+  EXPECT_TRUE(pool_.FindExtensionByPrintableName(foo_, "no_such_extension") ==
+              nullptr);
+  EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "no_such_extension") ==
+              nullptr);
+
+  ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "Bar.foo_message") ==
+               nullptr);
+  ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "Bar.foo_group") ==
+               nullptr);
+  EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_message") ==
+              nullptr);
+  EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_group") == nullptr);
+  EXPECT_EQ(bar_->FindExtensionByName("foo_message"),
+            pool_.FindExtensionByPrintableName(foo_, "Bar.foo_message"));
+  EXPECT_EQ(bar_->FindExtensionByName("foo_group"),
+            pool_.FindExtensionByPrintableName(foo_, "Bar.foo_group"));
+
+  ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "foo_int32") ==
+               nullptr);
+  ASSERT_FALSE(pool_.FindExtensionByPrintableName(foo_, "foo_enum") == nullptr);
+  EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_int32") == nullptr);
+  EXPECT_TRUE(pool_.FindExtensionByPrintableName(bar_, "foo_enum") == nullptr);
+  EXPECT_EQ(foo_file_->FindExtensionByName("foo_int32"),
+            pool_.FindExtensionByPrintableName(foo_, "foo_int32"));
+  EXPECT_EQ(foo_file_->FindExtensionByName("foo_enum"),
+            pool_.FindExtensionByPrintableName(foo_, "foo_enum"));
 }
 
 TEST_F(ExtensionDescriptorTest, FindAllExtensions) {
@@ -1962,7 +2019,7 @@
   FileDescriptorProto file_proto;
   // Add "google/protobuf/descriptor.proto".
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
   // Add "foo.proto":
   //   import "google/protobuf/descriptor.proto";
   //   extend google.protobuf.FieldOptions {
@@ -1974,7 +2031,7 @@
   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
                FieldDescriptorProto::LABEL_OPTIONAL,
                FieldDescriptorProto::TYPE_INT32);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
   // Add "bar.proto":
   //   import "google/protobuf/descriptor.proto";
   //   extend google.protobuf.FieldOptions {
@@ -1988,7 +2045,7 @@
                FieldDescriptorProto::TYPE_INT32);
   // Currently we only generate a warning for conflicting extension numbers.
   // TODO(xiaofeng): Change it to an error.
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 }
 
 // ===================================================================
@@ -2017,7 +2074,7 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->message_type_count());
     foo_ = foo_file_->message_type(0);
@@ -2112,7 +2169,7 @@
 
     // Build the descriptors and get the pointers.
     foo_file_ = pool_.BuildFile(foo_file);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     ASSERT_EQ(3, foo_file_->enum_type_count());
     foo_ = foo_file_->enum_type(0);
@@ -2226,40 +2283,40 @@
     pool_.reset(new DescriptorPool());
     const FileDescriptor* file = pool_->BuildFile(file_proto);
 
-    if (file != NULL && file->message_type_count() == 1 &&
+    if (file != nullptr && file->message_type_count() == 1 &&
         file->message_type(0)->field_count() == 1) {
       return file->message_type(0)->field(0);
     } else {
-      return NULL;
+      return nullptr;
     }
   }
 
   const char* GetTypeNameForFieldType(FieldDescriptor::Type type) {
     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
-    return field != NULL ? field->type_name() : "";
+    return field != nullptr ? field->type_name() : "";
   }
 
   FieldDescriptor::CppType GetCppTypeForFieldType(FieldDescriptor::Type type) {
     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
-    return field != NULL ? field->cpp_type()
-                         : static_cast<FieldDescriptor::CppType>(0);
+    return field != nullptr ? field->cpp_type()
+                            : static_cast<FieldDescriptor::CppType>(0);
   }
 
   const char* GetCppTypeNameForFieldType(FieldDescriptor::Type type) {
     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
-    return field != NULL ? field->cpp_type_name() : "";
+    return field != nullptr ? field->cpp_type_name() : "";
   }
 
   const Descriptor* GetMessageDescriptorForFieldType(
       FieldDescriptor::Type type) {
     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
-    return field != NULL ? field->message_type() : NULL;
+    return field != nullptr ? field->message_type() : nullptr;
   }
 
   const EnumDescriptor* GetEnumDescriptorForFieldType(
       FieldDescriptor::Type type) {
     const FieldDescriptor* field = GetFieldDescriptorOfType(type);
-    return field != NULL ? field->enum_type() : NULL;
+    return field != nullptr ? field->enum_type() : nullptr;
   }
 
   std::unique_ptr<DescriptorPool> pool_;
@@ -2383,53 +2440,53 @@
 }
 
 TEST_F(MiscTest, MessageType) {
-  // Test that message_type() is NULL for non-aggregate fields
+  // Test that message_type() is nullptr for non-aggregate fields
 
   typedef FieldDescriptor FD;  // avoid ugly line wrapping
 
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING));
-  EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP));
-  EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32));
-  EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_INT64));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_UINT64));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_INT32));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_BOOL));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_STRING));
+  EXPECT_TRUE(nullptr != GetMessageDescriptorForFieldType(FD::TYPE_GROUP));
+  EXPECT_TRUE(nullptr != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_BYTES));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_UINT32));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_ENUM));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SINT32));
+  EXPECT_TRUE(nullptr == GetMessageDescriptorForFieldType(FD::TYPE_SINT64));
 }
 
 TEST_F(MiscTest, EnumType) {
-  // Test that enum_type() is NULL for non-enum fields
+  // Test that enum_type() is nullptr for non-enum fields
 
   typedef FieldDescriptor FD;  // avoid ugly line wrapping
 
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32));
-  EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32));
-  EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_INT64));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_UINT64));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_INT32));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_BOOL));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_STRING));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_GROUP));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_BYTES));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_UINT32));
+  EXPECT_TRUE(nullptr != GetEnumDescriptorForFieldType(FD::TYPE_ENUM));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SINT32));
+  EXPECT_TRUE(nullptr == GetEnumDescriptorForFieldType(FD::TYPE_SINT64));
 }
 
 TEST_F(MiscTest, DefaultValues) {
@@ -2492,7 +2549,7 @@
   // Build it.
   DescriptorPool pool;
   const FileDescriptor* file = pool.BuildFile(file_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
 
   ASSERT_EQ(1, file->enum_type_count());
   const EnumDescriptor* enum_type = file->enum_type(0);
@@ -2574,7 +2631,7 @@
   // Build the descriptors and get the pointers.
   DescriptorPool pool;
   const FileDescriptor* file = pool.BuildFile(file_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
 
   ASSERT_EQ(1, file->message_type_count());
   const Descriptor* message = file->message_type(0);
@@ -2644,13 +2701,13 @@
 
     // Collect pointers to stuff.
     bar_file_ = BuildFile(bar_proto);
-    ASSERT_TRUE(bar_file_ != NULL);
+    ASSERT_TRUE(bar_file_ != nullptr);
 
     ASSERT_EQ(1, bar_file_->message_type_count());
     bar_type_ = bar_file_->message_type(0);
 
     foo_file_ = BuildFile(foo_proto);
-    ASSERT_TRUE(foo_file_ != NULL);
+    ASSERT_TRUE(foo_file_ != nullptr);
 
     ASSERT_EQ(1, foo_file_->message_type_count());
     foo_type_ = foo_file_->message_type(0);
@@ -2672,7 +2729,7 @@
       }
     }
     GOOGLE_LOG(FATAL) << "Can't get here.";
-    return NULL;
+    return nullptr;
   }
 
   const FileDescriptor* bar_file_;
@@ -2699,7 +2756,7 @@
 
   // Placeholder files should not be findable.
   EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name()));
-  EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == NULL);
+  EXPECT_TRUE(pool_->FindFileByName(baz_file->name()) == nullptr);
 
   // Copy*To should not crash for placeholder files.
   FileDescriptorProto baz_file_proto;
@@ -2728,8 +2785,8 @@
 
   // Placeholder types should not be findable.
   EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name()));
-  EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == NULL);
-  EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == NULL);
+  EXPECT_TRUE(pool_->FindMessageTypeByName(baz_type->full_name()) == nullptr);
+  EXPECT_TRUE(pool_->FindEnumTypeByName(qux_type->full_name()) == nullptr);
 }
 
 TEST_P(AllowUnknownDependenciesTest, CopyTo) {
@@ -2777,7 +2834,7 @@
       &extension_proto));
   const FileDescriptor* file = BuildFile(extension_proto);
 
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
 
   ASSERT_EQ(1, file->extension_count());
   const Descriptor* extendee = file->extension(0)->containing_type();
@@ -2830,7 +2887,7 @@
       &option_proto));
 
   const FileDescriptor* file = BuildFile(option_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
 
   // Verify that no extension options were set, but they were left as
   // uninterpreted_options.
@@ -2872,7 +2929,7 @@
   // test.proto below.
   switch (mode()) {
     case NO_DATABASE: {
-      ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == NULL);
+      ASSERT_TRUE(pool_->BuildFile(undeclared_dep_proto) == nullptr);
       break;
     }
     case FALLBACK_DATABASE: {
@@ -2893,7 +2950,7 @@
       &test_proto));
 
   const FileDescriptor* file = BuildFile(test_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   GOOGLE_LOG(INFO) << file->DebugString();
 
   EXPECT_EQ(0, file->dependency_count());
@@ -2909,7 +2966,7 @@
   ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name());
   EXPECT_TRUE(quux_field->message_type()->is_placeholder());
   // The place holder type should not be findable.
-  ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL);
+  ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == nullptr);
 }
 
 INSTANTIATE_TEST_SUITE_P(DatabaseSource, AllowUnknownDependenciesTest,
@@ -2952,7 +3009,7 @@
 }
 
 TEST(CustomOptions, OptionTypes) {
-  const MessageOptions* options = NULL;
+  const MessageOptions* options = nullptr;
 
   options =
       &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options();
@@ -3068,11 +3125,11 @@
 
   FileDescriptorProto file_proto;
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   ASSERT_TRUE(TextFormat::ParseFromString(
       "name: \"custom_options_import.proto\" "
@@ -3108,7 +3165,7 @@
       &file_proto));
 
   const FileDescriptor* file = pool.BuildFile(file_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   EXPECT_EQ(1234, file->options().GetExtension(protobuf_unittest::file_opt1));
   EXPECT_TRUE(file->options().has_java_package());
   EXPECT_EQ("foo", file->options().java_package());
@@ -3126,11 +3183,11 @@
 
   FileDescriptorProto file_proto;
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   // The following represents the definition:
   //
@@ -3186,7 +3243,7 @@
       &file_proto));
 
   const FileDescriptor* file = pool.BuildFile(file_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   ASSERT_EQ(1, file->message_type_count());
 
   const MessageOptions& options = file->message_type(0)->options();
@@ -3203,11 +3260,11 @@
 
   FileDescriptorProto file_proto;
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   // The following represents the definition:
   //
@@ -3263,7 +3320,7 @@
       &file_proto));
 
   const FileDescriptor* file = pool.BuildFile(file_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   ASSERT_EQ(1, file->message_type_count());
 
   const MessageOptions& options = file->message_type(0)->options();
@@ -3283,11 +3340,11 @@
 
   FileDescriptorProto file_proto;
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   // The following represents the definition:
   //
@@ -3343,7 +3400,7 @@
       &file_proto));
 
   const FileDescriptor* file = pool.BuildFile(file_proto);
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   ASSERT_EQ(1, file->message_type_count());
 
   const MessageOptions& options = file->message_type(0)->options();
@@ -3405,11 +3462,11 @@
 
   FileDescriptorProto file_proto;
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   protobuf_unittest::TestMessageWithCustomOptions::descriptor()->file()->CopyTo(
       &file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   pool.AddUnusedImportTrackFile("custom_options_import.proto");
   ASSERT_TRUE(TextFormat::ParseFromString(
@@ -3431,7 +3488,7 @@
 
   FileDescriptorProto file_proto;
   MessageOptions::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   // Create a new file descriptor proto containing a subset of the
   // messages defined in google/protobuf/unittest_custom_options.proto.
@@ -3471,7 +3528,7 @@
                                   test_message_type->mutable_options()));
 
   // Adding the file descriptor to the pool should fail.
-  EXPECT_TRUE(pool.BuildFile(file_proto) == NULL);
+  EXPECT_TRUE(pool.BuildFile(file_proto) == nullptr);
 }
 
 // Test that FileDescriptor::DebugString() formats custom options correctly.
@@ -3480,7 +3537,7 @@
 
   FileDescriptorProto file_proto;
   MessageOptions::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   // Add "foo.proto":
   //   import "google/protobuf/descriptor.proto";
@@ -3532,7 +3589,7 @@
       "}",
       &file_proto));
   const FileDescriptor* descriptor = pool.BuildFile(file_proto);
-  ASSERT_TRUE(descriptor != NULL);
+  ASSERT_TRUE(descriptor != nullptr);
 
   EXPECT_EQ(2, descriptor->extension_count());
 
@@ -3575,7 +3632,7 @@
 
     MockErrorCollector error_collector;
     EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector) ==
-                NULL);
+                nullptr);
     EXPECT_EQ(expected_errors, error_collector.text_);
   }
 
@@ -3596,7 +3653,7 @@
   void BuildFileInTestPool(const FileDescriptor* file) {
     FileDescriptorProto file_proto;
     file->CopyTo(&file_proto);
-    ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL);
+    ASSERT_TRUE(pool_.BuildFile(file_proto) != nullptr);
   }
 
   // Build descriptor.proto in our test pool. This allows us to extend it in
@@ -5580,7 +5637,7 @@
 
       "foo.proto: Foo: NAME: Files with optimize_for = LITE_RUNTIME cannot "
       "define services unless you set both options cc_generic_services and "
-      "java_generic_sevices to false.\n");
+      "java_generic_services to false.\n");
 
   BuildFile(
       "name: \"bar.proto\" "
@@ -5656,7 +5713,7 @@
 
   {
     ScopedMemoryLog log;
-    EXPECT_TRUE(pool_.BuildFile(file_proto) == NULL);
+    EXPECT_TRUE(pool_.BuildFile(file_proto) == nullptr);
     errors = log.GetMessages(ERROR);
   }
 
@@ -6381,7 +6438,7 @@
   FileDescriptorProto file_proto;
   // Add "google/protobuf/descriptor.proto".
   FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
   // Add "foo.proto":
   //   import "google/protobuf/descriptor.proto";
   //   extend google.protobuf.FieldOptions {
@@ -6394,7 +6451,7 @@
   AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000,
                FieldDescriptorProto::LABEL_OPTIONAL,
                FieldDescriptorProto::TYPE_INT32);
-  ASSERT_TRUE(pool.BuildFile(file_proto) != NULL);
+  ASSERT_TRUE(pool.BuildFile(file_proto) != nullptr);
 
   // Copy and change the package of the descriptor.proto
   BuildFile(
@@ -6585,27 +6642,27 @@
   DescriptorPool pool(&database_);
 
   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
   EXPECT_EQ("foo.proto", foo->name());
   ASSERT_EQ(1, foo->message_type_count());
   EXPECT_EQ("Foo", foo->message_type(0)->name());
 
   EXPECT_EQ(foo, pool.FindFileByName("foo.proto"));
 
-  EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == NULL);
+  EXPECT_TRUE(pool.FindFileByName("no_such_file.proto") == nullptr);
 }
 
 TEST_F(DatabaseBackedPoolTest, FindDependencyBeforeDependent) {
   DescriptorPool pool(&database_);
 
   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
   EXPECT_EQ("foo.proto", foo->name());
   ASSERT_EQ(1, foo->message_type_count());
   EXPECT_EQ("Foo", foo->message_type(0)->name());
 
   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
-  ASSERT_TRUE(bar != NULL);
+  ASSERT_TRUE(bar != nullptr);
   EXPECT_EQ("bar.proto", bar->name());
   ASSERT_EQ(1, bar->message_type_count());
   EXPECT_EQ("Bar", bar->message_type(0)->name());
@@ -6618,13 +6675,13 @@
   DescriptorPool pool(&database_);
 
   const FileDescriptor* bar = pool.FindFileByName("bar.proto");
-  ASSERT_TRUE(bar != NULL);
+  ASSERT_TRUE(bar != nullptr);
   EXPECT_EQ("bar.proto", bar->name());
   ASSERT_EQ(1, bar->message_type_count());
   ASSERT_EQ("Bar", bar->message_type(0)->name());
 
   const FileDescriptor* foo = pool.FindFileByName("foo.proto");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
   EXPECT_EQ("foo.proto", foo->name());
   ASSERT_EQ(1, foo->message_type_count());
   ASSERT_EQ("Foo", foo->message_type(0)->name());
@@ -6637,36 +6694,36 @@
   DescriptorPool pool(&database_);
 
   const FileDescriptor* file = pool.FindFileContainingSymbol("Foo");
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   EXPECT_EQ("foo.proto", file->name());
   EXPECT_EQ(file, pool.FindFileByName("foo.proto"));
 
-  EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == NULL);
+  EXPECT_TRUE(pool.FindFileContainingSymbol("NoSuchSymbol") == nullptr);
 }
 
 TEST_F(DatabaseBackedPoolTest, FindMessageTypeByName) {
   DescriptorPool pool(&database_);
 
   const Descriptor* type = pool.FindMessageTypeByName("Foo");
-  ASSERT_TRUE(type != NULL);
+  ASSERT_TRUE(type != nullptr);
   EXPECT_EQ("Foo", type->name());
   EXPECT_EQ(type->file(), pool.FindFileByName("foo.proto"));
 
-  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchType") == nullptr);
 }
 
 TEST_F(DatabaseBackedPoolTest, FindExtensionByNumber) {
   DescriptorPool pool(&database_);
 
   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
 
   const FieldDescriptor* extension = pool.FindExtensionByNumber(foo, 5);
-  ASSERT_TRUE(extension != NULL);
+  ASSERT_TRUE(extension != nullptr);
   EXPECT_EQ("foo_ext", extension->name());
   EXPECT_EQ(extension->file(), pool.FindFileByName("bar.proto"));
 
-  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == NULL);
+  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 12) == nullptr);
 }
 
 TEST_F(DatabaseBackedPoolTest, FindAllExtensions) {
@@ -6692,7 +6749,7 @@
 
   {
     ScopedMemoryLog log;
-    EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
+    EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr);
     errors = log.GetMessages(ERROR);
   }
 
@@ -6704,7 +6761,7 @@
   MockErrorCollector error_collector;
   DescriptorPool pool(&error_database, &error_collector);
 
-  EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL);
+  EXPECT_TRUE(pool.FindFileByName("error.proto") == nullptr);
   EXPECT_EQ(
       "error.proto: error2.proto: IMPORT: File recursively imports itself: "
       "error.proto -> error2.proto -> error.proto\n"
@@ -6720,7 +6777,7 @@
   // in the descriptor database but that have not not been built yet.
   MockErrorCollector error_collector;
   DescriptorPool pool(&database_, &error_collector);
-  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
   EXPECT_EQ(
       "baz.proto: Baz.foo: TYPE: \"Foo\" seems to be defined in \"foo.proto\", "
       "which is not imported by \"baz.proto\".  To use it here, please add "
@@ -6736,16 +6793,16 @@
   // Baz is defined in the database, but the file is invalid because it is
   // missing a necessary import.
   DescriptorPool pool(&database_);
-  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
   // Make sure that searching again for the file or the type fails.
-  EXPECT_TRUE(pool.FindFileByName("baz.proto") == NULL);
-  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == NULL);
+  EXPECT_TRUE(pool.FindFileByName("baz.proto") == nullptr);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Baz") == nullptr);
 }
 
 TEST_F(DatabaseBackedPoolTest, UnittestProto) {
   // Try to load all of unittest.proto from a DescriptorDatabase.  This should
   // thoroughly test all paths through DescriptorBuilder to insure that there
-  // are no deadlocking problems when pool_->mutex_ is non-NULL.
+  // are no deadlocking problems when pool_->mutex_ is non-null.
   const FileDescriptor* original_file =
       protobuf_unittest::TestAllTypes::descriptor()->file();
 
@@ -6754,7 +6811,7 @@
   const FileDescriptor* file_from_database =
       pool.FindFileByName(original_file->name());
 
-  ASSERT_TRUE(file_from_database != NULL);
+  ASSERT_TRUE(file_from_database != nullptr);
 
   FileDescriptorProto original_file_proto;
   original_file->CopyTo(&original_file_proto);
@@ -6777,39 +6834,39 @@
   DescriptorPool pool(&call_counter);
 
   const FileDescriptor* file = pool.FindFileByName("foo.proto");
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
-  ASSERT_TRUE(test_enum != NULL);
+  ASSERT_TRUE(test_enum != nullptr);
   const ServiceDescriptor* test_service = pool.FindServiceByName("TestService");
-  ASSERT_TRUE(test_service != NULL);
+  ASSERT_TRUE(test_service != nullptr);
 
   EXPECT_NE(0, call_counter.call_count_);
   call_counter.Clear();
 
-  EXPECT_TRUE(foo->FindFieldByName("no_such_field") == NULL);
-  EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == NULL);
-  EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == NULL);
-  EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == NULL);
-  EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == NULL);
+  EXPECT_TRUE(foo->FindFieldByName("no_such_field") == nullptr);
+  EXPECT_TRUE(foo->FindExtensionByName("no_such_extension") == nullptr);
+  EXPECT_TRUE(foo->FindNestedTypeByName("NoSuchMessageType") == nullptr);
+  EXPECT_TRUE(foo->FindEnumTypeByName("NoSuchEnumType") == nullptr);
+  EXPECT_TRUE(foo->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(test_enum->FindValueByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(test_service->FindMethodByName("NoSuchMethod") == nullptr);
 
-  EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == NULL);
-  EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == NULL);
-  EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == NULL);
+  EXPECT_TRUE(file->FindMessageTypeByName("NoSuchMessageType") == nullptr);
+  EXPECT_TRUE(file->FindEnumTypeByName("NoSuchEnumType") == nullptr);
+  EXPECT_TRUE(file->FindEnumValueByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(file->FindServiceByName("NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(file->FindExtensionByName("no_such_extension") == nullptr);
 
-  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == NULL);
-  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == NULL);
-  EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == NULL);
-  EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == NULL);
-  EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == NULL);
-  EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == NULL);
-  EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == NULL);
-  EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == NULL);
+  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no.such.field") == nullptr);
+  EXPECT_TRUE(pool.FindFileContainingSymbol("Foo.no_such_field") == nullptr);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Foo.NoSuchMessageType") == nullptr);
+  EXPECT_TRUE(pool.FindFieldByName("Foo.no_such_field") == nullptr);
+  EXPECT_TRUE(pool.FindExtensionByName("Foo.no_such_extension") == nullptr);
+  EXPECT_TRUE(pool.FindEnumTypeByName("Foo.NoSuchEnumType") == nullptr);
+  EXPECT_TRUE(pool.FindEnumValueByName("Foo.NO_SUCH_VALUE") == nullptr);
+  EXPECT_TRUE(pool.FindMethodByName("TestService.NoSuchMethod") == nullptr);
 
   EXPECT_EQ(0, call_counter.call_count_);
 }
@@ -6824,11 +6881,11 @@
 
   // First make sure foo.proto is loaded.
   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
 
   // Try inducing false positives.
-  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == NULL);
-  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("NoSuchSymbol") == nullptr);
+  EXPECT_TRUE(pool.FindExtensionByNumber(foo, 22) == nullptr);
 
   // No errors should have been reported.  (If foo.proto was incorrectly
   // loaded multiple times, errors would have been reported.)
@@ -6918,8 +6975,8 @@
 
   GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug.";
 
-  EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL);
-  EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL);
+  EXPECT_TRUE(pool.FindFileByName("file40.proto") == nullptr);
+  EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == nullptr);
 }
 
 TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) {
@@ -6930,22 +6987,22 @@
   DescriptorPool pool(&call_counter);
 
   const FileDescriptor* file = pool.FindFileByName("foo.proto");
-  ASSERT_TRUE(file != NULL);
+  ASSERT_TRUE(file != nullptr);
   const Descriptor* foo = pool.FindMessageTypeByName("Foo");
-  ASSERT_TRUE(foo != NULL);
+  ASSERT_TRUE(foo != nullptr);
   const EnumDescriptor* test_enum = pool.FindEnumTypeByName("TestEnum");
-  ASSERT_TRUE(test_enum != NULL);
+  ASSERT_TRUE(test_enum != nullptr);
 
   EXPECT_NE(0, call_counter.call_count_);
   call_counter.Clear();
 
-  EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == NULL);
-  EXPECT_TRUE(pool.FindFieldByName("Foo") == NULL);
-  EXPECT_TRUE(pool.FindExtensionByName("Foo") == NULL);
-  EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == NULL);
-  EXPECT_TRUE(pool.FindEnumValueByName("Foo") == NULL);
-  EXPECT_TRUE(pool.FindServiceByName("Foo") == NULL);
-  EXPECT_TRUE(pool.FindMethodByName("Foo") == NULL);
+  EXPECT_TRUE(pool.FindMessageTypeByName("TestEnum") == nullptr);
+  EXPECT_TRUE(pool.FindFieldByName("Foo") == nullptr);
+  EXPECT_TRUE(pool.FindExtensionByName("Foo") == nullptr);
+  EXPECT_TRUE(pool.FindEnumTypeByName("Foo") == nullptr);
+  EXPECT_TRUE(pool.FindEnumValueByName("Foo") == nullptr);
+  EXPECT_TRUE(pool.FindServiceByName("Foo") == nullptr);
+  EXPECT_TRUE(pool.FindMethodByName("Foo") == nullptr);
 
   EXPECT_EQ(0, call_counter.call_count_);
 }
@@ -6977,7 +7034,7 @@
   virtual io::ZeroCopyInputStream* Open(const std::string& filename) {
     return filename == filename_
                ? new io::ArrayInputStream(contents_.data(), contents_.size())
-               : NULL;
+               : nullptr;
   }
 
  private:
@@ -7627,7 +7684,7 @@
 
 class LazilyBuildDependenciesTest : public testing::Test {
  public:
-  LazilyBuildDependenciesTest() : pool_(&db_, NULL) {
+  LazilyBuildDependenciesTest() : pool_(&db_, nullptr) {
     pool_.InternalSetLazilyBuildDependencies();
   }
 
@@ -7697,7 +7754,7 @@
   const FileDescriptor* file = pool_.FindFileByName("foo.proto");
 
   // Verify only foo gets built when asking for foo.proto
-  EXPECT_TRUE(file != NULL);
+  EXPECT_TRUE(file != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
 
@@ -7706,7 +7763,7 @@
   // the field's type is defined in, as well.
   const Descriptor* desc = file->FindMessageTypeByName("Foo");
   const FieldDescriptor* field = desc->FindFieldByName("bar");
-  EXPECT_TRUE(field != NULL);
+  EXPECT_TRUE(field != nullptr);
   EXPECT_EQ(field, desc->FindFieldByNumber(1));
   EXPECT_EQ(field, desc->FindFieldByLowercaseName("bar"));
   EXPECT_EQ(field, desc->FindFieldByCamelcaseName("bar"));
@@ -7714,7 +7771,7 @@
 
   // Finally, verify that if we call message_type() on the field, we will
   // buid the file where the message is defined, and get a valid descriptor
-  EXPECT_TRUE(field->message_type() != NULL);
+  EXPECT_TRUE(field->message_type() != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
 }
 
@@ -7740,18 +7797,18 @@
   // yet built will build the file and return a descriptor.
   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto"));
   const Descriptor* desc = file->FindMessageTypeByName("Lazy");
-  EXPECT_TRUE(desc != NULL);
+  EXPECT_TRUE(desc != nullptr);
   const FieldDescriptor* field = desc->FindFieldByName("enum1");
-  EXPECT_TRUE(field != NULL);
-  EXPECT_TRUE(field->enum_type() != NULL);
+  EXPECT_TRUE(field != nullptr);
+  EXPECT_TRUE(field->enum_type() != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto"));
 
   // Verify calling default_value_enum() on a field whose definition is not
   // yet built will build the file and return a descriptor to the value.
   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto"));
   field = desc->FindFieldByName("enum2");
-  EXPECT_TRUE(field != NULL);
-  EXPECT_TRUE(field->default_value_enum() != NULL);
+  EXPECT_TRUE(field != nullptr);
+  EXPECT_TRUE(field->default_value_enum() != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto"));
 }
 
@@ -7785,9 +7842,9 @@
   // build the type defined in another file.
   EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto"));
   const Descriptor* desc = file->FindMessageTypeByName("Lazy");
-  EXPECT_TRUE(desc != NULL);
+  EXPECT_TRUE(desc != nullptr);
   const FieldDescriptor* field = desc->FindFieldByName("message1");
-  EXPECT_TRUE(field != NULL);
+  EXPECT_TRUE(field != nullptr);
   EXPECT_EQ(field->type(), FieldDescriptor::TYPE_MESSAGE);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto"));
 
@@ -7795,7 +7852,7 @@
   // build the type defined in another file.
   EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
   field = desc->FindFieldByName("message2");
-  EXPECT_TRUE(field != NULL);
+  EXPECT_TRUE(field != nullptr);
   EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_MESSAGE);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto"));
 
@@ -7803,7 +7860,7 @@
   // build the type defined in another file.
   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum1.proto"));
   field = desc->FindFieldByName("enum1");
-  EXPECT_TRUE(field != NULL);
+  EXPECT_TRUE(field != nullptr);
   EXPECT_EQ(field->type(), FieldDescriptor::TYPE_ENUM);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum1.proto"));
 
@@ -7811,7 +7868,7 @@
   // build the type defined in another file.
   EXPECT_FALSE(pool_.InternalIsFileLoaded("enum2.proto"));
   field = desc->FindFieldByName("enum2");
-  EXPECT_TRUE(field != NULL);
+  EXPECT_TRUE(field != nullptr);
   EXPECT_EQ(field->cpp_type(), FieldDescriptor::CPPTYPE_ENUM);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("enum2.proto"));
 }
@@ -7842,7 +7899,7 @@
 
   // Verify foo.bar gets loaded, and bar.proto gets loaded
   // to register the extension. baz.proto should not get loaded.
-  EXPECT_TRUE(file != NULL);
+  EXPECT_TRUE(file != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
   EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
   EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
@@ -7872,15 +7929,15 @@
   // files defining the input and output type, and input_type() and
   // output_type() does indeed build the appropriate files.
   const ServiceDescriptor* service = file->FindServiceByName("LazyService");
-  EXPECT_TRUE(service != NULL);
+  EXPECT_TRUE(service != nullptr);
   const MethodDescriptor* method = service->FindMethodByName("A");
   EXPECT_FALSE(pool_.InternalIsFileLoaded("message1.proto"));
   EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
-  EXPECT_TRUE(method != NULL);
-  EXPECT_TRUE(method->input_type() != NULL);
+  EXPECT_TRUE(method != nullptr);
+  EXPECT_TRUE(method->input_type() != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("message1.proto"));
   EXPECT_FALSE(pool_.InternalIsFileLoaded("message2.proto"));
-  EXPECT_TRUE(method->output_type() != NULL);
+  EXPECT_TRUE(method->output_type() != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("message2.proto"));
 }
 
@@ -7905,7 +7962,7 @@
   // the generated function "descriptor()" doesn't somehow subvert the laziness
   // by manually loading the dependencies or something.
   EXPECT_TRUE(protobuf_unittest::lazy_imports::ImportedMessage::descriptor() !=
-              NULL);
+              nullptr);
   EXPECT_TRUE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
       "google/protobuf/unittest_lazy_dependencies.proto"));
   EXPECT_FALSE(DescriptorPool::generated_pool()->InternalIsFileLoaded(
@@ -7963,7 +8020,7 @@
   AddSimpleMessageProtoFileToDb("baz", "Baz");
 
   const FileDescriptor* foo_file = pool_.FindFileByName("foo.proto");
-  EXPECT_TRUE(foo_file != NULL);
+  EXPECT_TRUE(foo_file != nullptr);
   // As expected, requesting foo.proto shouldn't build it's dependencies
   EXPECT_TRUE(pool_.InternalIsFileLoaded("foo.proto"));
   EXPECT_FALSE(pool_.InternalIsFileLoaded("bar.proto"));
@@ -7972,7 +8029,7 @@
   // Verify calling dependency(N) will build the dependency, but
   // not that file's dependencies.
   const FileDescriptor* bar_file = foo_file->dependency(0);
-  EXPECT_TRUE(bar_file != NULL);
+  EXPECT_TRUE(bar_file != nullptr);
   EXPECT_TRUE(pool_.InternalIsFileLoaded("bar.proto"));
   EXPECT_FALSE(pool_.InternalIsFileLoaded("baz.proto"));
 }
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index ae476de..4190f97 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -56,7 +56,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Duration_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 5890f78..0ef5dd9 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -34,10 +34,10 @@
 //
 // DynamicMessage is implemented by constructing a data structure which
 // has roughly the same memory layout as a generated message would have.
-// Then, we use GeneratedMessageReflection to implement our reflection
-// interface.  All the other operations we need to implement (e.g.
-// parsing, copying, etc.) are already implemented in terms of
-// Reflection, so the rest is easy.
+// Then, we use Reflection to implement our reflection interface.  All
+// the other operations we need to implement (e.g.  parsing, copying,
+// etc.) are already implemented in terms of Reflection, so the rest is
+// easy.
 //
 // The up side of this strategy is that it's very efficient.  We don't
 // need to use hash_maps or generic representations of fields.  The
@@ -87,7 +87,6 @@
 
 using internal::DynamicMapField;
 using internal::ExtensionSet;
-using internal::GeneratedMessageReflection;
 using internal::InternalMetadataWithArena;
 using internal::MapField;
 
@@ -248,7 +247,7 @@
     //   important (the prototype must be deleted *before* the offsets).
     std::unique_ptr<uint32[]> offsets;
     std::unique_ptr<uint32[]> has_bits_indices;
-    std::unique_ptr<const GeneratedMessageReflection> reflection;
+    std::unique_ptr<const Reflection> reflection;
     // Don't use a unique_ptr to hold the prototype: the destructor for
     // DynamicMessage needs to know whether it is the prototype, and does so by
     // looking back at this field. This would assume details about the
@@ -676,8 +675,8 @@
   type_info->pool = (pool_ == NULL) ? type->file()->pool() : pool_;
   type_info->factory = this;
 
-  // We need to construct all the structures passed to
-  // GeneratedMessageReflection's constructor.  This includes:
+  // We need to construct all the structures passed to Reflection's constructor.
+  // This includes:
   // - A block of memory that contains space for all the message's fields.
   // - An array of integers indicating the byte offset of each field within
   //   this block.
@@ -801,8 +800,8 @@
                                        type_info->size,
                                        type_info->weak_field_map_offset};
 
-  type_info->reflection.reset(new GeneratedMessageReflection(
-      type_info->type, schema, type_info->pool, this));
+  type_info->reflection.reset(
+      new Reflection(type_info->type, schema, type_info->pool, this));
 
   // Cross link prototypes.
   prototype->CrossLinkPrototypes();
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index eb1e466..481cb57 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -54,7 +54,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Empty_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 482bffa..034b44f 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -55,7 +55,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto[] PROTOBUF_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"
   "\214\001\n\023com.google.protobufB\016FieldMaskProtoP"
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index b7cdc87..34f0f8e 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -54,27 +54,46 @@
 
 #define GOOGLE_PROTOBUF_HAS_ONEOF
 
+using google::protobuf::internal::ArenaStringPtr;
+using google::protobuf::internal::DescriptorTable;
+using google::protobuf::internal::ExtensionSet;
+using google::protobuf::internal::GenericTypeHandler;
+using google::protobuf::internal::GetEmptyString;
+using google::protobuf::internal::InlinedStringField;
+using google::protobuf::internal::InternalMetadataWithArena;
+using google::protobuf::internal::LazyField;
+using google::protobuf::internal::MapFieldBase;
+using google::protobuf::internal::MigrationSchema;
+using google::protobuf::internal::OnShutdownDelete;
+using google::protobuf::internal::ReflectionSchema;
+using google::protobuf::internal::RepeatedPtrFieldBase;
+using google::protobuf::internal::StringSpaceUsedExcludingSelfLong;
+using google::protobuf::internal::WrappedMutex;
+
 namespace google {
 namespace protobuf {
-namespace internal {
 
 namespace {
 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
 }  // anonymous namespace
 
+namespace internal {
+
 bool ParseNamedEnum(const EnumDescriptor* descriptor, const std::string& name,
                     int* value) {
   const EnumValueDescriptor* d = descriptor->FindValueByName(name);
-  if (d == NULL) return false;
+  if (d == nullptr) return false;
   *value = d->number();
   return true;
 }
 
 const std::string& NameOfEnum(const EnumDescriptor* descriptor, int value) {
   const EnumValueDescriptor* d = descriptor->FindValueByNumber(value);
-  return (d == NULL ? GetEmptyString() : d->name());
+  return (d == nullptr ? GetEmptyString() : d->name());
 }
 
+}  // namespace internal
+
 // ===================================================================
 // Helpers for reporting usage errors (e.g. trying to use GetInt32() on
 // a string field).
@@ -198,9 +217,9 @@
 
 // ===================================================================
 
-GeneratedMessageReflection::GeneratedMessageReflection(
-    const Descriptor* descriptor, const ReflectionSchema& schema,
-    const DescriptorPool* pool, MessageFactory* factory)
+Reflection::Reflection(const Descriptor* descriptor,
+                       const internal::ReflectionSchema& schema,
+                       const DescriptorPool* pool, MessageFactory* factory)
     : descriptor_(descriptor),
       schema_(schema),
       descriptor_pool_(
@@ -210,19 +229,16 @@
   last_non_weak_field_index_ = descriptor_->field_count() - 1;
 }
 
-GeneratedMessageReflection::~GeneratedMessageReflection() {}
-
-const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields(
+const UnknownFieldSet& Reflection::GetUnknownFields(
     const Message& message) const {
   return GetInternalMetadataWithArena(message).unknown_fields();
 }
 
-UnknownFieldSet* GeneratedMessageReflection::MutableUnknownFields(
-    Message* message) const {
+UnknownFieldSet* Reflection::MutableUnknownFields(Message* message) const {
   return MutableInternalMetadataWithArena(message)->mutable_unknown_fields();
 }
 
-size_t GeneratedMessageReflection::SpaceUsedLong(const Message& message) const {
+size_t Reflection::SpaceUsedLong(const Message& message) const {
   // object_size_ already includes the in-memory representation of each field
   // in the message, so we only need to account for additional memory used by
   // the fields.
@@ -266,7 +282,7 @@
 
         case FieldDescriptor::CPPTYPE_MESSAGE:
           if (IsMapFieldInApi(field)) {
-            total_size += GetRaw<MapFieldBase>(message, field)
+            total_size += GetRaw<internal::MapFieldBase>(message, field)
                               .SpaceUsedExcludingSelfLong();
           } else {
             // We don't know which subclass of RepeatedPtrFieldBase the type is,
@@ -331,7 +347,7 @@
             // external type's prototype, so there is no extra memory usage.
           } else {
             const Message* sub_message = GetRaw<const Message*>(message, field);
-            if (sub_message != NULL) {
+            if (sub_message != nullptr) {
               total_size += sub_message->SpaceUsedLong();
             }
           }
@@ -342,8 +358,8 @@
   return total_size;
 }
 
-void GeneratedMessageReflection::SwapField(Message* message1, Message* message2,
-                                           const FieldDescriptor* field) const {
+void Reflection::SwapField(Message* message1, Message* message2,
+                           const FieldDescriptor* field) const {
   if (field->is_repeated()) {
     switch (field->cpp_type()) {
 #define SWAP_ARRAYS(CPPTYPE, TYPE)                                 \
@@ -410,12 +426,12 @@
         } else {
           Message** sub_msg1 = MutableRaw<Message*>(message1, field);
           Message** sub_msg2 = MutableRaw<Message*>(message2, field);
-          if (*sub_msg1 == NULL && *sub_msg2 == NULL) break;
+          if (*sub_msg1 == nullptr && *sub_msg2 == nullptr) break;
           if (*sub_msg1 && *sub_msg2) {
             (*sub_msg1)->GetReflection()->Swap(*sub_msg1, *sub_msg2);
             break;
           }
-          if (*sub_msg1 == NULL) {
+          if (*sub_msg1 == nullptr) {
             *sub_msg1 = (*sub_msg2)->New(message1->GetArena());
             (*sub_msg1)->CopyFrom(**sub_msg2);
             ClearField(message2, field);
@@ -466,9 +482,8 @@
   }
 }
 
-void GeneratedMessageReflection::SwapOneofField(
-    Message* message1, Message* message2,
-    const OneofDescriptor* oneof_descriptor) const {
+void Reflection::SwapOneofField(Message* message1, Message* message2,
+                                const OneofDescriptor* oneof_descriptor) const {
   uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor);
   uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor);
 
@@ -480,11 +495,11 @@
   double temp_double;
   bool temp_bool;
   int temp_int;
-  Message* temp_message = NULL;
+  Message* temp_message = nullptr;
   std::string temp_string;
 
   // Stores message1's oneof field to a temp variable.
-  const FieldDescriptor* field1 = NULL;
+  const FieldDescriptor* field1 = nullptr;
   if (oneof_case1 > 0) {
     field1 = descriptor_->FindFieldByNumber(oneof_case1);
     // oneof_descriptor->field(oneof_case1);
@@ -582,8 +597,7 @@
   }
 }
 
-void GeneratedMessageReflection::Swap(Message* message1,
-                                      Message* message2) const {
+void Reflection::Swap(Message* message1, Message* message2) const {
   if (message1 == message2) return;
 
   // TODO(kenton):  Other Reflection methods should probably check this too.
@@ -613,7 +627,7 @@
     temp->MergeFrom(*message2);
     message2->CopyFrom(*message1);
     Swap(message1, temp);
-    if (GetArena(message1) == NULL) {
+    if (GetArena(message1) == nullptr) {
       delete temp;
     }
     return;
@@ -656,7 +670,7 @@
   MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2));
 }
 
-void GeneratedMessageReflection::SwapFields(
+void Reflection::SwapFields(
     Message* message1, Message* message2,
     const std::vector<const FieldDescriptor*>& fields) const {
   if (message1 == message2) return;
@@ -711,8 +725,8 @@
 
 // -------------------------------------------------------------------
 
-bool GeneratedMessageReflection::HasField(const Message& message,
-                                          const FieldDescriptor* field) const {
+bool Reflection::HasField(const Message& message,
+                          const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(HasField);
   USAGE_CHECK_SINGULAR(HasField);
 
@@ -727,8 +741,8 @@
   }
 }
 
-int GeneratedMessageReflection::FieldSize(const Message& message,
-                                          const FieldDescriptor* field) const {
+int Reflection::FieldSize(const Message& message,
+                          const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(FieldSize);
   USAGE_CHECK_REPEATED(FieldSize);
 
@@ -772,8 +786,8 @@
   }
 }
 
-void GeneratedMessageReflection::ClearField(
-    Message* message, const FieldDescriptor* field) const {
+void Reflection::ClearField(Message* message,
+                            const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(ClearField);
 
   if (field->is_extension()) {
@@ -822,7 +836,7 @@
               const std::string* default_ptr =
                   &DefaultRaw<ArenaStringPtr>(field).Get();
               MutableRaw<ArenaStringPtr>(message, field)
-                  ->SetAllocated(default_ptr, NULL, GetArena(message));
+                  ->SetAllocated(default_ptr, nullptr, GetArena(message));
               break;
             }
           }
@@ -832,11 +846,11 @@
         case FieldDescriptor::CPPTYPE_MESSAGE:
           if (!schema_.HasHasbits()) {
             // Proto3 does not have has-bits and we need to set a message field
-            // to NULL in order to indicate its un-presence.
-            if (GetArena(message) == NULL) {
+            // to nullptr in order to indicate its un-presence.
+            if (GetArena(message) == nullptr) {
               delete *MutableRaw<Message*>(message, field);
             }
-            *MutableRaw<Message*>(message, field) = NULL;
+            *MutableRaw<Message*>(message, field) = nullptr;
           } else {
             (*MutableRaw<Message*>(message, field))->Clear();
           }
@@ -885,8 +899,8 @@
   }
 }
 
-void GeneratedMessageReflection::RemoveLast(
-    Message* message, const FieldDescriptor* field) const {
+void Reflection::RemoveLast(Message* message,
+                            const FieldDescriptor* field) const {
   USAGE_CHECK_MESSAGE_TYPE(RemoveLast);
   USAGE_CHECK_REPEATED(RemoveLast);
 
@@ -933,8 +947,8 @@
   }
 }
 
-Message* GeneratedMessageReflection::ReleaseLast(
-    Message* message, const FieldDescriptor* field) const {
+Message* Reflection::ReleaseLast(Message* message,
+                                 const FieldDescriptor* field) const {
   USAGE_CHECK_ALL(ReleaseLast, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
@@ -952,9 +966,8 @@
   }
 }
 
-void GeneratedMessageReflection::SwapElements(Message* message,
-                                              const FieldDescriptor* field,
-                                              int index1, int index2) const {
+void Reflection::SwapElements(Message* message, const FieldDescriptor* field,
+                              int index1, int index2) const {
   USAGE_CHECK_MESSAGE_TYPE(Swap);
   USAGE_CHECK_REPEATED(Swap);
 
@@ -1002,16 +1015,20 @@
   }
 };
 
-inline bool IsIndexInHasBitSet(const uint32* has_bit_set,
+bool IsIndexInHasBitSet(const uint32* has_bit_set,
                                uint32 has_bit_index) {
   GOOGLE_DCHECK_NE(has_bit_index, ~0u);
   return ((has_bit_set[has_bit_index / 32] >> (has_bit_index % 32)) &
           static_cast<uint32>(1)) != 0;
 }
+
+bool CreateUnknownEnumValues(const FileDescriptor* file) {
+  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
 }  // namespace
 
-void GeneratedMessageReflection::ListFields(
-    const Message& message, std::vector<const FieldDescriptor*>* output) const {
+void Reflection::ListFields(const Message& message,
+                            std::vector<const FieldDescriptor*>* output) const {
   output->clear();
 
   // Optimization:  The default instance never has any fields set.
@@ -1023,7 +1040,7 @@
   // fleetwide and properly allowing this optimization through public interfaces
   // seems more trouble than it is worth.
   const uint32* const has_bits =
-      schema_.HasHasbits() ? GetHasBits(message) : NULL;
+      schema_.HasHasbits() ? GetHasBits(message) : nullptr;
   const uint32* const has_bits_indices = schema_.has_bit_indices_;
   output->reserve(descriptor_->field_count());
   for (int i = 0; i <= last_non_weak_field_index_; i++) {
@@ -1064,8 +1081,8 @@
 
 #undef DEFINE_PRIMITIVE_ACCESSORS
 #define DEFINE_PRIMITIVE_ACCESSORS(TYPENAME, TYPE, PASSTYPE, CPPTYPE)          \
-  PASSTYPE GeneratedMessageReflection::Get##TYPENAME(                          \
-      const Message& message, const FieldDescriptor* field) const {            \
+  PASSTYPE Reflection::Get##TYPENAME(const Message& message,                   \
+                                     const FieldDescriptor* field) const {     \
     USAGE_CHECK_ALL(Get##TYPENAME, SINGULAR, CPPTYPE);                         \
     if (field->is_extension()) {                                               \
       return GetExtensionSet(message).Get##TYPENAME(                           \
@@ -1075,7 +1092,7 @@
     }                                                                          \
   }                                                                            \
                                                                                \
-  void GeneratedMessageReflection::Set##TYPENAME(                              \
+  void Reflection::Set##TYPENAME(                                              \
       Message* message, const FieldDescriptor* field, PASSTYPE value) const {  \
     USAGE_CHECK_ALL(Set##TYPENAME, SINGULAR, CPPTYPE);                         \
     if (field->is_extension()) {                                               \
@@ -1086,7 +1103,7 @@
     }                                                                          \
   }                                                                            \
                                                                                \
-  PASSTYPE GeneratedMessageReflection::GetRepeated##TYPENAME(                  \
+  PASSTYPE Reflection::GetRepeated##TYPENAME(                                  \
       const Message& message, const FieldDescriptor* field, int index) const { \
     USAGE_CHECK_ALL(GetRepeated##TYPENAME, REPEATED, CPPTYPE);                 \
     if (field->is_extension()) {                                               \
@@ -1097,9 +1114,9 @@
     }                                                                          \
   }                                                                            \
                                                                                \
-  void GeneratedMessageReflection::SetRepeated##TYPENAME(                      \
-      Message* message, const FieldDescriptor* field, int index,               \
-      PASSTYPE value) const {                                                  \
+  void Reflection::SetRepeated##TYPENAME(Message* message,                     \
+                                         const FieldDescriptor* field,         \
+                                         int index, PASSTYPE value) const {    \
     USAGE_CHECK_ALL(SetRepeated##TYPENAME, REPEATED, CPPTYPE);                 \
     if (field->is_extension()) {                                               \
       MutableExtensionSet(message)->SetRepeated##TYPENAME(field->number(),     \
@@ -1109,7 +1126,7 @@
     }                                                                          \
   }                                                                            \
                                                                                \
-  void GeneratedMessageReflection::Add##TYPENAME(                              \
+  void Reflection::Add##TYPENAME(                                              \
       Message* message, const FieldDescriptor* field, PASSTYPE value) const {  \
     USAGE_CHECK_ALL(Add##TYPENAME, REPEATED, CPPTYPE);                         \
     if (field->is_extension()) {                                               \
@@ -1132,8 +1149,8 @@
 
 // -------------------------------------------------------------------
 
-std::string GeneratedMessageReflection::GetString(
-    const Message& message, const FieldDescriptor* field) const {
+std::string Reflection::GetString(const Message& message,
+                                  const FieldDescriptor* field) const {
   USAGE_CHECK_ALL(GetString, SINGULAR, STRING);
   if (field->is_extension()) {
     return GetExtensionSet(message).GetString(field->number(),
@@ -1152,9 +1169,9 @@
   }
 }
 
-const std::string& GeneratedMessageReflection::GetStringReference(
-    const Message& message, const FieldDescriptor* field,
-    std::string* scratch) const {
+const std::string& Reflection::GetStringReference(const Message& message,
+                                                  const FieldDescriptor* field,
+                                                  std::string* scratch) const {
   USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING);
   if (field->is_extension()) {
     return GetExtensionSet(message).GetString(field->number(),
@@ -1174,9 +1191,8 @@
 }
 
 
-void GeneratedMessageReflection::SetString(Message* message,
-                                           const FieldDescriptor* field,
-                                           const std::string& value) const {
+void Reflection::SetString(Message* message, const FieldDescriptor* field,
+                           const std::string& value) const {
   USAGE_CHECK_ALL(SetString, SINGULAR, STRING);
   if (field->is_extension()) {
     return MutableExtensionSet(message)->SetString(field->number(),
@@ -1187,7 +1203,7 @@
       case FieldOptions::STRING: {
         if (IsInlined(field)) {
           MutableField<InlinedStringField>(message, field)
-              ->SetNoArena(NULL, value);
+              ->SetNoArena(nullptr, value);
           break;
         }
 
@@ -1208,8 +1224,9 @@
 }
 
 
-std::string GeneratedMessageReflection::GetRepeatedString(
-    const Message& message, const FieldDescriptor* field, int index) const {
+std::string Reflection::GetRepeatedString(const Message& message,
+                                          const FieldDescriptor* field,
+                                          int index) const {
   USAGE_CHECK_ALL(GetRepeatedString, REPEATED, STRING);
   if (field->is_extension()) {
     return GetExtensionSet(message).GetRepeatedString(field->number(), index);
@@ -1222,7 +1239,7 @@
   }
 }
 
-const std::string& GeneratedMessageReflection::GetRepeatedStringReference(
+const std::string& Reflection::GetRepeatedStringReference(
     const Message& message, const FieldDescriptor* field, int index,
     std::string* scratch) const {
   USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING);
@@ -1238,9 +1255,9 @@
 }
 
 
-void GeneratedMessageReflection::SetRepeatedString(
-    Message* message, const FieldDescriptor* field, int index,
-    const std::string& value) const {
+void Reflection::SetRepeatedString(Message* message,
+                                   const FieldDescriptor* field, int index,
+                                   const std::string& value) const {
   USAGE_CHECK_ALL(SetRepeatedString, REPEATED, STRING);
   if (field->is_extension()) {
     MutableExtensionSet(message)->SetRepeatedString(field->number(), index,
@@ -1256,9 +1273,8 @@
 }
 
 
-void GeneratedMessageReflection::AddString(Message* message,
-                                           const FieldDescriptor* field,
-                                           const std::string& value) const {
+void Reflection::AddString(Message* message, const FieldDescriptor* field,
+                           const std::string& value) const {
   USAGE_CHECK_ALL(AddString, REPEATED, STRING);
   if (field->is_extension()) {
     MutableExtensionSet(message)->AddString(field->number(), field->type(),
@@ -1276,19 +1292,15 @@
 
 // -------------------------------------------------------------------
 
-inline bool CreateUnknownEnumValues(const FileDescriptor* file) {
-  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
-const EnumValueDescriptor* GeneratedMessageReflection::GetEnum(
+const EnumValueDescriptor* Reflection::GetEnum(
     const Message& message, const FieldDescriptor* field) const {
   // Usage checked by GetEnumValue.
   int value = GetEnumValue(message, field);
   return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
 }
 
-int GeneratedMessageReflection::GetEnumValue(
-    const Message& message, const FieldDescriptor* field) const {
+int Reflection::GetEnumValue(const Message& message,
+                             const FieldDescriptor* field) const {
   USAGE_CHECK_ALL(GetEnumValue, SINGULAR, ENUM);
 
   int32 value;
@@ -1301,24 +1313,22 @@
   return value;
 }
 
-void GeneratedMessageReflection::SetEnum(
-    Message* message, const FieldDescriptor* field,
-    const EnumValueDescriptor* value) const {
+void Reflection::SetEnum(Message* message, const FieldDescriptor* field,
+                         const EnumValueDescriptor* value) const {
   // Usage checked by SetEnumValue.
   USAGE_CHECK_ENUM_VALUE(SetEnum);
   SetEnumValueInternal(message, field, value->number());
 }
 
-void GeneratedMessageReflection::SetEnumValue(Message* message,
-                                              const FieldDescriptor* field,
-                                              int value) const {
+void Reflection::SetEnumValue(Message* message, const FieldDescriptor* field,
+                              int value) const {
   USAGE_CHECK_ALL(SetEnumValue, SINGULAR, ENUM);
   if (!CreateUnknownEnumValues(descriptor_->file())) {
     // Check that the value is valid if we don't support direct storage of
     // unknown enum values.
     const EnumValueDescriptor* value_desc =
         field->enum_type()->FindValueByNumber(value);
-    if (value_desc == NULL) {
+    if (value_desc == nullptr) {
       MutableUnknownFields(message)->AddVarint(field->number(), value);
       return;
     }
@@ -1326,8 +1336,9 @@
   SetEnumValueInternal(message, field, value);
 }
 
-void GeneratedMessageReflection::SetEnumValueInternal(
-    Message* message, const FieldDescriptor* field, int value) const {
+void Reflection::SetEnumValueInternal(Message* message,
+                                      const FieldDescriptor* field,
+                                      int value) const {
   if (field->is_extension()) {
     MutableExtensionSet(message)->SetEnum(field->number(), field->type(), value,
                                           field);
@@ -1336,15 +1347,16 @@
   }
 }
 
-const EnumValueDescriptor* GeneratedMessageReflection::GetRepeatedEnum(
+const EnumValueDescriptor* Reflection::GetRepeatedEnum(
     const Message& message, const FieldDescriptor* field, int index) const {
   // Usage checked by GetRepeatedEnumValue.
   int value = GetRepeatedEnumValue(message, field, index);
   return field->enum_type()->FindValueByNumberCreatingIfUnknown(value);
 }
 
-int GeneratedMessageReflection::GetRepeatedEnumValue(
-    const Message& message, const FieldDescriptor* field, int index) const {
+int Reflection::GetRepeatedEnumValue(const Message& message,
+                                     const FieldDescriptor* field,
+                                     int index) const {
   USAGE_CHECK_ALL(GetRepeatedEnumValue, REPEATED, ENUM);
 
   int value;
@@ -1356,24 +1368,24 @@
   return value;
 }
 
-void GeneratedMessageReflection::SetRepeatedEnum(
-    Message* message, const FieldDescriptor* field, int index,
-    const EnumValueDescriptor* value) const {
+void Reflection::SetRepeatedEnum(Message* message, const FieldDescriptor* field,
+                                 int index,
+                                 const EnumValueDescriptor* value) const {
   // Usage checked by SetRepeatedEnumValue.
   USAGE_CHECK_ENUM_VALUE(SetRepeatedEnum);
   SetRepeatedEnumValueInternal(message, field, index, value->number());
 }
 
-void GeneratedMessageReflection::SetRepeatedEnumValue(
-    Message* message, const FieldDescriptor* field, int index,
-    int value) const {
+void Reflection::SetRepeatedEnumValue(Message* message,
+                                      const FieldDescriptor* field, int index,
+                                      int value) const {
   USAGE_CHECK_ALL(SetRepeatedEnum, REPEATED, ENUM);
   if (!CreateUnknownEnumValues(descriptor_->file())) {
     // Check that the value is valid if we don't support direct storage of
     // unknown enum values.
     const EnumValueDescriptor* value_desc =
         field->enum_type()->FindValueByNumber(value);
-    if (value_desc == NULL) {
+    if (value_desc == nullptr) {
       MutableUnknownFields(message)->AddVarint(field->number(), value);
       return;
     }
@@ -1381,9 +1393,9 @@
   SetRepeatedEnumValueInternal(message, field, index, value);
 }
 
-void GeneratedMessageReflection::SetRepeatedEnumValueInternal(
-    Message* message, const FieldDescriptor* field, int index,
-    int value) const {
+void Reflection::SetRepeatedEnumValueInternal(Message* message,
+                                              const FieldDescriptor* field,
+                                              int index, int value) const {
   if (field->is_extension()) {
     MutableExtensionSet(message)->SetRepeatedEnum(field->number(), index,
                                                   value);
@@ -1392,24 +1404,22 @@
   }
 }
 
-void GeneratedMessageReflection::AddEnum(
-    Message* message, const FieldDescriptor* field,
-    const EnumValueDescriptor* value) const {
+void Reflection::AddEnum(Message* message, const FieldDescriptor* field,
+                         const EnumValueDescriptor* value) const {
   // Usage checked by AddEnumValue.
   USAGE_CHECK_ENUM_VALUE(AddEnum);
   AddEnumValueInternal(message, field, value->number());
 }
 
-void GeneratedMessageReflection::AddEnumValue(Message* message,
-                                              const FieldDescriptor* field,
-                                              int value) const {
+void Reflection::AddEnumValue(Message* message, const FieldDescriptor* field,
+                              int value) const {
   USAGE_CHECK_ALL(AddEnum, REPEATED, ENUM);
   if (!CreateUnknownEnumValues(descriptor_->file())) {
     // Check that the value is valid if we don't support direct storage of
     // unknown enum values.
     const EnumValueDescriptor* value_desc =
         field->enum_type()->FindValueByNumber(value);
-    if (value_desc == NULL) {
+    if (value_desc == nullptr) {
       MutableUnknownFields(message)->AddVarint(field->number(), value);
       return;
     }
@@ -1417,8 +1427,9 @@
   AddEnumValueInternal(message, field, value);
 }
 
-void GeneratedMessageReflection::AddEnumValueInternal(
-    Message* message, const FieldDescriptor* field, int value) const {
+void Reflection::AddEnumValueInternal(Message* message,
+                                      const FieldDescriptor* field,
+                                      int value) const {
   if (field->is_extension()) {
     MutableExtensionSet(message)->AddEnum(field->number(), field->type(),
                                           field->options().packed(), value,
@@ -1430,31 +1441,31 @@
 
 // -------------------------------------------------------------------
 
-const Message& GeneratedMessageReflection::GetMessage(
-    const Message& message, const FieldDescriptor* field,
-    MessageFactory* factory) const {
+const Message& Reflection::GetMessage(const Message& message,
+                                      const FieldDescriptor* field,
+                                      MessageFactory* factory) const {
   USAGE_CHECK_ALL(GetMessage, SINGULAR, MESSAGE);
 
-  if (factory == NULL) factory = message_factory_;
+  if (factory == nullptr) factory = message_factory_;
 
   if (field->is_extension()) {
     return static_cast<const Message&>(GetExtensionSet(message).GetMessage(
         field->number(), field->message_type(), factory));
   } else {
     const Message* result = GetRaw<const Message*>(message, field);
-    if (result == NULL) {
+    if (result == nullptr) {
       result = DefaultRaw<const Message*>(field);
     }
     return *result;
   }
 }
 
-Message* GeneratedMessageReflection::MutableMessage(
-    Message* message, const FieldDescriptor* field,
-    MessageFactory* factory) const {
+Message* Reflection::MutableMessage(Message* message,
+                                    const FieldDescriptor* field,
+                                    MessageFactory* factory) const {
   USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE);
 
-  if (factory == NULL) factory = message_factory_;
+  if (factory == nullptr) factory = message_factory_;
 
   if (field->is_extension()) {
     return static_cast<Message*>(
@@ -1475,7 +1486,7 @@
       SetBit(message, field);
     }
 
-    if (*result_holder == NULL) {
+    if (*result_holder == nullptr) {
       const Message* default_message = DefaultRaw<const Message*>(field);
       *result_holder = default_message->New(message->GetArena());
     }
@@ -1484,7 +1495,7 @@
   }
 }
 
-void GeneratedMessageReflection::UnsafeArenaSetAllocatedMessage(
+void Reflection::UnsafeArenaSetAllocatedMessage(
     Message* message, Message* sub_message,
     const FieldDescriptor* field) const {
   USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE);
@@ -1494,7 +1505,7 @@
         field->number(), field->type(), field, sub_message);
   } else {
     if (field->containing_oneof()) {
-      if (sub_message == NULL) {
+      if (sub_message == nullptr) {
         ClearOneof(message, field->containing_oneof());
         return;
       }
@@ -1504,27 +1515,27 @@
       return;
     }
 
-    if (sub_message == NULL) {
+    if (sub_message == nullptr) {
       ClearBit(message, field);
     } else {
       SetBit(message, field);
     }
     Message** sub_message_holder = MutableRaw<Message*>(message, field);
-    if (GetArena(message) == NULL) {
+    if (GetArena(message) == nullptr) {
       delete *sub_message_holder;
     }
     *sub_message_holder = sub_message;
   }
 }
 
-void GeneratedMessageReflection::SetAllocatedMessage(
-    Message* message, Message* sub_message,
-    const FieldDescriptor* field) const {
+void Reflection::SetAllocatedMessage(Message* message, Message* sub_message,
+                                     const FieldDescriptor* field) const {
   // If message and sub-message are in different memory ownership domains
   // (different arenas, or one is on heap and one is not), then we may need to
   // do a copy.
-  if (sub_message != NULL && sub_message->GetArena() != message->GetArena()) {
-    if (sub_message->GetArena() == NULL && message->GetArena() != NULL) {
+  if (sub_message != nullptr &&
+      sub_message->GetArena() != message->GetArena()) {
+    if (sub_message->GetArena() == nullptr && message->GetArena() != nullptr) {
       // Case 1: parent is on an arena and child is heap-allocated. We can add
       // the child to the arena's Own() list to free on arena destruction, then
       // set our pointer.
@@ -1543,12 +1554,12 @@
   }
 }
 
-Message* GeneratedMessageReflection::UnsafeArenaReleaseMessage(
-    Message* message, const FieldDescriptor* field,
-    MessageFactory* factory) const {
+Message* Reflection::UnsafeArenaReleaseMessage(Message* message,
+                                               const FieldDescriptor* field,
+                                               MessageFactory* factory) const {
   USAGE_CHECK_ALL(ReleaseMessage, SINGULAR, MESSAGE);
 
-  if (factory == NULL) factory = message_factory_;
+  if (factory == nullptr) factory = message_factory_;
 
   if (field->is_extension()) {
     return static_cast<Message*>(
@@ -1562,21 +1573,21 @@
       if (HasOneofField(*message, field)) {
         *MutableOneofCase(message, field->containing_oneof()) = 0;
       } else {
-        return NULL;
+        return nullptr;
       }
     }
     Message** result = MutableRaw<Message*>(message, field);
     Message* ret = *result;
-    *result = NULL;
+    *result = nullptr;
     return ret;
   }
 }
 
-Message* GeneratedMessageReflection::ReleaseMessage(
-    Message* message, const FieldDescriptor* field,
-    MessageFactory* factory) const {
+Message* Reflection::ReleaseMessage(Message* message,
+                                    const FieldDescriptor* field,
+                                    MessageFactory* factory) const {
   Message* released = UnsafeArenaReleaseMessage(message, field, factory);
-  if (GetArena(message) != NULL && released != NULL) {
+  if (GetArena(message) != nullptr && released != nullptr) {
     Message* copy_from_arena = released->New();
     copy_from_arena->CopyFrom(*released);
     released = copy_from_arena;
@@ -1584,8 +1595,9 @@
   return released;
 }
 
-const Message& GeneratedMessageReflection::GetRepeatedMessage(
-    const Message& message, const FieldDescriptor* field, int index) const {
+const Message& Reflection::GetRepeatedMessage(const Message& message,
+                                              const FieldDescriptor* field,
+                                              int index) const {
   USAGE_CHECK_ALL(GetRepeatedMessage, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
@@ -1603,8 +1615,9 @@
   }
 }
 
-Message* GeneratedMessageReflection::MutableRepeatedMessage(
-    Message* message, const FieldDescriptor* field, int index) const {
+Message* Reflection::MutableRepeatedMessage(Message* message,
+                                            const FieldDescriptor* field,
+                                            int index) const {
   USAGE_CHECK_ALL(MutableRepeatedMessage, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
@@ -1623,22 +1636,21 @@
   }
 }
 
-Message* GeneratedMessageReflection::AddMessage(Message* message,
-                                                const FieldDescriptor* field,
-                                                MessageFactory* factory) const {
+Message* Reflection::AddMessage(Message* message, const FieldDescriptor* field,
+                                MessageFactory* factory) const {
   USAGE_CHECK_ALL(AddMessage, REPEATED, MESSAGE);
 
-  if (factory == NULL) factory = message_factory_;
+  if (factory == nullptr) factory = message_factory_;
 
   if (field->is_extension()) {
     return static_cast<Message*>(
         MutableExtensionSet(message)->AddMessage(field, factory));
   } else {
-    Message* result = NULL;
+    Message* result = nullptr;
 
     // We can't use AddField<Message>() because RepeatedPtrFieldBase doesn't
     // know how to allocate one.
-    RepeatedPtrFieldBase* repeated = NULL;
+    RepeatedPtrFieldBase* repeated = nullptr;
     if (IsMapFieldInApi(field)) {
       repeated =
           MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
@@ -1646,7 +1658,7 @@
       repeated = MutableRaw<RepeatedPtrFieldBase>(message, field);
     }
     result = repeated->AddFromCleared<GenericTypeHandler<Message> >();
-    if (result == NULL) {
+    if (result == nullptr) {
       // We must allocate a new object.
       const Message* prototype;
       if (repeated->size() == 0) {
@@ -1665,14 +1677,15 @@
   }
 }
 
-void GeneratedMessageReflection::AddAllocatedMessage(
-    Message* message, const FieldDescriptor* field, Message* new_entry) const {
+void Reflection::AddAllocatedMessage(Message* message,
+                                     const FieldDescriptor* field,
+                                     Message* new_entry) const {
   USAGE_CHECK_ALL(AddAllocatedMessage, REPEATED, MESSAGE);
 
   if (field->is_extension()) {
     MutableExtensionSet(message)->AddAllocatedMessage(field, new_entry);
   } else {
-    RepeatedPtrFieldBase* repeated = NULL;
+    RepeatedPtrFieldBase* repeated = nullptr;
     if (IsMapFieldInApi(field)) {
       repeated =
           MutableRaw<MapFieldBase>(message, field)->MutableRepeatedField();
@@ -1683,14 +1696,16 @@
   }
 }
 
-void* GeneratedMessageReflection::MutableRawRepeatedField(
-    Message* message, const FieldDescriptor* field,
-    FieldDescriptor::CppType cpptype, int ctype, const Descriptor* desc) const {
+void* Reflection::MutableRawRepeatedField(Message* message,
+                                          const FieldDescriptor* field,
+                                          FieldDescriptor::CppType cpptype,
+                                          int ctype,
+                                          const Descriptor* desc) const {
   USAGE_CHECK_REPEATED("MutableRawRepeatedField");
   if (field->cpp_type() != cpptype)
     ReportReflectionUsageTypeError(descriptor_, field,
                                    "MutableRawRepeatedField", cpptype);
-  if (desc != NULL)
+  if (desc != nullptr)
     GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
   if (field->is_extension()) {
     return MutableExtensionSet(message)->MutableRawRepeatedField(
@@ -1705,16 +1720,18 @@
   }
 }
 
-const void* GeneratedMessageReflection::GetRawRepeatedField(
-    const Message& message, const FieldDescriptor* field,
-    FieldDescriptor::CppType cpptype, int ctype, const Descriptor* desc) const {
+const void* Reflection::GetRawRepeatedField(const Message& message,
+                                            const FieldDescriptor* field,
+                                            FieldDescriptor::CppType cpptype,
+                                            int ctype,
+                                            const Descriptor* desc) const {
   USAGE_CHECK_REPEATED("GetRawRepeatedField");
   if (field->cpp_type() != cpptype)
     ReportReflectionUsageTypeError(descriptor_, field, "GetRawRepeatedField",
                                    cpptype);
   if (ctype >= 0)
     GOOGLE_CHECK_EQ(field->options().ctype(), ctype) << "subtype mismatch";
-  if (desc != NULL)
+  if (desc != nullptr)
     GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type";
   if (field->is_extension()) {
     // Should use extension_set::GetRawRepeatedField. However, the required
@@ -1733,26 +1750,27 @@
   }
 }
 
-const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor(
+const FieldDescriptor* Reflection::GetOneofFieldDescriptor(
     const Message& message, const OneofDescriptor* oneof_descriptor) const {
   uint32 field_number = GetOneofCase(message, oneof_descriptor);
   if (field_number == 0) {
-    return NULL;
+    return nullptr;
   }
   return descriptor_->FindFieldByNumber(field_number);
 }
 
-bool GeneratedMessageReflection::ContainsMapKey(const Message& message,
-                                                const FieldDescriptor* field,
-                                                const MapKey& key) const {
+bool Reflection::ContainsMapKey(const Message& message,
+                                const FieldDescriptor* field,
+                                const MapKey& key) const {
   USAGE_CHECK(IsMapFieldInApi(field), "LookupMapValue",
               "Field is not a map field.");
   return GetRaw<MapFieldBase>(message, field).ContainsMapKey(key);
 }
 
-bool GeneratedMessageReflection::InsertOrLookupMapValue(
-    Message* message, const FieldDescriptor* field, const MapKey& key,
-    MapValueRef* val) const {
+bool Reflection::InsertOrLookupMapValue(Message* message,
+                                        const FieldDescriptor* field,
+                                        const MapKey& key,
+                                        MapValueRef* val) const {
   USAGE_CHECK(IsMapFieldInApi(field), "InsertOrLookupMapValue",
               "Field is not a map field.");
   val->SetType(field->message_type()->FindFieldByName("value")->cpp_type());
@@ -1760,75 +1778,50 @@
       ->InsertOrLookupMapValue(key, val);
 }
 
-bool GeneratedMessageReflection::DeleteMapValue(Message* message,
-                                                const FieldDescriptor* field,
-                                                const MapKey& key) const {
+bool Reflection::DeleteMapValue(Message* message, const FieldDescriptor* field,
+                                const MapKey& key) const {
   USAGE_CHECK(IsMapFieldInApi(field), "DeleteMapValue",
               "Field is not a map field.");
   return MutableRaw<MapFieldBase>(message, field)->DeleteMapValue(key);
 }
 
-MapIterator GeneratedMessageReflection::MapBegin(
-    Message* message, const FieldDescriptor* field) const {
+MapIterator Reflection::MapBegin(Message* message,
+                                 const FieldDescriptor* field) const {
   USAGE_CHECK(IsMapFieldInApi(field), "MapBegin", "Field is not a map field.");
   MapIterator iter(message, field);
   GetRaw<MapFieldBase>(*message, field).MapBegin(&iter);
   return iter;
 }
 
-MapIterator GeneratedMessageReflection::MapEnd(
-    Message* message, const FieldDescriptor* field) const {
+MapIterator Reflection::MapEnd(Message* message,
+                               const FieldDescriptor* field) const {
   USAGE_CHECK(IsMapFieldInApi(field), "MapEnd", "Field is not a map field.");
   MapIterator iter(message, field);
   GetRaw<MapFieldBase>(*message, field).MapEnd(&iter);
   return iter;
 }
 
-int GeneratedMessageReflection::MapSize(const Message& message,
-                                        const FieldDescriptor* field) const {
+int Reflection::MapSize(const Message& message,
+                        const FieldDescriptor* field) const {
   USAGE_CHECK(IsMapFieldInApi(field), "MapSize", "Field is not a map field.");
   return GetRaw<MapFieldBase>(message, field).size();
 }
 
 // -----------------------------------------------------------------------------
 
-const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName(
+const FieldDescriptor* Reflection::FindKnownExtensionByName(
     const std::string& name) const {
-  if (!schema_.HasExtensionSet()) return NULL;
-
-  const FieldDescriptor* result = descriptor_pool_->FindExtensionByName(name);
-  if (result != NULL && result->containing_type() == descriptor_) {
-    return result;
-  }
-
-  if (descriptor_->options().message_set_wire_format()) {
-    // MessageSet extensions may be identified by type name.
-    const Descriptor* type = descriptor_pool_->FindMessageTypeByName(name);
-    if (type != NULL) {
-      // Look for a matching extension in the foreign type's scope.
-      const int type_extension_count = type->extension_count();
-      for (int i = 0; i < type_extension_count; i++) {
-        const FieldDescriptor* extension = type->extension(i);
-        if (extension->containing_type() == descriptor_ &&
-            extension->type() == FieldDescriptor::TYPE_MESSAGE &&
-            extension->is_optional() && extension->message_type() == type) {
-          // Found it.
-          return extension;
-        }
-      }
-    }
-  }
-
-  return NULL;
+  if (!schema_.HasExtensionSet()) return nullptr;
+  return descriptor_pool_->FindExtensionByPrintableName(descriptor_, name);
 }
 
-const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber(
+const FieldDescriptor* Reflection::FindKnownExtensionByNumber(
     int number) const {
-  if (!schema_.HasExtensionSet()) return NULL;
+  if (!schema_.HasExtensionSet()) return nullptr;
   return descriptor_pool_->FindExtensionByNumber(descriptor_, number);
 }
 
-bool GeneratedMessageReflection::SupportsUnknownEnumValues() const {
+bool Reflection::SupportsUnknownEnumValues() const {
   return CreateUnknownEnumValues(descriptor_->file());
 }
 
@@ -1839,111 +1832,105 @@
 // the given field.
 
 template <class Type>
-const Type& GeneratedMessageReflection::GetRawNonOneof(
-    const Message& message, const FieldDescriptor* field) const {
+const Type& Reflection::GetRawNonOneof(const Message& message,
+                                       const FieldDescriptor* field) const {
   return GetConstRefAtOffset<Type>(message,
                                    schema_.GetFieldOffsetNonOneof(field));
 }
 
 template <class Type>
-Type* GeneratedMessageReflection::MutableRawNonOneof(
-    Message* message, const FieldDescriptor* field) const {
+Type* Reflection::MutableRawNonOneof(Message* message,
+                                     const FieldDescriptor* field) const {
   return GetPointerAtOffset<Type>(message,
                                   schema_.GetFieldOffsetNonOneof(field));
 }
 
 template <typename Type>
-const Type& GeneratedMessageReflection::GetRaw(
-    const Message& message, const FieldDescriptor* field) const {
+const Type& Reflection::GetRaw(const Message& message,
+                               const FieldDescriptor* field) const {
   if (field->containing_oneof() && !HasOneofField(message, field)) {
     return DefaultRaw<Type>(field);
   }
   return GetConstRefAtOffset<Type>(message, schema_.GetFieldOffset(field));
 }
 
-bool GeneratedMessageReflection::IsInlined(const FieldDescriptor* field) const {
+bool Reflection::IsInlined(const FieldDescriptor* field) const {
   return schema_.IsFieldInlined(field);
 }
 
 template <typename Type>
-Type* GeneratedMessageReflection::MutableRaw(
-    Message* message, const FieldDescriptor* field) const {
+Type* Reflection::MutableRaw(Message* message,
+                             const FieldDescriptor* field) const {
   return GetPointerAtOffset<Type>(message, schema_.GetFieldOffset(field));
 }
 
-inline const uint32* GeneratedMessageReflection::GetHasBits(
-    const Message& message) const {
+const uint32* Reflection::GetHasBits(const Message& message) const {
   GOOGLE_DCHECK(schema_.HasHasbits());
   return &GetConstRefAtOffset<uint32>(message, schema_.HasBitsOffset());
 }
 
-inline uint32* GeneratedMessageReflection::MutableHasBits(
-    Message* message) const {
+uint32* Reflection::MutableHasBits(Message* message) const {
   GOOGLE_DCHECK(schema_.HasHasbits());
   return GetPointerAtOffset<uint32>(message, schema_.HasBitsOffset());
 }
 
-inline uint32 GeneratedMessageReflection::GetOneofCase(
+uint32 Reflection::GetOneofCase(
     const Message& message, const OneofDescriptor* oneof_descriptor) const {
   return GetConstRefAtOffset<uint32>(
       message, schema_.GetOneofCaseOffset(oneof_descriptor));
 }
 
-inline uint32* GeneratedMessageReflection::MutableOneofCase(
+uint32* Reflection::MutableOneofCase(
     Message* message, const OneofDescriptor* oneof_descriptor) const {
   return GetPointerAtOffset<uint32>(
       message, schema_.GetOneofCaseOffset(oneof_descriptor));
 }
 
-inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet(
+const ExtensionSet& Reflection::GetExtensionSet(
     const Message& message) const {
   return GetConstRefAtOffset<ExtensionSet>(message,
                                            schema_.GetExtensionSetOffset());
 }
 
-inline ExtensionSet* GeneratedMessageReflection::MutableExtensionSet(
-    Message* message) const {
+ExtensionSet* Reflection::MutableExtensionSet(Message* message) const {
   return GetPointerAtOffset<ExtensionSet>(message,
                                           schema_.GetExtensionSetOffset());
 }
 
-inline Arena* GeneratedMessageReflection::GetArena(Message* message) const {
+Arena* Reflection::GetArena(Message* message) const {
   return GetInternalMetadataWithArena(*message).arena();
 }
 
-inline const InternalMetadataWithArena&
-GeneratedMessageReflection::GetInternalMetadataWithArena(
-    const Message& message) const {
+const InternalMetadataWithArena&
+Reflection::GetInternalMetadataWithArena(const Message& message) const {
   return GetConstRefAtOffset<InternalMetadataWithArena>(
       message, schema_.GetMetadataOffset());
 }
 
-inline InternalMetadataWithArena*
-GeneratedMessageReflection::MutableInternalMetadataWithArena(
+InternalMetadataWithArena* Reflection::MutableInternalMetadataWithArena(
     Message* message) const {
   return GetPointerAtOffset<InternalMetadataWithArena>(
       message, schema_.GetMetadataOffset());
 }
 
 template <typename Type>
-inline const Type& GeneratedMessageReflection::DefaultRaw(
-    const FieldDescriptor* field) const {
+const Type& Reflection::DefaultRaw(const FieldDescriptor* field) const {
   return *reinterpret_cast<const Type*>(schema_.GetFieldDefault(field));
 }
 
 // Simple accessors for manipulating has_bits_.
-inline bool GeneratedMessageReflection::HasBit(
-    const Message& message, const FieldDescriptor* field) const {
+bool Reflection::HasBit(const Message& message,
+                               const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
   if (schema_.HasHasbits()) {
     return IsIndexInHasBitSet(GetHasBits(message), schema_.HasBitIndex(field));
   }
 
   // proto3: no has-bits. All fields present except messages, which are
-  // present only if their message-field pointer is non-NULL.
+  // present only if their message-field pointer is non-null.
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     return !schema_.IsDefaultInstance(message) &&
-           GetRaw<const Message*>(message, field) != NULL;
+           GetRaw<const Message*>(message, field) != nullptr;
   } else {
     // Non-message field (and non-oneof, since that was handled in HasField()
     // before calling us), and singular (again, checked in HasField). So, this
@@ -1993,8 +1980,8 @@
   }
 }
 
-inline void GeneratedMessageReflection::SetBit(
-    Message* message, const FieldDescriptor* field) const {
+void Reflection::SetBit(Message* message,
+                               const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
   if (!schema_.HasHasbits()) {
     return;
@@ -2004,8 +1991,8 @@
       (static_cast<uint32>(1) << (index % 32));
 }
 
-inline void GeneratedMessageReflection::ClearBit(
-    Message* message, const FieldDescriptor* field) const {
+void Reflection::ClearBit(Message* message,
+                                 const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
   if (!schema_.HasHasbits()) {
     return;
@@ -2015,8 +2002,8 @@
       ~(static_cast<uint32>(1) << (index % 32));
 }
 
-inline void GeneratedMessageReflection::SwapBit(
-    Message* message1, Message* message2, const FieldDescriptor* field) const {
+void Reflection::SwapBit(Message* message1, Message* message2,
+                                const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!field->options().weak());
   if (!schema_.HasHasbits()) {
     return;
@@ -2034,29 +2021,29 @@
   }
 }
 
-inline bool GeneratedMessageReflection::HasOneof(
-    const Message& message, const OneofDescriptor* oneof_descriptor) const {
+bool Reflection::HasOneof(const Message& message,
+                          const OneofDescriptor* oneof_descriptor) const {
   return (GetOneofCase(message, oneof_descriptor) > 0);
 }
 
-inline bool GeneratedMessageReflection::HasOneofField(
-    const Message& message, const FieldDescriptor* field) const {
+bool Reflection::HasOneofField(const Message& message,
+                                      const FieldDescriptor* field) const {
   return (GetOneofCase(message, field->containing_oneof()) == field->number());
 }
 
-inline void GeneratedMessageReflection::SetOneofCase(
-    Message* message, const FieldDescriptor* field) const {
+void Reflection::SetOneofCase(Message* message,
+                                     const FieldDescriptor* field) const {
   *MutableOneofCase(message, field->containing_oneof()) = field->number();
 }
 
-inline void GeneratedMessageReflection::ClearOneofField(
-    Message* message, const FieldDescriptor* field) const {
+void Reflection::ClearOneofField(Message* message,
+                                        const FieldDescriptor* field) const {
   if (HasOneofField(*message, field)) {
     ClearOneof(message, field->containing_oneof());
   }
 }
 
-inline void GeneratedMessageReflection::ClearOneof(
+void Reflection::ClearOneof(
     Message* message, const OneofDescriptor* oneof_descriptor) const {
   // TODO(jieluo): Consider to cache the unused object instead of deleting
   // it. It will be much faster if an application switches a lot from
@@ -2064,7 +2051,7 @@
   uint32 oneof_case = GetOneofCase(*message, oneof_descriptor);
   if (oneof_case > 0) {
     const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case);
-    if (GetArena(message) == NULL) {
+    if (GetArena(message) == nullptr) {
       switch (field->cpp_type()) {
         case FieldDescriptor::CPPTYPE_STRING: {
           switch (field->options().ctype()) {
@@ -2092,19 +2079,52 @@
   }
 }
 
+#define HANDLE_TYPE(TYPE, CPPTYPE, CTYPE)                               \
+  template <>                                                           \
+  const RepeatedField<TYPE>& Reflection::GetRepeatedField<TYPE>(        \
+      const Message& message, const FieldDescriptor* field) const {     \
+    return *static_cast<RepeatedField<TYPE>*>(MutableRawRepeatedField(  \
+        const_cast<Message*>(&message), field, CPPTYPE, CTYPE, NULL));  \
+  }                                                                     \
+                                                                        \
+  template <>                                                           \
+  RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>(          \
+      Message * message, const FieldDescriptor* field) const {          \
+    return static_cast<RepeatedField<TYPE>*>(                           \
+        MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
+  }
+
+HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1);
+HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1);
+HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
+HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
+HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
+HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
+HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
+
+
+#undef HANDLE_TYPE
+
+void* Reflection::MutableRawRepeatedString(Message* message,
+                                           const FieldDescriptor* field,
+                                           bool is_string) const {
+  return MutableRawRepeatedField(message, field,
+                                 FieldDescriptor::CPPTYPE_STRING,
+                                 FieldOptions::STRING, NULL);
+}
+
 // Template implementations of basic accessors.  Inline because each
 // template instance is only called from one location.  These are
 // used for all types except messages.
 template <typename Type>
-inline const Type& GeneratedMessageReflection::GetField(
-    const Message& message, const FieldDescriptor* field) const {
+const Type& Reflection::GetField(const Message& message,
+                                        const FieldDescriptor* field) const {
   return GetRaw<Type>(message, field);
 }
 
 template <typename Type>
-inline void GeneratedMessageReflection::SetField(Message* message,
-                                                 const FieldDescriptor* field,
-                                                 const Type& value) const {
+void Reflection::SetField(Message* message, const FieldDescriptor* field,
+                                 const Type& value) const {
   if (field->containing_oneof() && !HasOneofField(*message, field)) {
     ClearOneof(message, field->containing_oneof());
   }
@@ -2114,62 +2134,65 @@
 }
 
 template <typename Type>
-inline Type* GeneratedMessageReflection::MutableField(
-    Message* message, const FieldDescriptor* field) const {
+Type* Reflection::MutableField(Message* message,
+                                      const FieldDescriptor* field) const {
   field->containing_oneof() ? SetOneofCase(message, field)
                             : SetBit(message, field);
   return MutableRaw<Type>(message, field);
 }
 
 template <typename Type>
-inline const Type& GeneratedMessageReflection::GetRepeatedField(
-    const Message& message, const FieldDescriptor* field, int index) const {
+const Type& Reflection::GetRepeatedField(const Message& message,
+                                                const FieldDescriptor* field,
+                                                int index) const {
   return GetRaw<RepeatedField<Type> >(message, field).Get(index);
 }
 
 template <typename Type>
-inline const Type& GeneratedMessageReflection::GetRepeatedPtrField(
-    const Message& message, const FieldDescriptor* field, int index) const {
+const Type& Reflection::GetRepeatedPtrField(const Message& message,
+                                                   const FieldDescriptor* field,
+                                                   int index) const {
   return GetRaw<RepeatedPtrField<Type> >(message, field).Get(index);
 }
 
 template <typename Type>
-inline void GeneratedMessageReflection::SetRepeatedField(
-    Message* message, const FieldDescriptor* field, int index,
-    Type value) const {
+void Reflection::SetRepeatedField(Message* message,
+                                         const FieldDescriptor* field,
+                                         int index, Type value) const {
   MutableRaw<RepeatedField<Type> >(message, field)->Set(index, value);
 }
 
 template <typename Type>
-inline Type* GeneratedMessageReflection::MutableRepeatedField(
-    Message* message, const FieldDescriptor* field, int index) const {
+Type* Reflection::MutableRepeatedField(Message* message,
+                                              const FieldDescriptor* field,
+                                              int index) const {
   RepeatedPtrField<Type>* repeated =
       MutableRaw<RepeatedPtrField<Type> >(message, field);
   return repeated->Mutable(index);
 }
 
 template <typename Type>
-inline void GeneratedMessageReflection::AddField(Message* message,
-                                                 const FieldDescriptor* field,
-                                                 const Type& value) const {
+void Reflection::AddField(Message* message, const FieldDescriptor* field,
+                                 const Type& value) const {
   MutableRaw<RepeatedField<Type> >(message, field)->Add(value);
 }
 
 template <typename Type>
-inline Type* GeneratedMessageReflection::AddField(
-    Message* message, const FieldDescriptor* field) const {
+Type* Reflection::AddField(Message* message,
+                                  const FieldDescriptor* field) const {
   RepeatedPtrField<Type>* repeated =
       MutableRaw<RepeatedPtrField<Type> >(message, field);
   return repeated->Add();
 }
 
-MessageFactory* GeneratedMessageReflection::GetMessageFactory() const {
+MessageFactory* Reflection::GetMessageFactory() const {
   return message_factory_;
 }
 
-void* GeneratedMessageReflection::RepeatedFieldData(
-    Message* message, const FieldDescriptor* field,
-    FieldDescriptor::CppType cpp_type, const Descriptor* message_type) const {
+void* Reflection::RepeatedFieldData(Message* message,
+                                    const FieldDescriptor* field,
+                                    FieldDescriptor::CppType cpp_type,
+                                    const Descriptor* message_type) const {
   GOOGLE_CHECK(field->is_repeated());
   GOOGLE_CHECK(field->cpp_type() == cpp_type ||
         (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
@@ -2177,7 +2200,7 @@
       << "The type parameter T in RepeatedFieldRef<T> API doesn't match "
       << "the actual field type (for enums T should be the generated enum "
       << "type or int32).";
-  if (message_type != NULL) {
+  if (message_type != nullptr) {
     GOOGLE_CHECK_EQ(message_type, field->message_type());
   }
   if (field->is_extension()) {
@@ -2188,15 +2211,15 @@
   }
 }
 
-MapFieldBase* GeneratedMessageReflection::MutableMapData(
-    Message* message, const FieldDescriptor* field) const {
+MapFieldBase* Reflection::MutableMapData(Message* message,
+                                         const FieldDescriptor* field) const {
   USAGE_CHECK(IsMapFieldInApi(field), "GetMapData",
               "Field is not a map field.");
   return MutableRaw<MapFieldBase>(message, field);
 }
 
-const MapFieldBase* GeneratedMessageReflection::GetMapData(
-    const Message& message, const FieldDescriptor* field) const {
+const MapFieldBase* Reflection::GetMapData(const Message& message,
+                                           const FieldDescriptor* field) const {
   USAGE_CHECK(IsMapFieldInApi(field), "GetMapData",
               "Field is not a map field.");
   return &(GetRaw<MapFieldBase>(message, field));
@@ -2223,13 +2246,14 @@
   return result;
 }
 
-template <typename Schema>
+}  // namespace
+
 class AssignDescriptorsHelper {
  public:
   AssignDescriptorsHelper(MessageFactory* factory,
                           Metadata* file_level_metadata,
                           const EnumDescriptor** file_level_enum_descriptors,
-                          const Schema* schemas,
+                          const MigrationSchema* schemas,
                           const Message* const* default_instance_data,
                           const uint32* offsets)
       : factory_(factory),
@@ -2246,11 +2270,11 @@
 
     file_level_metadata_->descriptor = descriptor;
 
-    file_level_metadata_->reflection = new GeneratedMessageReflection(
-        descriptor,
-        MigrationToReflectionSchema(default_instance_data_, offsets_,
-                                    *schemas_),
-        DescriptorPool::internal_generated_pool(), factory_);
+    file_level_metadata_->reflection =
+        new Reflection(descriptor,
+                       MigrationToReflectionSchema(default_instance_data_,
+                                                   offsets_, *schemas_),
+                       DescriptorPool::internal_generated_pool(), factory_);
     for (int i = 0; i < descriptor->enum_type_count(); i++) {
       AssignEnumDescriptor(descriptor->enum_type(i));
     }
@@ -2270,11 +2294,13 @@
   MessageFactory* factory_;
   Metadata* file_level_metadata_;
   const EnumDescriptor** file_level_enum_descriptors_;
-  const Schema* schemas_;
+  const MigrationSchema* schemas_;
   const Message* const* default_instance_data_;
   const uint32* offsets_;
 };
 
+namespace {
+
 // We have the routines that assign descriptors and build reflection
 // automatically delete the allocated reflection. MetadataOwner owns
 // all the allocated reflection instances.
@@ -2319,11 +2345,11 @@
   const FileDescriptor* file =
       DescriptorPool::internal_generated_pool()->FindFileByName(
           table->filename);
-  GOOGLE_CHECK(file != NULL);
+  GOOGLE_CHECK(file != nullptr);
 
   MessageFactory* factory = MessageFactory::generated_factory();
 
-  AssignDescriptorsHelper<MigrationSchema> helper(
+  AssignDescriptorsHelper helper(
       factory, table->file_level_metadata, table->file_level_enum_descriptors,
       table->schemas, table->default_instances, table->offsets);
 
@@ -2364,6 +2390,19 @@
 
 }  // namespace
 
+// Separate function because it needs to be a friend of
+// Reflection
+void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) {
+  for (int i = 0; i < size; i++) {
+    const Reflection* reflection = file_level_metadata[i].reflection;
+    MessageFactory::InternalRegisterGeneratedMessage(
+        file_level_metadata[i].descriptor,
+        reflection->schema_.default_instance_);
+  }
+}
+
+namespace internal {
+
 void AssignDescriptors(const DescriptorTable* table) {
   call_once(*table->once, AssignDescriptorsImpl, table);
 }
@@ -2378,19 +2417,6 @@
   AddDescriptorsImpl(table);
 }
 
-// Separate function because it needs to be a friend of
-// GeneratedMessageReflection
-void RegisterAllTypesInternal(const Metadata* file_level_metadata, int size) {
-  for (int i = 0; i < size; i++) {
-    const GeneratedMessageReflection* reflection =
-        static_cast<const GeneratedMessageReflection*>(
-            file_level_metadata[i].reflection);
-    MessageFactory::InternalRegisterGeneratedMessage(
-        file_level_metadata[i].descriptor,
-        reflection->schema_.default_instance_);
-  }
-}
-
 void RegisterFileLevelMetadata(const DescriptorTable* table) {
   AssignDescriptors(table);
   RegisterAllTypesInternal(table->file_level_metadata, table->num_messages);
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index a0555b5..f61dce4 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -44,8 +44,8 @@
 #include <google/protobuf/stubs/common.h>
 // TODO(jasonh): Remove this once the compiler change to directly include this
 // is released to components.
+#include <google/protobuf/descriptor.h>
 #include <google/protobuf/generated_enum_reflection.h>
-#include <google/protobuf/message.h>
 #include <google/protobuf/metadata.h>
 #include <google/protobuf/stubs/once.h>
 #include <google/protobuf/port.h>
@@ -58,17 +58,14 @@
 #error "You cannot SWIG proto headers"
 #endif
 
-namespace upb {
-namespace google_opensource {
-class GMR_Handlers;
-}  // namespace google_opensource
-}  // namespace upb
-
 namespace google {
 namespace protobuf {
 class DescriptorPool;
 class MapKey;
 class MapValueRef;
+class MessageLayoutInspector;
+class Message;
+struct Metadata;
 }  // namespace protobuf
 }  // namespace google
 
@@ -79,9 +76,6 @@
 class DefaultEmptyOneof;
 class ReflectionAccessor;
 
-// Defined in this file.
-class GeneratedMessageReflection;
-
 // Defined in other files.
 class ExtensionSet;  // extension_set.h
 class WeakFieldMap;  // weak_field_map.h
@@ -92,7 +86,7 @@
 //                  used to obtain pointers to default instances of embedded
 //                  messages, which GetMessage() will return if the particular
 //                  sub-message has not been initialized yet.  (Thus, all
-//                  embedded message fields *must* have non-NULL pointers
+//                  embedded message fields *must* have non-null pointers
 //                  in the default instance.)
 //   offsets:       An array of ints giving the byte offsets.
 //                  For each oneof or weak field, the offset is relative to the
@@ -269,396 +263,6 @@
   int object_size;
 };
 
-// THIS CLASS IS NOT INTENDED FOR DIRECT USE.  It is intended for use
-// by generated code.  This class is just a big hack that reduces code
-// size.
-//
-// A GeneratedMessageReflection is an implementation of Reflection
-// which expects all fields to be backed by simple variables located in
-// memory.  The locations are given using a base pointer and a set of
-// offsets.
-//
-// It is required that the user represents fields of each type in a standard
-// way, so that GeneratedMessageReflection can cast the void* pointer to
-// the appropriate type.  For primitive fields and string fields, each
-// field should be represented using the obvious C++ primitive type.  Enums and
-// Messages are different:
-//  - Singular Message fields are stored as a pointer to a Message.  These
-//    should start out NULL, except for in the default instance where they
-//    should start out pointing to other default instances.
-//  - Enum fields are stored as an int.  This int must always contain
-//    a valid value, such that EnumDescriptor::FindValueByNumber() would
-//    not return NULL.
-//  - Repeated fields are stored as RepeatedFields or RepeatedPtrFields
-//    of whatever type the individual field would be.  Strings and
-//    Messages use RepeatedPtrFields while everything else uses
-//    RepeatedFields.
-class GeneratedMessageReflection final : public Reflection {
- public:
-  // Constructs a GeneratedMessageReflection.
-  // Parameters:
-  //   descriptor:    The descriptor for the message type being implemented.
-  //   schema:        The description of the internal guts of the message.
-  //   pool:          DescriptorPool to search for extension definitions.  Only
-  //                  used by FindKnownExtensionByName() and
-  //                  FindKnownExtensionByNumber().
-  //   factory:       MessageFactory to use to construct extension messages.
-  GeneratedMessageReflection(const Descriptor* descriptor,
-                             const ReflectionSchema& schema,
-                             const DescriptorPool* pool,
-                             MessageFactory* factory);
-
-  ~GeneratedMessageReflection() override;
-
-  // implements Reflection -------------------------------------------
-
-  const UnknownFieldSet& GetUnknownFields(
-      const Message& message) const override;
-  UnknownFieldSet* MutableUnknownFields(Message* message) const override;
-
-  size_t SpaceUsedLong(const Message& message) const override;
-
-  bool HasField(const Message& message,
-                const FieldDescriptor* field) const override;
-  int FieldSize(const Message& message,
-                const FieldDescriptor* field) const override;
-  void ClearField(Message* message,
-                  const FieldDescriptor* field) const override;
-  bool HasOneof(const Message& message,
-                const OneofDescriptor* oneof_descriptor) const override;
-  void ClearOneof(Message* message,
-                  const OneofDescriptor* oneof_descriptor) const override;
-  void RemoveLast(Message* message,
-                  const FieldDescriptor* field) const override;
-  Message* ReleaseLast(Message* message,
-                       const FieldDescriptor* field) const override;
-  void Swap(Message* message1, Message* message2) const override;
-  void SwapFields(
-      Message* message1, Message* message2,
-      const std::vector<const FieldDescriptor*>& fields) const override;
-  void SwapElements(Message* message, const FieldDescriptor* field, int index1,
-                    int index2) const override;
-  void ListFields(const Message& message,
-                  std::vector<const FieldDescriptor*>* output) const override;
-  int32 GetInt32(const Message& message,
-                 const FieldDescriptor* field) const override;
-  int64 GetInt64(const Message& message,
-                 const FieldDescriptor* field) const override;
-  uint32 GetUInt32(const Message& message,
-                   const FieldDescriptor* field) const override;
-  uint64 GetUInt64(const Message& message,
-                   const FieldDescriptor* field) const override;
-  float GetFloat(const Message& message,
-                 const FieldDescriptor* field) const override;
-  double GetDouble(const Message& message,
-                   const FieldDescriptor* field) const override;
-  bool GetBool(const Message& message,
-               const FieldDescriptor* field) const override;
-  std::string GetString(const Message& message,
-                        const FieldDescriptor* field) const override;
-  const std::string& GetStringReference(const Message& message,
-                                        const FieldDescriptor* field,
-                                        std::string* scratch) const override;
-  const EnumValueDescriptor* GetEnum(
-      const Message& message, const FieldDescriptor* field) const override;
-  int GetEnumValue(const Message& message,
-                   const FieldDescriptor* field) const override;
-  const Message& GetMessage(const Message& message,
-                            const FieldDescriptor* field,
-                            MessageFactory* factory = NULL) const override;
-
-  const FieldDescriptor* GetOneofFieldDescriptor(
-      const Message& message,
-      const OneofDescriptor* oneof_descriptor) const override;
-
- private:
-  bool ContainsMapKey(const Message& message, const FieldDescriptor* field,
-                      const MapKey& key) const override;
-  bool InsertOrLookupMapValue(Message* message, const FieldDescriptor* field,
-                              const MapKey& key,
-                              MapValueRef* val) const override;
-  bool DeleteMapValue(Message* message, const FieldDescriptor* field,
-                      const MapKey& key) const override;
-  MapIterator MapBegin(Message* message,
-                       const FieldDescriptor* field) const override;
-  MapIterator MapEnd(Message* message,
-                     const FieldDescriptor* field) const override;
-  int MapSize(const Message& message,
-              const FieldDescriptor* field) const override;
-
- public:
-  void SetInt32(Message* message, const FieldDescriptor* field,
-                int32 value) const override;
-  void SetInt64(Message* message, const FieldDescriptor* field,
-                int64 value) const override;
-  void SetUInt32(Message* message, const FieldDescriptor* field,
-                 uint32 value) const override;
-  void SetUInt64(Message* message, const FieldDescriptor* field,
-                 uint64 value) const override;
-  void SetFloat(Message* message, const FieldDescriptor* field,
-                float value) const override;
-  void SetDouble(Message* message, const FieldDescriptor* field,
-                 double value) const override;
-  void SetBool(Message* message, const FieldDescriptor* field,
-               bool value) const override;
-  void SetString(Message* message, const FieldDescriptor* field,
-                 const std::string& value) const override;
-  void SetEnum(Message* message, const FieldDescriptor* field,
-               const EnumValueDescriptor* value) const override;
-  void SetEnumValue(Message* message, const FieldDescriptor* field,
-                    int value) const override;
-  Message* MutableMessage(Message* message, const FieldDescriptor* field,
-                          MessageFactory* factory = NULL) const override;
-  void SetAllocatedMessage(Message* message, Message* sub_message,
-                           const FieldDescriptor* field) const override;
-  Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
-                          MessageFactory* factory = NULL) const override;
-
-  int32 GetRepeatedInt32(const Message& message, const FieldDescriptor* field,
-                         int index) const override;
-  int64 GetRepeatedInt64(const Message& message, const FieldDescriptor* field,
-                         int index) const override;
-  uint32 GetRepeatedUInt32(const Message& message, const FieldDescriptor* field,
-                           int index) const override;
-  uint64 GetRepeatedUInt64(const Message& message, const FieldDescriptor* field,
-                           int index) const override;
-  float GetRepeatedFloat(const Message& message, const FieldDescriptor* field,
-                         int index) const override;
-  double GetRepeatedDouble(const Message& message, const FieldDescriptor* field,
-                           int index) const override;
-  bool GetRepeatedBool(const Message& message, const FieldDescriptor* field,
-                       int index) const override;
-  std::string GetRepeatedString(const Message& message,
-                                const FieldDescriptor* field,
-                                int index) const override;
-  const std::string& GetRepeatedStringReference(
-      const Message& message, const FieldDescriptor* field, int index,
-      std::string* scratch) const override;
-  const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
-                                             const FieldDescriptor* field,
-                                             int index) const override;
-  int GetRepeatedEnumValue(const Message& message, const FieldDescriptor* field,
-                           int index) const override;
-  const Message& GetRepeatedMessage(const Message& message,
-                                    const FieldDescriptor* field,
-                                    int index) const override;
-
-  // Set the value of a field.
-  void SetRepeatedInt32(Message* message, const FieldDescriptor* field,
-                        int index, int32 value) const override;
-  void SetRepeatedInt64(Message* message, const FieldDescriptor* field,
-                        int index, int64 value) const override;
-  void SetRepeatedUInt32(Message* message, const FieldDescriptor* field,
-                         int index, uint32 value) const override;
-  void SetRepeatedUInt64(Message* message, const FieldDescriptor* field,
-                         int index, uint64 value) const override;
-  void SetRepeatedFloat(Message* message, const FieldDescriptor* field,
-                        int index, float value) const override;
-  void SetRepeatedDouble(Message* message, const FieldDescriptor* field,
-                         int index, double value) const override;
-  void SetRepeatedBool(Message* message, const FieldDescriptor* field,
-                       int index, bool value) const override;
-  void SetRepeatedString(Message* message, const FieldDescriptor* field,
-                         int index, const std::string& value) const override;
-  void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
-                       int index,
-                       const EnumValueDescriptor* value) const override;
-  void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field,
-                            int index, int value) const override;
-  // Get a mutable pointer to a field with a message type.
-  Message* MutableRepeatedMessage(Message* message,
-                                  const FieldDescriptor* field,
-                                  int index) const override;
-
-  void AddInt32(Message* message, const FieldDescriptor* field,
-                int32 value) const override;
-  void AddInt64(Message* message, const FieldDescriptor* field,
-                int64 value) const override;
-  void AddUInt32(Message* message, const FieldDescriptor* field,
-                 uint32 value) const override;
-  void AddUInt64(Message* message, const FieldDescriptor* field,
-                 uint64 value) const override;
-  void AddFloat(Message* message, const FieldDescriptor* field,
-                float value) const override;
-  void AddDouble(Message* message, const FieldDescriptor* field,
-                 double value) const override;
-  void AddBool(Message* message, const FieldDescriptor* field,
-               bool value) const override;
-  void AddString(Message* message, const FieldDescriptor* field,
-                 const std::string& value) const override;
-  void AddEnum(Message* message, const FieldDescriptor* field,
-               const EnumValueDescriptor* value) const override;
-  void AddEnumValue(Message* message, const FieldDescriptor* field,
-                    int value) const override;
-  Message* AddMessage(Message* message, const FieldDescriptor* field,
-                      MessageFactory* factory = NULL) const override;
-  void AddAllocatedMessage(Message* message, const FieldDescriptor* field,
-                           Message* new_entry) const override;
-
-  const FieldDescriptor* FindKnownExtensionByName(
-      const std::string& name) const override;
-  const FieldDescriptor* FindKnownExtensionByNumber(int number) const override;
-
-  bool SupportsUnknownEnumValues() const override;
-
-  // This value for arena_offset_ indicates that there is no arena pointer in
-  // this message (e.g., old generated code).
-  static const int kNoArenaPointer = -1;
-
-  // This value for unknown_field_offset_ indicates that there is no
-  // UnknownFieldSet in this message, and that instead, we are using the
-  // Zero-Overhead Arena Pointer trick. When this is the case, arena_offset_
-  // actually indexes to an InternalMetadataWithArena instance, which can return
-  // either an arena pointer or an UnknownFieldSet or both. It is never the case
-  // that unknown_field_offset_ == kUnknownFieldSetInMetadata && arena_offset_
-  // == kNoArenaPointer.
-  static const int kUnknownFieldSetInMetadata = -1;
-
- protected:
-  void* MutableRawRepeatedField(Message* message, const FieldDescriptor* field,
-                                FieldDescriptor::CppType, int ctype,
-                                const Descriptor* desc) const override;
-
-  const void* GetRawRepeatedField(const Message& message,
-                                  const FieldDescriptor* field,
-                                  FieldDescriptor::CppType, int ctype,
-                                  const Descriptor* desc) const override;
-
-  MessageFactory* GetMessageFactory() const override;
-
-  void* RepeatedFieldData(Message* message, const FieldDescriptor* field,
-                          FieldDescriptor::CppType cpp_type,
-                          const Descriptor* message_type) const override;
-
- private:
-  friend class ReflectionAccessor;
-  friend class upb::google_opensource::GMR_Handlers;
-
-  const Descriptor* const descriptor_;
-  const ReflectionSchema schema_;
-  const DescriptorPool* const descriptor_pool_;
-  MessageFactory* const message_factory_;
-
-  // Last non weak field index. This is an optimization when most weak fields
-  // are at the end of the containing message. If a message proto doesn't
-  // contain weak fields, then this field equals descriptor_->field_count().
-  int last_non_weak_field_index_;
-
-  template <class T>
-  const T& GetRawNonOneof(const Message& message,
-                          const FieldDescriptor* field) const;
-  template <class T>
-  T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const;
-
-  template <typename Type>
-  const Type& GetRaw(const Message& message,
-                     const FieldDescriptor* field) const;
-  template <typename Type>
-  inline Type* MutableRaw(Message* message, const FieldDescriptor* field) const;
-  template <typename Type>
-  inline const Type& DefaultRaw(const FieldDescriptor* field) const;
-
-  inline const uint32* GetHasBits(const Message& message) const;
-  inline uint32* MutableHasBits(Message* message) const;
-  inline uint32 GetOneofCase(const Message& message,
-                             const OneofDescriptor* oneof_descriptor) const;
-  inline uint32* MutableOneofCase(
-      Message* message, const OneofDescriptor* oneof_descriptor) const;
-  inline const ExtensionSet& GetExtensionSet(const Message& message) const;
-  inline ExtensionSet* MutableExtensionSet(Message* message) const;
-  inline Arena* GetArena(Message* message) const;
-
-  inline const InternalMetadataWithArena& GetInternalMetadataWithArena(
-      const Message& message) const;
-
-  inline InternalMetadataWithArena* MutableInternalMetadataWithArena(
-      Message* message) const;
-
-  inline bool IsInlined(const FieldDescriptor* field) const;
-
-  inline bool HasBit(const Message& message,
-                     const FieldDescriptor* field) const;
-  inline void SetBit(Message* message, const FieldDescriptor* field) const;
-  inline void ClearBit(Message* message, const FieldDescriptor* field) const;
-  inline void SwapBit(Message* message1, Message* message2,
-                      const FieldDescriptor* field) const;
-
-  // This function only swaps the field. Should swap corresponding has_bit
-  // before or after using this function.
-  void SwapField(Message* message1, Message* message2,
-                 const FieldDescriptor* field) const;
-
-  void SwapOneofField(Message* message1, Message* message2,
-                      const OneofDescriptor* oneof_descriptor) const;
-
-  inline bool HasOneofField(const Message& message,
-                            const FieldDescriptor* field) const;
-  inline void SetOneofCase(Message* message,
-                           const FieldDescriptor* field) const;
-  inline void ClearOneofField(Message* message,
-                              const FieldDescriptor* field) const;
-
-  template <typename Type>
-  inline const Type& GetField(const Message& message,
-                              const FieldDescriptor* field) const;
-  template <typename Type>
-  inline void SetField(Message* message, const FieldDescriptor* field,
-                       const Type& value) const;
-  template <typename Type>
-  inline Type* MutableField(Message* message,
-                            const FieldDescriptor* field) const;
-  template <typename Type>
-  inline const Type& GetRepeatedField(const Message& message,
-                                      const FieldDescriptor* field,
-                                      int index) const;
-  template <typename Type>
-  inline const Type& GetRepeatedPtrField(const Message& message,
-                                         const FieldDescriptor* field,
-                                         int index) const;
-  template <typename Type>
-  inline void SetRepeatedField(Message* message, const FieldDescriptor* field,
-                               int index, Type value) const;
-  template <typename Type>
-  inline Type* MutableRepeatedField(Message* message,
-                                    const FieldDescriptor* field,
-                                    int index) const;
-  template <typename Type>
-  inline void AddField(Message* message, const FieldDescriptor* field,
-                       const Type& value) const;
-  template <typename Type>
-  inline Type* AddField(Message* message, const FieldDescriptor* field) const;
-
-  int GetExtensionNumberOrDie(const Descriptor* type) const;
-
-  // Internal versions of EnumValue API perform no checking. Called after checks
-  // by public methods.
-  void SetEnumValueInternal(Message* message, const FieldDescriptor* field,
-                            int value) const;
-  void SetRepeatedEnumValueInternal(Message* message,
-                                    const FieldDescriptor* field, int index,
-                                    int value) const;
-  void AddEnumValueInternal(Message* message, const FieldDescriptor* field,
-                            int value) const;
-
-  Message* UnsafeArenaReleaseMessage(Message* message,
-                                     const FieldDescriptor* field,
-                                     MessageFactory* factory = NULL) const;
-
-  void UnsafeArenaSetAllocatedMessage(Message* message, Message* sub_message,
-                                      const FieldDescriptor* field) const;
-
-  internal::MapFieldBase* MutableMapData(
-      Message* message, const FieldDescriptor* field) const override;
-
-  const internal::MapFieldBase* GetMapData(
-      const Message& message, const FieldDescriptor* field) const override;
-
-  friend inline  // inline so nobody can call this function.
-      void
-      RegisterAllTypesInternal(const Metadata* file_level_metadata, int size);
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratedMessageReflection);
-};
-
 struct PROTOBUF_EXPORT DescriptorTable {
   bool* is_initialized;
   const char* descriptor;
diff --git a/src/google/protobuf/generated_message_table_driven_lite.h b/src/google/protobuf/generated_message_table_driven_lite.h
index b36e51b..8cf177b 100644
--- a/src/google/protobuf/generated_message_table_driven_lite.h
+++ b/src/google/protobuf/generated_message_table_driven_lite.h
@@ -237,7 +237,7 @@
 
   switch (ctype) {
     case StringType_INLINED: {
-      InlinedStringField* s;
+      InlinedStringField* s = nullptr;
       switch (cardinality) {
         case Cardinality_SINGULAR:
           // TODO(ckennelly): Is this optimal?
diff --git a/src/google/protobuf/io/io_win32.cc b/src/google/protobuf/io/io_win32.cc
index b8f9bf8..eae2b7f 100755
--- a/src/google/protobuf/io/io_win32.cc
+++ b/src/google/protobuf/io/io_win32.cc
@@ -42,7 +42,7 @@
 //
 // This file is only used on Windows, it's empty on other platforms.
 
-#if defined(_WIN32)
+#if defined(_WIN32) && !defined(_XBOX_ONE)
 
 // 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
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 666266d..a650c87 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -126,7 +126,6 @@
             WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType,
             int default_enum>
   friend class internal::MapField;
-  friend class internal::GeneratedMessageReflection;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
 };
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 3b1dbb5..3314f4e 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -662,7 +662,7 @@
   template <typename K, typename V>
   friend class internal::TypeDefinedMapFieldBase;
   friend class ::PROTOBUF_NAMESPACE_ID::MapIterator;
-  friend class internal::GeneratedMessageReflection;
+  friend class Reflection;
   friend class internal::DynamicMapField;
 
   void SetType(FieldDescriptor::CppType type) { type_ = type; }
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc
index 5800b38..56259bb 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -150,7 +150,7 @@
  public:
   static void* GetOffset(void* msg, const google::protobuf::FieldDescriptor* f,
                          const google::protobuf::Reflection* r) {
-    return static_cast<char*>(msg) + CheckedCast(r)->schema_.GetFieldOffset(f);
+    return static_cast<char*>(msg) + r->schema_.GetFieldOffset(f);
   }
 
   static void* GetRepeatedEnum(const Reflection* reflection,
@@ -158,13 +158,6 @@
     return reflection->MutableRawRepeatedField(
         msg, field, FieldDescriptor::CPPTYPE_ENUM, 0, nullptr);
   }
-
- private:
-  static const GeneratedMessageReflection* CheckedCast(const Reflection* r) {
-    auto gr = dynamic_cast<const GeneratedMessageReflection*>(r);
-    GOOGLE_CHECK(gr != nullptr);
-    return gr;
-  }
 };
 
 }  // namespace internal
@@ -554,64 +547,6 @@
 }
 
 // =============================================================================
-// Reflection and associated Template Specializations
-
-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>(        \
-      const Message& message, const FieldDescriptor* field) const {     \
-    return *static_cast<RepeatedField<TYPE>*>(MutableRawRepeatedField(  \
-        const_cast<Message*>(&message), field, CPPTYPE, CTYPE, NULL));  \
-  }                                                                     \
-                                                                        \
-  template <>                                                           \
-  RepeatedField<TYPE>* Reflection::MutableRepeatedField<TYPE>(          \
-      Message * message, const FieldDescriptor* field) const {          \
-    return static_cast<RepeatedField<TYPE>*>(                           \
-        MutableRawRepeatedField(message, field, CPPTYPE, CTYPE, NULL)); \
-  }
-
-HANDLE_TYPE(int32, FieldDescriptor::CPPTYPE_INT32, -1);
-HANDLE_TYPE(int64, FieldDescriptor::CPPTYPE_INT64, -1);
-HANDLE_TYPE(uint32, FieldDescriptor::CPPTYPE_UINT32, -1);
-HANDLE_TYPE(uint64, FieldDescriptor::CPPTYPE_UINT64, -1);
-HANDLE_TYPE(float, FieldDescriptor::CPPTYPE_FLOAT, -1);
-HANDLE_TYPE(double, FieldDescriptor::CPPTYPE_DOUBLE, -1);
-HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1);
-
-
-#undef HANDLE_TYPE
-
-void* Reflection::MutableRawRepeatedString(Message* message,
-                                           const FieldDescriptor* field,
-                                           bool is_string) const {
-  return MutableRawRepeatedField(message, field,
-                                 FieldDescriptor::CPPTYPE_STRING,
-                                 FieldOptions::STRING, NULL);
-}
-
-
-MapIterator Reflection::MapBegin(Message* message,
-                                 const FieldDescriptor* field) const {
-  GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
-  MapIterator iter(message, field);
-  return iter;
-}
-
-MapIterator Reflection::MapEnd(Message* message,
-                               const FieldDescriptor* field) const {
-  GOOGLE_LOG(FATAL) << "Unimplemented Map Reflection API.";
-  MapIterator iter(message, field);
-  return iter;
-}
-
-// =============================================================================
 // MessageFactory
 
 MessageFactory::~MessageFactory() {}
@@ -725,19 +660,6 @@
 }
 
 
-MessageFactory* Reflection::GetMessageFactory() const {
-  GOOGLE_LOG(FATAL) << "Not implemented.";
-  return NULL;
-}
-
-void* Reflection::RepeatedFieldData(Message* message,
-                                    const FieldDescriptor* field,
-                                    FieldDescriptor::CppType cpp_type,
-                                    const Descriptor* message_type) const {
-  GOOGLE_LOG(FATAL) << "Not implemented.";
-  return NULL;
-}
-
 namespace {
 template <typename T>
 T* GetSingleton() {
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 8c9051a..b6e966d 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -84,12 +84,12 @@
 //     // Get the descriptors for the fields we're interested in and verify
 //     // their types.
 //     const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
-//     assert(text_field != NULL);
+//     assert(text_field != nullptr);
 //     assert(text_field->type() == FieldDescriptor::TYPE_STRING);
 //     assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
 //     const FieldDescriptor* numbers_field = descriptor->
 //                                            FindFieldByName("numbers");
-//     assert(numbers_field != NULL);
+//     assert(numbers_field != nullptr);
 //     assert(numbers_field->type() == FieldDescriptor::TYPE_INT32);
 //     assert(numbers_field->label() == FieldDescriptor::LABEL_REPEATED);
 //
@@ -119,6 +119,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/arena.h>
 #include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
 #include <google/protobuf/message_lite.h>
 #include <google/protobuf/port.h>
 
@@ -141,6 +142,8 @@
 class MessageFactory;
 
 // Defined in other files.
+class AssignDescriptorsHelper;
+class DynamicMessageFactory;
 class MapKey;
 class MapValueRef;
 class MapIterator;
@@ -212,11 +215,11 @@
   Message* New() const override = 0;
 
   // Construct a new instance on the arena. Ownership is passed to the caller
-  // if arena is a NULL. Default implementation allows for API compatibility
+  // if arena is a nullptr. Default implementation allows for API compatibility
   // during the Arena transition.
   Message* New(Arena* arena) const override {
     Message* message = New();
-    if (arena != NULL) {
+    if (arena != nullptr) {
       arena->Own(message);
     }
     return message;
@@ -394,23 +397,19 @@
 // double the message's memory footprint, probably worse.  Allocating the
 // objects on-demand, on the other hand, would be expensive and prone to
 // memory leaks.  So, instead we ended up with this flat interface.
-class PROTOBUF_EXPORT Reflection {
+class PROTOBUF_EXPORT Reflection final {
  public:
-  inline Reflection() {}
-  virtual ~Reflection();
-
   // Get the UnknownFieldSet for the message.  This contains fields which
   // were seen when the Message was parsed but were not recognized according
   // to the Message's definition.
-  virtual const UnknownFieldSet& GetUnknownFields(
-      const Message& message) const = 0;
+  const UnknownFieldSet& GetUnknownFields(const Message& message) const;
   // Get a mutable pointer to the UnknownFieldSet for the message.  This
   // contains fields which were seen when the Message was parsed but were not
   // recognized according to the Message's definition.
-  virtual UnknownFieldSet* MutableUnknownFields(Message* message) const = 0;
+  UnknownFieldSet* MutableUnknownFields(Message* message) const;
 
   // Estimate the amount of memory used by the message object.
-  virtual size_t SpaceUsedLong(const Message& message) const = 0;
+  size_t SpaceUsedLong(const Message& message) const;
 
   PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead")
   int SpaceUsed(const Message& message) const {
@@ -418,37 +417,26 @@
   }
 
   // Check if the given non-repeated field is set.
-  virtual bool HasField(const Message& message,
-                        const FieldDescriptor* field) const = 0;
+  bool HasField(const Message& message, const FieldDescriptor* field) const;
 
   // Get the number of elements of a repeated field.
-  virtual int FieldSize(const Message& message,
-                        const FieldDescriptor* field) const = 0;
+  int FieldSize(const Message& message, const FieldDescriptor* field) const;
 
   // Clear the value of a field, so that HasField() returns false or
   // FieldSize() returns zero.
-  virtual void ClearField(Message* message,
-                          const FieldDescriptor* field) const = 0;
+  void ClearField(Message* message, const FieldDescriptor* field) const;
 
   // Check if the oneof is set. Returns true if any field in oneof
   // is set, false otherwise.
-  // TODO(jieluo) - make it pure virtual after updating all
-  // the subclasses.
-  virtual bool HasOneof(const Message& /*message*/,
-                        const OneofDescriptor* /*oneof_descriptor*/) const {
-    return false;
-  }
+  bool HasOneof(const Message& message,
+                const OneofDescriptor* oneof_descriptor) const;
 
-  virtual void ClearOneof(Message* /*message*/,
-                          const OneofDescriptor* /*oneof_descriptor*/) const {}
+  void ClearOneof(Message* message,
+                  const OneofDescriptor* oneof_descriptor) const;
 
-  // Returns the field descriptor if the oneof is set. NULL otherwise.
-  // TODO(jieluo) - make it pure virtual.
-  virtual const FieldDescriptor* GetOneofFieldDescriptor(
-      const Message& /*message*/,
-      const OneofDescriptor* /*oneof_descriptor*/) const {
-    return NULL;
-  }
+  // Returns the field descriptor if the oneof is set. nullptr otherwise.
+  const FieldDescriptor* GetOneofFieldDescriptor(
+      const Message& message, const OneofDescriptor* oneof_descriptor) const;
 
   // Removes the last element of a repeated field.
   // We don't provide a way to remove any element other than the last
@@ -457,24 +445,21 @@
   // than the last, the best way to do it is to re-arrange the elements
   // (using Swap()) so that the one you want removed is at the end, then
   // call RemoveLast().
-  virtual void RemoveLast(Message* message,
-                          const FieldDescriptor* field) const = 0;
+  void RemoveLast(Message* message, const FieldDescriptor* field) const;
   // Removes the last element of a repeated message field, and returns the
   // pointer to the caller.  Caller takes ownership of the returned pointer.
-  virtual Message* ReleaseLast(Message* message,
-                               const FieldDescriptor* field) const = 0;
+  Message* ReleaseLast(Message* message, const FieldDescriptor* field) const;
 
   // Swap the complete contents of two messages.
-  virtual void Swap(Message* message1, Message* message2) const = 0;
+  void Swap(Message* message1, Message* message2) const;
 
   // Swap fields listed in fields vector of two messages.
-  virtual void SwapFields(
-      Message* message1, Message* message2,
-      const std::vector<const FieldDescriptor*>& fields) const = 0;
+  void SwapFields(Message* message1, Message* message2,
+                  const std::vector<const FieldDescriptor*>& fields) const;
 
   // Swap two elements of a repeated field.
-  virtual void SwapElements(Message* message, const FieldDescriptor* field,
-                            int index1, int index2) const = 0;
+  void SwapElements(Message* message, const FieldDescriptor* field, int index1,
+                    int index2) const;
 
   // List all fields of the message which are currently set, except for unknown
   // fields, but including extension known to the parser (i.e. compiled in).
@@ -484,45 +469,36 @@
   // ordered by field number.
   // Use Reflection::GetUnknownFields() or message.unknown_fields() to also get
   // access to fields/extensions unknown to the parser.
-  virtual void ListFields(
-      const Message& message,
-      std::vector<const FieldDescriptor*>* output) const = 0;
+  void ListFields(const Message& message,
+                  std::vector<const FieldDescriptor*>* output) const;
 
   // Singular field getters ------------------------------------------
   // These get the value of a non-repeated field.  They return the default
   // value for fields that aren't set.
 
-  virtual int32 GetInt32(const Message& message,
-                         const FieldDescriptor* field) const = 0;
-  virtual int64 GetInt64(const Message& message,
-                         const FieldDescriptor* field) const = 0;
-  virtual uint32 GetUInt32(const Message& message,
-                           const FieldDescriptor* field) const = 0;
-  virtual uint64 GetUInt64(const Message& message,
-                           const FieldDescriptor* field) const = 0;
-  virtual float GetFloat(const Message& message,
-                         const FieldDescriptor* field) const = 0;
-  virtual double GetDouble(const Message& message,
-                           const FieldDescriptor* field) const = 0;
-  virtual bool GetBool(const Message& message,
-                       const FieldDescriptor* field) const = 0;
-  virtual std::string GetString(const Message& message,
-                                const FieldDescriptor* field) const = 0;
-  virtual const EnumValueDescriptor* GetEnum(
-      const Message& message, const FieldDescriptor* field) const = 0;
+  int32 GetInt32(const Message& message, const FieldDescriptor* field) const;
+  int64 GetInt64(const Message& message, const FieldDescriptor* field) const;
+  uint32 GetUInt32(const Message& message, const FieldDescriptor* field) const;
+  uint64 GetUInt64(const Message& message, const FieldDescriptor* field) const;
+  float GetFloat(const Message& message, const FieldDescriptor* field) const;
+  double GetDouble(const Message& message, const FieldDescriptor* field) const;
+  bool GetBool(const Message& message, const FieldDescriptor* field) const;
+  std::string GetString(const Message& message,
+                        const FieldDescriptor* field) const;
+  const EnumValueDescriptor* GetEnum(const Message& message,
+                                     const FieldDescriptor* field) const;
 
   // GetEnumValue() returns an enum field's value as an integer rather than
   // an EnumValueDescriptor*. If the integer value does not correspond to a
   // known value descriptor, a new value descriptor is created. (Such a value
   // will only be present when the new unknown-enum-value semantics are enabled
   // for a message.)
-  virtual int GetEnumValue(const Message& message,
-                           const FieldDescriptor* field) const = 0;
+  int GetEnumValue(const Message& message, const FieldDescriptor* field) const;
 
   // See MutableMessage() for the meaning of the "factory" parameter.
-  virtual const Message& GetMessage(const Message& message,
-                                    const FieldDescriptor* field,
-                                    MessageFactory* factory = NULL) const = 0;
+  const Message& GetMessage(const Message& message,
+                            const FieldDescriptor* field,
+                            MessageFactory* factory = nullptr) const;
 
   // Get a string value without copying, if possible.
   //
@@ -539,32 +515,32 @@
   //   a newly-constructed string, though, it's just as fast and more
   //   readable to use code like:
   //     std::string str = reflection->GetString(message, field);
-  virtual const std::string& GetStringReference(const Message& message,
-                                                const FieldDescriptor* field,
-                                                std::string* scratch) const = 0;
+  const std::string& GetStringReference(const Message& message,
+                                        const FieldDescriptor* field,
+                                        std::string* scratch) const;
 
 
   // Singular field mutators -----------------------------------------
   // These mutate the value of a non-repeated field.
 
-  virtual void SetInt32(Message* message, const FieldDescriptor* field,
-                        int32 value) const = 0;
-  virtual void SetInt64(Message* message, const FieldDescriptor* field,
-                        int64 value) const = 0;
-  virtual void SetUInt32(Message* message, const FieldDescriptor* field,
-                         uint32 value) const = 0;
-  virtual void SetUInt64(Message* message, const FieldDescriptor* field,
-                         uint64 value) const = 0;
-  virtual void SetFloat(Message* message, const FieldDescriptor* field,
-                        float value) const = 0;
-  virtual void SetDouble(Message* message, const FieldDescriptor* field,
-                         double value) const = 0;
-  virtual void SetBool(Message* message, const FieldDescriptor* field,
-                       bool value) const = 0;
-  virtual void SetString(Message* message, const FieldDescriptor* field,
-                         const std::string& value) const = 0;
-  virtual void SetEnum(Message* message, const FieldDescriptor* field,
-                       const EnumValueDescriptor* value) const = 0;
+  void SetInt32(Message* message, const FieldDescriptor* field,
+                int32 value) const;
+  void SetInt64(Message* message, const FieldDescriptor* field,
+                int64 value) const;
+  void SetUInt32(Message* message, const FieldDescriptor* field,
+                 uint32 value) const;
+  void SetUInt64(Message* message, const FieldDescriptor* field,
+                 uint64 value) const;
+  void SetFloat(Message* message, const FieldDescriptor* field,
+                float value) const;
+  void SetDouble(Message* message, const FieldDescriptor* field,
+                 double value) const;
+  void SetBool(Message* message, const FieldDescriptor* field,
+               bool value) const;
+  void SetString(Message* message, const FieldDescriptor* field,
+                 const std::string& value) const;
+  void SetEnum(Message* message, const FieldDescriptor* field,
+               const EnumValueDescriptor* value) const;
   // Set an enum field's value with an integer rather than EnumValueDescriptor.
   // For proto3 this is just setting the enum field to the value specified, for
   // proto2 it's more complicated. If value is a known enum value the field is
@@ -572,8 +548,8 @@
   // set. Note this matches the behavior of parsing unknown enum values.
   // If multiple calls with unknown values happen than they are all added to the
   // unknown field set in order of the calls.
-  virtual void SetEnumValue(Message* message, const FieldDescriptor* field,
-                            int value) const = 0;
+  void SetEnumValue(Message* message, const FieldDescriptor* field,
+                    int value) const;
 
   // Get a mutable pointer to a field with a message type.  If a MessageFactory
   // is provided, it will be used to construct instances of the sub-message;
@@ -585,97 +561,86 @@
   // FieldDescriptor is for a compiled-in extension, then
   // factory->GetPrototype(field->message_type()) MUST return an instance of
   // the compiled-in class for this type, NOT DynamicMessage.
-  virtual Message* MutableMessage(Message* message,
-                                  const FieldDescriptor* field,
-                                  MessageFactory* factory = NULL) const = 0;
+  Message* MutableMessage(Message* message, const FieldDescriptor* field,
+                          MessageFactory* factory = nullptr) const;
   // Replaces the message specified by 'field' with the already-allocated object
   // sub_message, passing ownership to the message.  If the field contained a
-  // message, that message is deleted.  If sub_message is NULL, the field is
+  // message, that message is deleted.  If sub_message is nullptr, the field is
   // cleared.
-  virtual void SetAllocatedMessage(Message* message, Message* sub_message,
-                                   const FieldDescriptor* field) const = 0;
+  void SetAllocatedMessage(Message* message, Message* sub_message,
+                           const FieldDescriptor* field) const;
   // Releases the message specified by 'field' and returns the pointer,
   // ReleaseMessage() will return the message the message object if it exists.
-  // Otherwise, it may or may not return NULL.  In any case, if the return value
-  // is non-NULL, the caller takes ownership of the pointer.
+  // Otherwise, it may or may not return nullptr.  In any case, if the return
+  // value is non-null, the caller takes ownership of the pointer.
   // If the field existed (HasField() is true), then the returned pointer will
   // be the same as the pointer returned by MutableMessage().
   // This function has the same effect as ClearField().
-  virtual Message* ReleaseMessage(Message* message,
-                                  const FieldDescriptor* field,
-                                  MessageFactory* factory = NULL) const = 0;
+  Message* ReleaseMessage(Message* message, const FieldDescriptor* field,
+                          MessageFactory* factory = nullptr) const;
 
 
   // Repeated field getters ------------------------------------------
   // These get the value of one element of a repeated field.
 
-  virtual int32 GetRepeatedInt32(const Message& message,
-                                 const FieldDescriptor* field,
-                                 int index) const = 0;
-  virtual int64 GetRepeatedInt64(const Message& message,
-                                 const FieldDescriptor* field,
-                                 int index) const = 0;
-  virtual uint32 GetRepeatedUInt32(const Message& message,
-                                   const FieldDescriptor* field,
-                                   int index) const = 0;
-  virtual uint64 GetRepeatedUInt64(const Message& message,
-                                   const FieldDescriptor* field,
-                                   int index) const = 0;
-  virtual float GetRepeatedFloat(const Message& message,
-                                 const FieldDescriptor* field,
-                                 int index) const = 0;
-  virtual double GetRepeatedDouble(const Message& message,
-                                   const FieldDescriptor* field,
-                                   int index) const = 0;
-  virtual bool GetRepeatedBool(const Message& message,
-                               const FieldDescriptor* field,
-                               int index) const = 0;
-  virtual std::string GetRepeatedString(const Message& message,
-                                        const FieldDescriptor* field,
-                                        int index) const = 0;
-  virtual const EnumValueDescriptor* GetRepeatedEnum(
-      const Message& message, const FieldDescriptor* field,
-      int index) const = 0;
+  int32 GetRepeatedInt32(const Message& message, const FieldDescriptor* field,
+                         int index) const;
+  int64 GetRepeatedInt64(const Message& message, const FieldDescriptor* field,
+                         int index) const;
+  uint32 GetRepeatedUInt32(const Message& message, const FieldDescriptor* field,
+                           int index) const;
+  uint64 GetRepeatedUInt64(const Message& message, const FieldDescriptor* field,
+                           int index) const;
+  float GetRepeatedFloat(const Message& message, const FieldDescriptor* field,
+                         int index) const;
+  double GetRepeatedDouble(const Message& message, const FieldDescriptor* field,
+                           int index) const;
+  bool GetRepeatedBool(const Message& message, const FieldDescriptor* field,
+                       int index) const;
+  std::string GetRepeatedString(const Message& message,
+                                const FieldDescriptor* field, int index) const;
+  const EnumValueDescriptor* GetRepeatedEnum(const Message& message,
+                                             const FieldDescriptor* field,
+                                             int index) const;
   // GetRepeatedEnumValue() returns an enum field's value as an integer rather
   // than an EnumValueDescriptor*. If the integer value does not correspond to a
   // known value descriptor, a new value descriptor is created. (Such a value
   // will only be present when the new unknown-enum-value semantics are enabled
   // for a message.)
-  virtual int GetRepeatedEnumValue(const Message& message,
-                                   const FieldDescriptor* field,
-                                   int index) const = 0;
-  virtual const Message& GetRepeatedMessage(const Message& message,
-                                            const FieldDescriptor* field,
-                                            int index) const = 0;
+  int GetRepeatedEnumValue(const Message& message, const FieldDescriptor* field,
+                           int index) const;
+  const Message& GetRepeatedMessage(const Message& message,
+                                    const FieldDescriptor* field,
+                                    int index) const;
 
   // See GetStringReference(), above.
-  virtual const std::string& GetRepeatedStringReference(
-      const Message& message, const FieldDescriptor* field, int index,
-      std::string* scratch) const = 0;
+  const std::string& GetRepeatedStringReference(const Message& message,
+                                                const FieldDescriptor* field,
+                                                int index,
+                                                std::string* scratch) const;
 
 
   // Repeated field mutators -----------------------------------------
   // These mutate the value of one element of a repeated field.
 
-  virtual void SetRepeatedInt32(Message* message, const FieldDescriptor* field,
-                                int index, int32 value) const = 0;
-  virtual void SetRepeatedInt64(Message* message, const FieldDescriptor* field,
-                                int index, int64 value) const = 0;
-  virtual void SetRepeatedUInt32(Message* message, const FieldDescriptor* field,
-                                 int index, uint32 value) const = 0;
-  virtual void SetRepeatedUInt64(Message* message, const FieldDescriptor* field,
-                                 int index, uint64 value) const = 0;
-  virtual void SetRepeatedFloat(Message* message, const FieldDescriptor* field,
-                                int index, float value) const = 0;
-  virtual void SetRepeatedDouble(Message* message, const FieldDescriptor* field,
-                                 int index, double value) const = 0;
-  virtual void SetRepeatedBool(Message* message, const FieldDescriptor* field,
-                               int index, bool value) const = 0;
-  virtual void SetRepeatedString(Message* message, const FieldDescriptor* field,
-                                 int index, const std::string& value) const = 0;
-  virtual void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
-                               int index,
-                               const EnumValueDescriptor* value) const = 0;
+  void SetRepeatedInt32(Message* message, const FieldDescriptor* field,
+                        int index, int32 value) const;
+  void SetRepeatedInt64(Message* message, const FieldDescriptor* field,
+                        int index, int64 value) const;
+  void SetRepeatedUInt32(Message* message, const FieldDescriptor* field,
+                         int index, uint32 value) const;
+  void SetRepeatedUInt64(Message* message, const FieldDescriptor* field,
+                         int index, uint64 value) const;
+  void SetRepeatedFloat(Message* message, const FieldDescriptor* field,
+                        int index, float value) const;
+  void SetRepeatedDouble(Message* message, const FieldDescriptor* field,
+                         int index, double value) const;
+  void SetRepeatedBool(Message* message, const FieldDescriptor* field,
+                       int index, bool value) const;
+  void SetRepeatedString(Message* message, const FieldDescriptor* field,
+                         int index, const std::string& value) const;
+  void SetRepeatedEnum(Message* message, const FieldDescriptor* field,
+                       int index, const EnumValueDescriptor* value) const;
   // Set an enum field's value with an integer rather than EnumValueDescriptor.
   // For proto3 this is just setting the enum field to the value specified, for
   // proto2 it's more complicated. If value is a known enum value the field is
@@ -683,37 +648,36 @@
   // set. Note this matches the behavior of parsing unknown enum values.
   // If multiple calls with unknown values happen than they are all added to the
   // unknown field set in order of the calls.
-  virtual void SetRepeatedEnumValue(Message* message,
-                                    const FieldDescriptor* field, int index,
-                                    int value) const = 0;
+  void SetRepeatedEnumValue(Message* message, const FieldDescriptor* field,
+                            int index, int value) const;
   // Get a mutable pointer to an element of a repeated field with a message
   // type.
-  virtual Message* MutableRepeatedMessage(Message* message,
-                                          const FieldDescriptor* field,
-                                          int index) const = 0;
+  Message* MutableRepeatedMessage(Message* message,
+                                  const FieldDescriptor* field,
+                                  int index) const;
 
 
   // Repeated field adders -------------------------------------------
   // These add an element to a repeated field.
 
-  virtual void AddInt32(Message* message, const FieldDescriptor* field,
-                        int32 value) const = 0;
-  virtual void AddInt64(Message* message, const FieldDescriptor* field,
-                        int64 value) const = 0;
-  virtual void AddUInt32(Message* message, const FieldDescriptor* field,
-                         uint32 value) const = 0;
-  virtual void AddUInt64(Message* message, const FieldDescriptor* field,
-                         uint64 value) const = 0;
-  virtual void AddFloat(Message* message, const FieldDescriptor* field,
-                        float value) const = 0;
-  virtual void AddDouble(Message* message, const FieldDescriptor* field,
-                         double value) const = 0;
-  virtual void AddBool(Message* message, const FieldDescriptor* field,
-                       bool value) const = 0;
-  virtual void AddString(Message* message, const FieldDescriptor* field,
-                         const std::string& value) const = 0;
-  virtual void AddEnum(Message* message, const FieldDescriptor* field,
-                       const EnumValueDescriptor* value) const = 0;
+  void AddInt32(Message* message, const FieldDescriptor* field,
+                int32 value) const;
+  void AddInt64(Message* message, const FieldDescriptor* field,
+                int64 value) const;
+  void AddUInt32(Message* message, const FieldDescriptor* field,
+                 uint32 value) const;
+  void AddUInt64(Message* message, const FieldDescriptor* field,
+                 uint64 value) const;
+  void AddFloat(Message* message, const FieldDescriptor* field,
+                float value) const;
+  void AddDouble(Message* message, const FieldDescriptor* field,
+                 double value) const;
+  void AddBool(Message* message, const FieldDescriptor* field,
+               bool value) const;
+  void AddString(Message* message, const FieldDescriptor* field,
+                 const std::string& value) const;
+  void AddEnum(Message* message, const FieldDescriptor* field,
+               const EnumValueDescriptor* value) const;
   // Add an integer value to a repeated enum field rather than
   // EnumValueDescriptor. For proto3 this is just setting the enum field to the
   // value specified, for proto2 it's more complicated. If value is a known enum
@@ -721,19 +685,16 @@
   // to the unknown field set. Note this matches the behavior of parsing unknown
   // enum values. If multiple calls with unknown values happen than they are all
   // added to the unknown field set in order of the calls.
-  virtual void AddEnumValue(Message* message, const FieldDescriptor* field,
-                            int value) const = 0;
+  void AddEnumValue(Message* message, const FieldDescriptor* field,
+                    int value) const;
   // See MutableMessage() for comments on the "factory" parameter.
-  virtual Message* AddMessage(Message* message, const FieldDescriptor* field,
-                              MessageFactory* factory = NULL) const = 0;
+  Message* AddMessage(Message* message, const FieldDescriptor* field,
+                      MessageFactory* factory = nullptr) const;
 
   // Appends an already-allocated object 'new_entry' to the repeated field
   // specified 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;
+  void AddAllocatedMessage(Message* message, const FieldDescriptor* field,
+                           Message* new_entry) const;
 
 
   // Get a RepeatedFieldRef object that can be used to read the underlying
@@ -821,14 +782,17 @@
   // Extensions ----------------------------------------------------------------
 
   // Try to find an extension of this message type by fully-qualified field
-  // name.  Returns NULL if no extension is known for this name or number.
-  virtual const FieldDescriptor* FindKnownExtensionByName(
-      const std::string& name) const = 0;
+  // name.  Returns nullptr if no extension is known for this name or number.
+  PROTOBUF_DEPRECATED_MSG(
+      "Please use DescriptorPool::FindExtensionByPrintableName instead")
+  const FieldDescriptor* FindKnownExtensionByName(
+      const std::string& name) const;
 
   // Try to find an extension of this message type by field number.
-  // Returns NULL if no extension is known for this name or number.
-  virtual const FieldDescriptor* FindKnownExtensionByNumber(
-      int number) const = 0;
+  // Returns nullptr if no extension is known for this name or number.
+  PROTOBUF_DEPRECATED_MSG(
+      "Please use DescriptorPool::FindExtensionByNumber instead")
+  const FieldDescriptor* FindKnownExtensionByNumber(int number) const;
 
   // Feature Flags -------------------------------------------------------------
 
@@ -849,7 +813,7 @@
   //     reflection->SetEnumValue(message, field, new_value);
   //   } else {
   //     if (field_descriptor->enum_type()->
-  //             FindValueByNumber(new_value) != NULL) {
+  //             FindValueByNumber(new_value) != nullptr) {
   //       reflection->SetEnumValue(message, field, new_value);
   //     } else if (emit_unknown_enum_values) {
   //       reflection->MutableUnknownFields(message)->AddVarint(
@@ -860,7 +824,7 @@
   //       reflection->SetEnumValue(message, field, new_value);
   //     }
   //   }
-  virtual bool SupportsUnknownEnumValues() const { return false; }
+  bool SupportsUnknownEnumValues() const;
 
   // Returns the MessageFactory associated with this message.  This can be
   // useful for determining if a message is a generated message or not, for
@@ -871,60 +835,63 @@
   //   }
   // It can also be used to create more messages of this type, though
   // Message::New() is an easier way to accomplish this.
-  virtual MessageFactory* GetMessageFactory() const;
+  MessageFactory* GetMessageFactory() const;
 
-  // ---------------------------------------------------------------------------
-
- protected:
+ private:
   // Obtain a pointer to a Repeated Field Structure and do some type checking:
   //   on field->cpp_type(),
   //   on field->field_option().ctype() (if ctype >= 0)
-  //   of field->message_type() (if message_type != NULL).
+  //   of field->message_type() (if message_type != nullptr).
   // We use 2 routine rather than 4 (const vs mutable) x (scalar vs pointer).
-  virtual void* MutableRawRepeatedField(
-      Message* message, const FieldDescriptor* field, FieldDescriptor::CppType,
-      int ctype, const Descriptor* message_type) const = 0;
+  void* MutableRawRepeatedField(Message* message, const FieldDescriptor* field,
+                                FieldDescriptor::CppType, int ctype,
+                                const Descriptor* message_type) const;
 
-  // TODO(jieluo) - make it pure virtual after updating all the subclasses.
-  virtual const void* GetRawRepeatedField(
-      const Message& message, const FieldDescriptor* field,
-      FieldDescriptor::CppType cpptype, int ctype,
-      const Descriptor* message_type) const {
-    return MutableRawRepeatedField(const_cast<Message*>(&message), field,
-                                   cpptype, ctype, message_type);
-  }
+  const void* GetRawRepeatedField(const Message& message,
+                                  const FieldDescriptor* field,
+                                  FieldDescriptor::CppType cpptype, int ctype,
+                                  const Descriptor* message_type) const;
 
   // The following methods are used to implement (Mutable)RepeatedFieldRef.
   // A Ref object will store a raw pointer to the repeated field data (obtained
   // from RepeatedFieldData()) and a pointer to a Accessor (obtained from
   // RepeatedFieldAccessor) which will be used to access the raw data.
-  //
-  // TODO(xiaofeng): Make these methods pure-virtual.
 
   // Returns a raw pointer to the repeated field
   //
   // "cpp_type" and "message_type" are deduced from the type parameter T passed
   // to Get(Mutable)RepeatedFieldRef. If T is a generated message type,
   // "message_type" should be set to its descriptor. Otherwise "message_type"
-  // should be set to NULL. Implementations of this method should check whether
-  // "cpp_type"/"message_type" is consistent with the actual type of the field.
-  // We use 1 routine rather than 2 (const vs mutable) because it is protected
-  // and it doesn't change the message.
-  virtual void* RepeatedFieldData(Message* message,
-                                  const FieldDescriptor* field,
-                                  FieldDescriptor::CppType cpp_type,
-                                  const Descriptor* message_type) const;
+  // should be set to nullptr. Implementations of this method should check
+  // whether "cpp_type"/"message_type" is consistent with the actual type of the
+  // field. We use 1 routine rather than 2 (const vs mutable) because it is
+  // protected and it doesn't change the message.
+  void* RepeatedFieldData(Message* message, const FieldDescriptor* field,
+                          FieldDescriptor::CppType cpp_type,
+                          const Descriptor* message_type) const;
 
   // The returned pointer should point to a singleton instance which implements
   // the RepeatedFieldAccessor interface.
-  virtual const internal::RepeatedFieldAccessor* RepeatedFieldAccessor(
+  const internal::RepeatedFieldAccessor* RepeatedFieldAccessor(
       const FieldDescriptor* field) const;
 
- private:
+  const Descriptor* const descriptor_;
+  const internal::ReflectionSchema schema_;
+  const DescriptorPool* const descriptor_pool_;
+  MessageFactory* const message_factory_;
+
+  // Last non weak field index. This is an optimization when most weak fields
+  // are at the end of the containing message. If a message proto doesn't
+  // contain weak fields, then this field equals descriptor_->field_count().
+  int last_non_weak_field_index_;
+
   template <typename T, typename Enable>
   friend class RepeatedFieldRef;
   template <typename T, typename Enable>
   friend class MutableRepeatedFieldRef;
+  friend class ::PROTOBUF_NAMESPACE_ID::MessageLayoutInspector;
+  friend class ::PROTOBUF_NAMESPACE_ID::AssignDescriptorsHelper;
+  friend class DynamicMessageFactory;
   friend class python::MapReflectionFriend;
 #define GOOGLE_PROTOBUF_HAS_CEL_MAP_REFLECTION_FRIEND
   friend class expr::CelMapReflectionFriend;
@@ -936,6 +903,10 @@
   friend class internal::MapFieldPrinterHelper;
   friend class internal::ReflectionAccessor;
 
+  Reflection(const Descriptor* descriptor,
+             const internal::ReflectionSchema& schema,
+             const DescriptorPool* pool, MessageFactory* factory);
+
   // Special version for specialized implementations of string.  We can't
   // call MutableRawRepeatedField directly here because we don't have access to
   // FieldOptions::* which are defined in descriptor.pb.h.  Including that
@@ -946,63 +917,150 @@
                                  bool is_string) const;
 
   friend class MapReflectionTester;
-  // TODO(jieluo) - make the map APIs pure virtual after updating
-  // all the subclasses.
   // Returns true if key is in map. Returns false if key is not in map field.
-  virtual bool ContainsMapKey(const Message& /* message */,
-                              const FieldDescriptor* /* field */,
-                              const MapKey& /* key */) const {
-    return false;
-  }
+  bool ContainsMapKey(const Message& message, const FieldDescriptor* field,
+                      const MapKey& key) const;
 
   // If key is in map field: Saves the value pointer to val and returns
   // false. If key in not in map field: Insert the key into map, saves
   // value pointer to val and retuns true.
-  virtual bool InsertOrLookupMapValue(Message* /* message */,
-                                      const FieldDescriptor* /* field */,
-                                      const MapKey& /* key */,
-                                      MapValueRef* /* val */) const {
-    return false;
-  }
+  bool InsertOrLookupMapValue(Message* message, const FieldDescriptor* field,
+                              const MapKey& key, MapValueRef* val) const;
 
   // Delete and returns true if key is in the map field. Returns false
   // otherwise.
-  virtual bool DeleteMapValue(Message* /* message */,
-                              const FieldDescriptor* /* field */,
-                              const MapKey& /* key */) const {
-    return false;
-  }
+  bool DeleteMapValue(Message* message, const FieldDescriptor* field,
+                      const MapKey& key) const;
 
   // Returns a MapIterator referring to the first element in the map field.
   // If the map field is empty, this function returns the same as
   // reflection::MapEnd. Mutation to the field may invalidate the iterator.
-  virtual MapIterator MapBegin(Message* message,
-                               const FieldDescriptor* field) const;
+  MapIterator MapBegin(Message* message, const FieldDescriptor* field) const;
 
   // Returns a MapIterator referring to the theoretical element that would
   // follow the last element in the map field. It does not point to any
   // real element. Mutation to the field may invalidate the iterator.
-  virtual MapIterator MapEnd(Message* message,
-                             const FieldDescriptor* field) const;
+  MapIterator MapEnd(Message* message, const FieldDescriptor* field) const;
 
   // Get the number of <key, value> pair of a map field. The result may be
   // different from FieldSize which can have duplicate keys.
-  virtual int MapSize(const Message& /* message */,
-                      const FieldDescriptor* /* field */) const {
-    return 0;
-  }
+  int MapSize(const Message& message, const FieldDescriptor* field) const;
 
   // Help method for MapIterator.
   friend class MapIterator;
-  virtual internal::MapFieldBase* MutableMapData(
-      Message* /* message */, const FieldDescriptor* /* field */) const {
-    return NULL;
-  }
+  internal::MapFieldBase* MutableMapData(Message* message,
+                                         const FieldDescriptor* field) const;
 
-  virtual const internal::MapFieldBase* GetMapData(
-      const Message& /* message */, const FieldDescriptor* /* field */) const {
-    return NULL;
-  }
+  const internal::MapFieldBase* GetMapData(const Message& message,
+                                           const FieldDescriptor* field) const;
+
+  template <class T>
+  const T& GetRawNonOneof(const Message& message,
+                          const FieldDescriptor* field) const;
+  template <class T>
+  T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const;
+
+  template <typename Type>
+  const Type& GetRaw(const Message& message,
+                     const FieldDescriptor* field) const;
+  template <typename Type>
+  inline Type* MutableRaw(Message* message, const FieldDescriptor* field) const;
+  template <typename Type>
+  inline const Type& DefaultRaw(const FieldDescriptor* field) const;
+
+  inline const uint32* GetHasBits(const Message& message) const;
+  inline uint32* MutableHasBits(Message* message) const;
+  inline uint32 GetOneofCase(const Message& message,
+                             const OneofDescriptor* oneof_descriptor) const;
+  inline uint32* MutableOneofCase(
+      Message* message, const OneofDescriptor* oneof_descriptor) const;
+  inline const internal::ExtensionSet& GetExtensionSet(
+      const Message& message) const;
+  inline internal::ExtensionSet* MutableExtensionSet(Message* message) const;
+  inline Arena* GetArena(Message* message) const;
+
+  inline const internal::InternalMetadataWithArena&
+  GetInternalMetadataWithArena(const Message& message) const;
+
+  inline internal::InternalMetadataWithArena* MutableInternalMetadataWithArena(
+      Message* message) const;
+
+  inline bool IsInlined(const FieldDescriptor* field) const;
+
+  inline bool HasBit(const Message& message,
+                     const FieldDescriptor* field) const;
+  inline void SetBit(Message* message, const FieldDescriptor* field) const;
+  inline void ClearBit(Message* message, const FieldDescriptor* field) const;
+  inline void SwapBit(Message* message1, Message* message2,
+                      const FieldDescriptor* field) const;
+
+  // This function only swaps the field. Should swap corresponding has_bit
+  // before or after using this function.
+  void SwapField(Message* message1, Message* message2,
+                 const FieldDescriptor* field) const;
+
+  void SwapOneofField(Message* message1, Message* message2,
+                      const OneofDescriptor* oneof_descriptor) const;
+
+  inline bool HasOneofField(const Message& message,
+                            const FieldDescriptor* field) const;
+  inline void SetOneofCase(Message* message,
+                           const FieldDescriptor* field) const;
+  inline void ClearOneofField(Message* message,
+                              const FieldDescriptor* field) const;
+
+  template <typename Type>
+  inline const Type& GetField(const Message& message,
+                              const FieldDescriptor* field) const;
+  template <typename Type>
+  inline void SetField(Message* message, const FieldDescriptor* field,
+                       const Type& value) const;
+  template <typename Type>
+  inline Type* MutableField(Message* message,
+                            const FieldDescriptor* field) const;
+  template <typename Type>
+  inline const Type& GetRepeatedField(const Message& message,
+                                      const FieldDescriptor* field,
+                                      int index) const;
+  template <typename Type>
+  inline const Type& GetRepeatedPtrField(const Message& message,
+                                         const FieldDescriptor* field,
+                                         int index) const;
+  template <typename Type>
+  inline void SetRepeatedField(Message* message, const FieldDescriptor* field,
+                               int index, Type value) const;
+  template <typename Type>
+  inline Type* MutableRepeatedField(Message* message,
+                                    const FieldDescriptor* field,
+                                    int index) const;
+  template <typename Type>
+  inline void AddField(Message* message, const FieldDescriptor* field,
+                       const Type& value) const;
+  template <typename Type>
+  inline Type* AddField(Message* message, const FieldDescriptor* field) const;
+
+  int GetExtensionNumberOrDie(const Descriptor* type) const;
+
+  // Internal versions of EnumValue API perform no checking. Called after checks
+  // by public methods.
+  void SetEnumValueInternal(Message* message, const FieldDescriptor* field,
+                            int value) const;
+  void SetRepeatedEnumValueInternal(Message* message,
+                                    const FieldDescriptor* field, int index,
+                                    int value) const;
+  void AddEnumValueInternal(Message* message, const FieldDescriptor* field,
+                            int value) const;
+
+  Message* UnsafeArenaReleaseMessage(Message* message,
+                                     const FieldDescriptor* field,
+                                     MessageFactory* factory = nullptr) const;
+
+  void UnsafeArenaSetAllocatedMessage(Message* message, Message* sub_message,
+                                      const FieldDescriptor* field) const;
+
+  friend inline  // inline so nobody can call this function.
+      void
+      RegisterAllTypesInternal(const Metadata* file_level_metadata, int size);
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
 };
@@ -1027,7 +1085,7 @@
   // outlive the MessageFactory.
   //
   // Some implementations do not support all types.  GetPrototype() will
-  // return NULL if the descriptor passed in is not supported.
+  // return nullptr if the descriptor passed in is not supported.
   //
   // This method may or may not be thread-safe depending on the implementation.
   // Each implementation should document its own degree thread-safety.
@@ -1039,7 +1097,7 @@
   //     FooMessage::descriptor()) == FooMessage::default_instance()
   // This factory supports all types which are found in
   // DescriptorPool::generated_pool().  If given a descriptor from any other
-  // pool, GetPrototype() will return NULL.  (You can also check if a
+  // pool, GetPrototype() will return nullptr.  (You can also check if a
   // descriptor is for a generated message by checking if
   // descriptor->file()->pool() == DescriptorPool::generated_pool().)
   //
@@ -1091,8 +1149,8 @@
 
 #undef DECLARE_GET_REPEATED_FIELD
 
-// Tries to downcast this message to a generated message type.  Returns NULL if
-// this class is not an instance of T.  This works even if RTTI is disabled.
+// Tries to downcast this message to a generated message type.  Returns nullptr
+// if this class is not an instance of T.  This works even if RTTI is disabled.
 //
 // This also has the effect of creating a strong reference to T that will
 // prevent the linker from stripping it out at link time.  This can be important
@@ -1180,14 +1238,14 @@
 inline const RepeatedPtrField<Message>& Reflection::GetRepeatedPtrField(
     const Message& message, const FieldDescriptor* field) const {
   return *static_cast<const RepeatedPtrField<Message>*>(GetRawRepeatedField(
-      message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, NULL));
+      message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, nullptr));
 }
 
 template <>
 inline RepeatedPtrField<Message>* Reflection::MutableRepeatedPtrField(
     Message* message, const FieldDescriptor* field) const {
   return static_cast<RepeatedPtrField<Message>*>(MutableRawRepeatedField(
-      message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, NULL));
+      message, field, FieldDescriptor::CPPTYPE_MESSAGE, -1, nullptr));
 }
 
 template <typename PB>
diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc
index 0cd46d4..e92171f 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -46,7 +46,11 @@
 #include <fstream>
 #include <sstream>
 
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/test_util2.h>
+#include <google/protobuf/io/io_win32.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>
@@ -54,14 +58,9 @@
 #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/logging.h>
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
-#include <google/protobuf/io/io_win32.h>
 
 namespace google {
 namespace protobuf {
@@ -630,6 +629,5 @@
 }
 
 
-
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 4c631f0..e4a7b62 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -83,6 +83,7 @@
 namespace protobuf {
 
 class Message;
+class Reflection;
 
 namespace internal {
 
@@ -147,6 +148,11 @@
   // Appends a new element and return a pointer to it.
   // The new element is uninitialized if |Element| is a POD type.
   Element* Add();
+  // Append elements in the range [begin, end) after reserving
+  // the appropriate number of elements.
+  template <typename Iter>
+  void Add(Iter begin, Iter end);
+
   // Remove the last element in the array.
   void RemoveLast();
 
@@ -630,7 +636,7 @@
   // The reflection implementation needs to call protected methods directly,
   // reinterpreting pointers as being to Message instead of a specific Message
   // subclass.
-  friend class GeneratedMessageReflection;
+  friend class ::PROTOBUF_NAMESPACE_ID::Reflection;
 
   // ExtensionSet stores repeated message extensions as
   // RepeatedPtrField<MessageLite>, but non-lite ExtensionSets need to implement
@@ -1071,26 +1077,7 @@
 template <typename Iter>
 RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
     : current_size_(0), total_size_(0), ptr_(NULL) {
-  int reserve = internal::CalculateReserve(begin, end);
-  if (reserve != -1) {
-    if (reserve == 0) {
-      return;
-    }
-
-    Reserve(reserve);
-    // TODO(ckennelly):  The compiler loses track of the buffer freshly
-    // allocated by Reserve() by the time we call elements, so it cannot
-    // guarantee that elements does not alias [begin(), end()).
-    //
-    // If restrict is available, annotating the pointer obtained from elements()
-    // causes this to lower to memcpy instead of memmove.
-    std::copy(begin, end, elements());
-    current_size_ = reserve;
-  } else {
-    for (; begin != end; ++begin) {
-      Add(*begin);
-    }
-  }
+  Add(begin, end);
 }
 
 template <typename Element>
@@ -1235,6 +1222,31 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedField<Element>::Add(Iter begin, Iter end) {
+  int reserve = internal::CalculateReserve(begin, end);
+  if (reserve != -1) {
+    if (reserve == 0) {
+      return;
+    }
+
+    Reserve(reserve + size());
+    // TODO(ckennelly):  The compiler loses track of the buffer freshly
+    // allocated by Reserve() by the time we call elements, so it cannot
+    // guarantee that elements does not alias [begin(), end()).
+    //
+    // If restrict is available, annotating the pointer obtained from elements()
+    // causes this to lower to memcpy instead of memmove.
+    std::copy(begin, end, elements() + size());
+    current_size_ = reserve + size();
+  } else {
+    for (; begin != end; ++begin) {
+      Add(*begin);
+    }
+  }
+}
+
+template <typename Element>
 inline void RepeatedField<Element>::RemoveLast() {
   GOOGLE_DCHECK_GT(current_size_, 0);
   current_size_--;
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index f88801e..3964d44 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -35,14 +35,15 @@
 // TODO(kenton):  Improve this unittest to bring it up to the standards of
 //   other proto2 unittests.
 
+#include <google/protobuf/repeated_field.h>
+
 #include <algorithm>
 #include <limits>
 #include <list>
+#include <sstream>
 #include <type_traits>
 #include <vector>
 
-#include <google/protobuf/repeated_field.h>
-
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/unittest.pb.h>
@@ -343,6 +344,71 @@
   EXPECT_EQ(8, me.Get(2));
 }
 
+// Add contents of empty container to an empty field.
+TEST(RepeatedField, AddRange1) {
+  RepeatedField<int> me;
+  std::vector<int> values;
+
+  me.Add(values.begin(), values.end());
+  ASSERT_EQ(me.size(), 0);
+}
+
+// Add contents of container with one thing to an empty field.
+TEST(RepeatedField, AddRange2) {
+  RepeatedField<int> me;
+  std::vector<int> values;
+  values.push_back(-1);
+
+  me.Add(values.begin(), values.end());
+  ASSERT_EQ(me.size(), 1);
+  ASSERT_EQ(me.Get(0), values[0]);
+}
+
+// Add contents of container with more than one thing to an empty field.
+TEST(RepeatedField, AddRange3) {
+  RepeatedField<int> me;
+  std::vector<int> values;
+  values.push_back(0);
+  values.push_back(1);
+
+  me.Add(values.begin(), values.end());
+  ASSERT_EQ(me.size(), 2);
+  ASSERT_EQ(me.Get(0), values[0]);
+  ASSERT_EQ(me.Get(1), values[1]);
+}
+
+// Add contents of container with more than one thing to a non-empty field.
+TEST(RepeatedField, AddRange4) {
+  RepeatedField<int> me;
+  me.Add(0);
+  me.Add(1);
+
+  std::vector<int> values;
+  values.push_back(2);
+  values.push_back(3);
+
+  me.Add(values.begin(), values.end());
+  ASSERT_EQ(me.size(), 4);
+  ASSERT_EQ(me.Get(0), 0);
+  ASSERT_EQ(me.Get(1), 1);
+  ASSERT_EQ(me.Get(2), values[0]);
+  ASSERT_EQ(me.Get(3), values[1]);
+}
+
+// Add contents of a stringstream in order to test code paths where there is
+// an input iterator.
+TEST(RepeatedField, AddRange5) {
+  RepeatedField<int> me;
+
+  std::stringstream ss;
+  ss << 1 << ' ' << 2;
+
+  me.Add(std::istream_iterator<int>(ss), std::istream_iterator<int>());
+  ASSERT_EQ(me.size(), 2);
+  ASSERT_EQ(me.Get(0), 1);
+  ASSERT_EQ(me.Get(1), 2);
+}
+
 TEST(RepeatedField, CopyConstruct) {
   RepeatedField<int> source;
   source.Add(1);
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 50a5c0e..98add69 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -55,7 +55,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 2cad5a9..c4ff59b 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -124,7 +124,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 8f0a4c5..562f452 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -153,7 +153,7 @@
 }
 
 void CheckFieldIndex(const FieldDescriptor* field, int index) {
-  if (field == NULL) {
+  if (field == nullptr) {
     return;
   }
 
@@ -175,7 +175,7 @@
 
   const std::vector<TextFormat::ParseLocation>* locations =
       FindOrNull(locations_, field);
-  if (locations == NULL || index >= locations->size()) {
+  if (locations == nullptr || index >= locations->size()) {
     return TextFormat::ParseLocation();
   }
 
@@ -191,8 +191,8 @@
 
   const std::vector<TextFormat::ParseInfoTree*>* trees =
       FindOrNull(nested_, field);
-  if (trees == NULL || index >= trees->size()) {
-    return NULL;
+  if (trees == nullptr || index >= trees->size()) {
+    return nullptr;
   }
 
   return (*trees)[index];
@@ -200,10 +200,12 @@
 
 namespace {
 // These functions implement the behavior of the "default" TextFormat::Finder,
-// they are defined as standalone to be called when finder_ is NULL.
+// they are defined as standalone to be called when finder_ is nullptr.
 const FieldDescriptor* DefaultFinderFindExtension(Message* message,
                                                   const std::string& name) {
-  return message->GetReflection()->FindKnownExtensionByName(name);
+  const Descriptor* descriptor = message->GetDescriptor();
+  return descriptor->file()->pool()->FindExtensionByPrintableName(descriptor,
+                                                                  name);
 }
 
 const Descriptor* DefaultFinderFindAnyType(const Message& message,
@@ -211,7 +213,7 @@
                                            const std::string& name) {
   if (prefix != internal::kTypeGoogleApisComPrefix &&
       prefix != internal::kTypeGoogleProdComPrefix) {
-    return NULL;
+    return nullptr;
   }
   return message.GetDescriptor()->file()->pool()->FindMessageTypeByName(name);
 }
@@ -312,7 +314,7 @@
 
   void ReportError(int line, int col, const std::string& message) {
     had_errors_ = true;
-    if (error_collector_ == NULL) {
+    if (error_collector_ == nullptr) {
       if (line >= 0) {
         GOOGLE_LOG(ERROR) << "Error parsing text-format "
                    << root_message_type_->full_name() << ": " << (line + 1)
@@ -327,7 +329,7 @@
   }
 
   void ReportWarning(int line, int col, const std::string& message) {
-    if (error_collector_ == NULL) {
+    if (error_collector_ == nullptr) {
       if (line >= 0) {
         GOOGLE_LOG(WARNING) << "Warning parsing text-format "
                      << root_message_type_->full_name() << ": " << (line + 1)
@@ -391,7 +393,7 @@
 
     std::string field_name;
     bool reserved_field = false;
-    const FieldDescriptor* field = NULL;
+    const FieldDescriptor* field = nullptr;
     int start_line = tokenizer_.current().line;
     int start_column = tokenizer_.current().column;
 
@@ -408,7 +410,7 @@
       const Descriptor* value_descriptor =
           finder_ ? finder_->FindAnyType(*message, prefix, full_type_name)
                   : DefaultFinderFindAnyType(*message, prefix, full_type_name);
-      if (value_descriptor == NULL) {
+      if (value_descriptor == nullptr) {
         ReportError("Could not find type \"" + prefix + full_type_name +
                     "\" stored in google.protobuf.Any.");
         return false;
@@ -437,7 +439,7 @@
       field = finder_ ? finder_->FindExtension(message, field_name)
                       : DefaultFinderFindExtension(message, field_name);
 
-      if (field == NULL) {
+      if (field == nullptr) {
         if (!allow_unknown_field_ && !allow_unknown_extension_) {
           ReportError("Extension \"" + field_name +
                       "\" is not defined or "
@@ -457,7 +459,8 @@
       if (allow_field_number_ &&
           safe_strto32(field_name, &field_number)) {
         if (descriptor->IsExtensionNumber(field_number)) {
-          field = reflection->FindKnownExtensionByNumber(field_number);
+          field = descriptor->file()->pool()->FindExtensionByNumber(
+              descriptor, field_number);
         } else if (descriptor->IsReservedNumber(field_number)) {
           reserved_field = true;
         } else {
@@ -468,33 +471,34 @@
         // Group names are expected to be capitalized as they appear in the
         // .proto file, which actually matches their type names, not their
         // field names.
-        if (field == NULL) {
+        if (field == nullptr) {
           std::string lower_field_name = field_name;
           LowerString(&lower_field_name);
           field = descriptor->FindFieldByName(lower_field_name);
           // If the case-insensitive match worked but the field is NOT a group,
-          if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) {
-            field = NULL;
+          if (field != nullptr &&
+              field->type() != FieldDescriptor::TYPE_GROUP) {
+            field = nullptr;
           }
         }
         // Again, special-case group names as described above.
-        if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP &&
+        if (field != nullptr && field->type() == FieldDescriptor::TYPE_GROUP &&
             field->message_type()->name() != field_name) {
-          field = NULL;
+          field = nullptr;
         }
 
-        if (field == NULL && allow_case_insensitive_field_) {
+        if (field == nullptr && allow_case_insensitive_field_) {
           std::string lower_field_name = field_name;
           LowerString(&lower_field_name);
           field = descriptor->FindFieldByLowercaseName(lower_field_name);
         }
 
-        if (field == NULL) {
+        if (field == nullptr) {
           reserved_field = descriptor->IsReservedName(field_name);
         }
       }
 
-      if (field == NULL && !reserved_field) {
+      if (field == nullptr && !reserved_field) {
         if (!allow_unknown_field_) {
           ReportError("Message type \"" + descriptor->full_name() +
                       "\" has no field named \"" + field_name + "\".");
@@ -507,7 +511,7 @@
     }
 
     // Skips unknown or reserved fields.
-    if (field == NULL) {
+    if (field == nullptr) {
       GOOGLE_CHECK(allow_unknown_field_ || allow_unknown_extension_ || reserved_field);
 
       // Try to guess the type of this field.
@@ -533,7 +537,7 @@
       // Fail if the field is a member of a oneof and another member has already
       // been specified.
       const OneofDescriptor* oneof = field->containing_oneof();
-      if (oneof != NULL && reflection->HasOneof(*message, oneof)) {
+      if (oneof != nullptr && reflection->HasOneof(*message, oneof)) {
         const FieldDescriptor* other_field =
             reflection->GetOneofFieldDescriptor(*message, oneof);
         ReportError("Field \"" + field_name +
@@ -601,7 +605,7 @@
 
     // If a parse info tree exists, add the location for the parsed
     // field.
-    if (parse_info_tree_ != NULL) {
+    if (parse_info_tree_ != nullptr) {
       RecordLocation(parse_info_tree_, field,
                      ParseLocation(start_line, start_column));
     }
@@ -643,10 +647,10 @@
       ReportError("Message is too deep");
       return false;
     }
-    // If the parse information tree is not NULL, create a nested one
+    // If the parse information tree is not nullptr, create a nested one
     // for the nested message.
     ParseInfoTree* parent = parse_info_tree_;
-    if (parent != NULL) {
+    if (parent != nullptr) {
       parse_info_tree_ = CreateNested(parent, field);
     }
 
@@ -768,7 +772,7 @@
         std::string value;
         int64 int_value = kint64max;
         const EnumDescriptor* enum_type = field->enum_type();
-        const EnumValueDescriptor* enum_value = NULL;
+        const EnumValueDescriptor* enum_value = nullptr;
 
         if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
           DO(ConsumeIdentifier(&value));
@@ -786,7 +790,7 @@
           return false;
         }
 
-        if (enum_value == NULL) {
+        if (enum_value == nullptr) {
           if (int_value != kint64max &&
               reflection->SupportsUnknownEnumValues()) {
             SET_FIELD(EnumValue, int_value);
@@ -1111,7 +1115,7 @@
                        std::string* serialized_value) {
     DynamicMessageFactory factory;
     const Message* value_prototype = factory.GetPrototype(value_descriptor);
-    if (value_prototype == NULL) {
+    if (value_prototype == nullptr) {
       return false;
     }
     std::unique_ptr<Message> value(value_prototype->New());
@@ -1209,7 +1213,7 @@
   explicit TextGenerator(io::ZeroCopyOutputStream* output,
                          int initial_indent_level)
       : output_(output),
-        buffer_(NULL),
+        buffer_(nullptr),
         buffer_size_(0),
         at_start_of_line_(true),
         failed_(false),
@@ -1293,7 +1297,7 @@
         data += buffer_size_;
         size -= buffer_size_;
       }
-      void* void_buffer = NULL;
+      void* void_buffer = nullptr;
       failed_ = !output_->Next(&void_buffer, &buffer_size_);
       if (failed_) return;
       buffer_ = reinterpret_cast<char*>(void_buffer);
@@ -1364,9 +1368,9 @@
 // ===========================================================================
 
 TextFormat::Parser::Parser()
-    : error_collector_(NULL),
-      finder_(NULL),
-      parse_info_tree_(NULL),
+    : error_collector_(nullptr),
+      finder_(nullptr),
+      parse_info_tree_(nullptr),
       allow_partial_(false),
       allow_case_insensitive_field_(false),
       allow_unknown_field_(false),
@@ -1647,15 +1651,7 @@
     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->PrintString(field->PrintableNameForExtension());
     generator->PrintLiteral("]");
   } else if (field->type() == FieldDescriptor::TYPE_GROUP) {
     // Groups must be serialized with their original capitalization.
@@ -1795,7 +1791,7 @@
       print_message_fields_in_index_order_(false),
       expand_any_(false),
       truncate_string_field_longer_than_(0LL),
-      finder_(NULL) {
+      finder_(nullptr) {
   SetUseUtf8StringEscaping(false);
 }
 
@@ -1821,7 +1817,7 @@
 
 bool TextFormat::Printer::RegisterFieldValuePrinter(
     const FieldDescriptor* field, const FieldValuePrinter* printer) {
-  if (field == NULL || printer == NULL) {
+  if (field == nullptr || printer == nullptr) {
     return false;
   }
   FieldValuePrinterWrapper* const wrapper =
@@ -1837,7 +1833,7 @@
 
 bool TextFormat::Printer::RegisterFieldValuePrinter(
     const FieldDescriptor* field, const FastFieldValuePrinter* printer) {
-  return field != NULL && printer != NULL &&
+  return field != nullptr && printer != nullptr &&
          custom_printers_.insert(std::make_pair(field, printer)).second;
 }
 
@@ -1850,7 +1846,7 @@
 
 bool TextFormat::Printer::PrintToString(const Message& message,
                                         std::string* output) const {
-  GOOGLE_DCHECK(output) << "output specified is NULL";
+  GOOGLE_DCHECK(output) << "output specified is nullptr";
 
   output->clear();
   io::StringOutputStream output_stream(output);
@@ -1860,7 +1856,7 @@
 
 bool TextFormat::Printer::PrintUnknownFieldsToString(
     const UnknownFieldSet& unknown_fields, std::string* output) const {
-  GOOGLE_DCHECK(output) << "output specified is NULL";
+  GOOGLE_DCHECK(output) << "output specified is nullptr";
 
   output->clear();
   io::StringOutputStream output_stream(output);
@@ -1931,7 +1927,7 @@
   const Descriptor* value_descriptor =
       finder_ ? finder_->FindAnyType(message, url_prefix, full_type_name)
               : DefaultFinderFindAnyType(message, url_prefix, full_type_name);
-  if (value_descriptor == NULL) {
+  if (value_descriptor == nullptr) {
     GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found";
     return false;
   }
@@ -2004,7 +2000,7 @@
                                                   const FieldDescriptor* field,
                                                   int index,
                                                   std::string* output) const {
-  GOOGLE_DCHECK(output) << "output specified is NULL";
+  GOOGLE_DCHECK(output) << "output specified is nullptr";
 
   output->clear();
   io::StringOutputStream output_stream(output);
@@ -2353,7 +2349,7 @@
               : reflection->GetEnumValue(message, field);
       const EnumValueDescriptor* enum_desc =
           field->enum_type()->FindValueByNumber(enum_value);
-      if (enum_desc != NULL) {
+      if (enum_desc != nullptr) {
         printer->PrintEnum(enum_value, enum_desc->name(), generator);
       } else {
         // Ordinarily, enum_desc should not be null, because proto2 has the
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 11e4c10..56801c3 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -82,7 +82,7 @@
 
 class TextFormatTest : public testing::Test {
  public:
-  static void SetUpTestCase() {
+  static void SetUpTestSuite() {
     GOOGLE_CHECK_OK(File::GetContents(
         TestUtil::GetTestDataPath(
             "net/proto2/internal/"
@@ -105,7 +105,7 @@
 
 class TextFormatExtensionsTest : public testing::Test {
  public:
-  static void SetUpTestCase() {
+  static void SetUpTestSuite() {
     GOOGLE_CHECK_OK(File::GetContents(
         TestUtil::GetTestDataPath("net/proto2/internal/testdata/"
                                   "text_format_unittest_extensions_data.txt"),
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 65849a3..3d56e3a 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -56,7 +56,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index 66f7d07..0631fdd 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -194,7 +194,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_Option_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] PROTOBUF_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"
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index f0f8d02..b2e1866 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -40,10 +40,6 @@
 
 #include <google/protobuf/port_def.inc>
 
-namespace util {
-class Status;
-}  // namespace util
-
 namespace google {
 namespace protobuf {
 namespace util {
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index c6edc82..3e2b346 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -1411,7 +1411,7 @@
     if (change_type == ADDITION || change_type == DELETION ||
         change_type == MODIFICATION) {
       if (reporter_ == NULL) {
-        // We found a difference and we have no reproter.
+        // We found a difference and we have no reporter.
         return false;
       }
       is_different = true;
diff --git a/src/google/protobuf/util/time_util.h b/src/google/protobuf/util/time_util.h
index 756e23b..8906beb 100644
--- a/src/google/protobuf/util/time_util.h
+++ b/src/google/protobuf/util/time_util.h
@@ -37,7 +37,14 @@
 #include <ostream>
 #include <string>
 #ifdef _MSC_VER
+#ifdef _XBOX_ONE
+struct timeval {
+	long    tv_sec;         /* seconds */
+	long    tv_usec;        /* and microseconds */
+};
+#else
 #include <winsock2.h>
+#endif // _XBOX_ONE
 #else
 #include <sys/time.h>
 #endif
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index af6a90c..e8100d9 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -263,7 +263,7 @@
   reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&PROTOBUF_NAMESPACE_ID::_BytesValue_default_instance_),
 };
 
-const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] =
+const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] PROTOBUF_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"