Merge tag 'refs/tags/sync-piper' into sync-stage
diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec
index 4b54404..fbd37b2 100644
--- a/Protobuf-C++.podspec
+++ b/Protobuf-C++.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name     = 'Protobuf-C++'
-  s.version  = '3.15.2'
+  s.version  = '3.15.6'
   s.summary  = 'Protocol Buffers v3 runtime library for C++.'
   s.homepage = 'https://github.com/google/protobuf'
   s.license  = '3-Clause BSD License'
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 52661f5..5c3b6e4 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -45,6 +45,7 @@
 option(protobuf_BUILD_EXAMPLES "Build examples" OFF)
 option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON)
 option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF)
+option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF)
 if (BUILD_SHARED_LIBS)
   set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
 else (BUILD_SHARED_LIBS)
@@ -117,6 +118,10 @@
 
 add_definitions(-DGOOGLE_PROTOBUF_CMAKE_BUILD)
 
+if (protobuf_DISABLE_RTTI)
+  add_definitions(-DGOOGLE_PROTOBUF_NO_RTTI=1)
+endif()
+
 find_package(Threads REQUIRED)
 if (CMAKE_USE_PTHREADS_INIT)
   add_definitions(-DHAVE_PTHREAD)
diff --git a/cmake/install.cmake b/cmake/install.cmake
index 9dd6e77..ef5bb13 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -30,7 +30,9 @@
 
 if (protobuf_BUILD_PROTOC_BINARIES)
   install(TARGETS protoc EXPORT protobuf-targets
-    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc)
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
+    COMPONENT protoc)
   if (UNIX AND NOT APPLE)
     set_property(TARGET protoc
       PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}")
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index fac5efe..9197625 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -15,7 +15,7 @@
   if(COMMAND target_sources)
     list(APPEND _singleargs TARGET)
   endif()
-  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS)
+  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS)
 
   cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
 
@@ -130,9 +130,9 @@
     add_custom_command(
       OUTPUT ${_generated_srcs}
       COMMAND  protobuf::protoc
-      ARGS --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
+      ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_dll_export_decl}${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
       DEPENDS ${_abs_file} protobuf::protoc
-      COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}"
+      COMMENT "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}. Custom options: ${protobuf_generate_PROTOC_OPTIONS}"
       VERBATIM )
   endforeach()
 
diff --git a/configure.ac b/configure.ac
index 232dd87..0e84cc0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
 # In the SVN trunk, the version should always be the next anticipated release
 # version with the "-pre" suffix.  (We used to use "-SNAPSHOT" but this pushed
 # the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[3.15.2],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.15.6],[protobuf@googlegroups.com],[protobuf])
 
 AM_MAINTAINER_MODE([enable])
 
@@ -223,6 +223,19 @@
 esac
 AM_CONDITIONAL([OBJC_CONFORMANCE_TEST], [test $OBJC_CONFORMANCE_TEST = 1])
 
+AC_MSG_CHECKING(whether -llog is needed)
+ANDROID_TEST=no
+case "$target_os" in
+  *android*)
+    ANDROID_TEST=yes
+    ;;
+esac
+AC_MSG_RESULT($ANDROID_TEST)
+if test "x$ANDROID_TEST" = xyes; then
+  LIBLOG_LIBS="-llog"
+fi
+AC_SUBST([LIBLOG_LIBS])
+
 # HACK:  Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS,
 #   since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock
 #   too.
diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc
index d27612b..5782789 100644
--- a/conformance/conformance_cpp.cc
+++ b/conformance/conformance_cpp.cc
@@ -134,7 +134,7 @@
                              &proto_binary, options);
       if (!status.ok()) {
         response->set_parse_error(string("Parse error: ") +
-                                  std::string(status.error_message()));
+                                  std::string(status.message()));
         return;
       }
 
@@ -189,7 +189,7 @@
       if (!status.ok()) {
         response->set_serialize_error(
             string("Failed to serialize JSON output: ") +
-            std::string(status.error_message()));
+            std::string(status.message()));
         return;
       }
       break;
diff --git a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
index b47eeef..4b43033 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -78,7 +78,7 @@
     /* This write can be racy if the same exception is stored and then thrown by multiple custom
      * InputStreams on different threads. But since it only ever moves from false->true, there's no
      * problem. A thread checking this condition after catching this exception from a delegate
-     * stram of CodedInputStream is guaranteed to always observe true, because a write on the same
+     * stream of CodedInputStream is guaranteed to always observe true, because a write on the same
      * thread set the value when the exception left the delegate. A thread checking the same
      * condition with an exception created by CodedInputStream is guaranteed to always see false,
      * because the exception has not been exposed to any code that could publish it to other threads
diff --git a/js/package.json b/js/package.json
index 4610c05..5971046 100644
--- a/js/package.json
+++ b/js/package.json
@@ -1,6 +1,6 @@
 {
   "name": "google-protobuf",
-  "version": "3.15.2",
+  "version": "3.15.6",
   "description": "Protocol Buffers for JavaScript",
   "main": "google-protobuf.js",
   "files": [
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index 4807f97..b356d67 100644
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -30,4 +30,4 @@
 
 # Copyright 2007 Google Inc. All Rights Reserved.
 
-__version__ = '3.15.2'
+__version__ = '3.15.6'
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index feff228..77122a2 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -841,8 +841,7 @@
     m1.MergeFromString(m2.SerializeToString())
     self.assertEqual(1, m1.optional_nested_message.bb)
 
-  @unittest.skipIf(six.PY2, 'memoryview objects are not supported on py2')
-  def testMergeFromStringUsingMemoryViewWorksInPy3(self, message_module):
+  def testMergeFromStringUsingMemoryView(self, message_module):
     m2 = message_module.TestAllTypes()
     m2.optional_string = 'scalar string'
     m2.repeated_string.append('repeated string')
@@ -864,12 +863,6 @@
     self.assertIsInstance(m1.optional_string, six.text_type)
     self.assertIsInstance(m1.repeated_string[0], six.text_type)
 
-  @unittest.skipIf(six.PY3, 'memoryview is supported by py3')
-  def testMergeFromStringUsingMemoryViewIsPy2Error(self, message_module):
-    memview = memoryview(b'')
-    with self.assertRaises(TypeError):
-      message_module.TestAllTypes.FromString(memview)
-
   def testMergeFromEmpty(self, message_module):
     m1 = message_module.TestAllTypes()
     # Cpp extension will lazily create a sub message which is immutable.
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
index d1f4dcd..99d2f07 100644
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -1133,12 +1133,6 @@
 def _AddMergeFromStringMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
   def MergeFromString(self, serialized):
-    if isinstance(serialized, memoryview) and six.PY2:
-      raise TypeError(
-          'memoryview not supported in Python 2 with the pure Python proto '
-          'implementation: this is to maintain compatibility with the C++ '
-          'implementation')
-
     serialized = memoryview(serialized)
     length = len(serialized)
     try:
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 42d99e8..3218d7d 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -251,7 +251,7 @@
     return NULL;
   }
   ScopedPyObjectPtr value(
-      PyEval_CallObject(message_class->AsPyObject(), NULL));
+      PyObject_Call(message_class->AsPyObject(), NULL, NULL));
   Py_DECREF(message_class);
   if (value == NULL) {
     return NULL;
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index 6f1464e..a24d45d 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -176,9 +176,9 @@
 // The public DescriptorPool constructor.
 static PyObject* New(PyTypeObject* type,
                      PyObject* args, PyObject* kwargs) {
-  static char* kwlist[] = {"descriptor_db", 0};
+  static const char* kwlist[] = {"descriptor_db", 0};
   PyObject* py_database = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &py_database)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", const_cast<char**>(kwlist), &py_database)) {
     return NULL;
   }
   DescriptorDatabase* database = NULL;
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index 2573327..346a5f5 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -463,10 +463,10 @@
 
 static PyObject* ScalarMapGet(PyObject* self, PyObject* args,
                               PyObject* kwargs) {
-  static char* kwlist[] = {"key", "default", nullptr};
+  static const char* kwlist[] = {"key", "default", nullptr};
   PyObject* key;
   PyObject* default_value = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", const_cast<char**>(kwlist), &key,
                                    &default_value)) {
     return NULL;
   }
@@ -758,10 +758,10 @@
 }
 
 PyObject* MessageMapGet(PyObject* self, PyObject* args, PyObject* kwargs) {
-  static char* kwlist[] = {"key", "default", nullptr};
+  static const char* kwlist[] = {"key", "default", nullptr};
   PyObject* key;
   PyObject* default_value = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", kwlist, &key,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", const_cast<char**>(kwlist), &key,
                                    &default_value)) {
     return NULL;
   }
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 33034bf..0921af7 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -197,12 +197,12 @@
 }
 
 static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
-  static char *kwlist[] = {"name", "bases", "dict", 0};
+  static const char *kwlist[] = {"name", "bases", "dict", 0};
   PyObject *bases, *dict;
   const char* name;
 
   // Check arguments: (name, bases, dict)
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", kwlist,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO!O!:type", const_cast<char**>(kwlist),
                                    &name,
                                    &PyTuple_Type, &bases,
                                    &PyDict_Type, &dict)) {
@@ -547,7 +547,7 @@
 
 // Format an error message for unexpected types.
 // Always return with an exception set.
-void FormatTypeError(PyObject* arg, char* expected_types) {
+void FormatTypeError(PyObject* arg, const char* expected_types) {
   // This function is often called with an exception set.
   // Clear it to call PyObject_Repr() in good conditions.
   PyErr_Clear();
@@ -1680,9 +1680,9 @@
     CMessage* self, PyObject* args, PyObject* kwargs,
     bool require_initialized) {
   // Parse the "deterministic" kwarg; defaults to False.
-  static char* kwlist[] = { "deterministic", 0 };
+  static const char* kwlist[] = { "deterministic", 0 };
   PyObject* deterministic_obj = Py_None;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", const_cast<char**>(kwlist),
                                    &deterministic_obj)) {
     return NULL;
   }
@@ -1928,9 +1928,8 @@
 }
 
 static PyObject* MergeFromString(CMessage* self, PyObject* arg) {
-  const void* data;
-  Py_ssize_t data_length;
-  if (PyObject_AsReadBuffer(arg, &data, &data_length) < 0) {
+  Py_buffer data;
+  if (PyObject_GetBuffer(arg, &data, PyBUF_SIMPLE) < 0) {
     return NULL;
   }
 
@@ -1943,7 +1942,8 @@
   const char* ptr;
   internal::ParseContext ctx(
       depth, false, &ptr,
-      StringPiece(static_cast<const char*>(data), data_length));
+      StringPiece(static_cast<const char*>(data.buf), data.len));
+  PyBuffer_Release(&data);
   ctx.data().pool = factory->pool->pool;
   ctx.data().factory = factory->message_factory;
 
@@ -1969,9 +1969,9 @@
     // TODO(jieluo): Raise error and return NULL instead.
     // b/27494216
     PyErr_Warn(nullptr, "Unexpected end-group tag: Not all data was converted");
-    return PyInt_FromLong(data_length - ctx.BytesUntilLimit(ptr));
+    return PyInt_FromLong(data.len - ctx.BytesUntilLimit(ptr));
   }
-  return PyInt_FromLong(data_length);
+  return PyInt_FromLong(data.len);
 }
 
 static PyObject* ParseFromString(CMessage* self, PyObject* arg) {
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index 6a175dd..29af255 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -330,7 +330,7 @@
 
 #define FULL_MODULE_NAME "google.protobuf.pyext._message"
 
-void FormatTypeError(PyObject* arg, char* expected_types);
+void FormatTypeError(PyObject* arg, const char* expected_types);
 template<class T>
 bool CheckAndGetInteger(PyObject* arg, T* value);
 bool CheckAndGetDouble(PyObject* arg, double* value);
diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc
index 5fed13b..5a10c3d 100644
--- a/python/google/protobuf/pyext/message_factory.cc
+++ b/python/google/protobuf/pyext/message_factory.cc
@@ -77,9 +77,9 @@
 }
 
 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
-  static char* kwlist[] = {"pool", 0};
+  static const char* kwlist[] = {"pool", 0};
   PyObject* pool = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", kwlist, &pool)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", const_cast<char**>(kwlist), &pool)) {
     return NULL;
   }
   ScopedPyObjectPtr owned_pool;
diff --git a/src/Makefile.am b/src/Makefile.am
index 3658477..e67f37f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,7 +18,7 @@
 PTHREAD_DEF =
 endif
 
-PROTOBUF_VERSION = 26:2:0
+PROTOBUF_VERSION = 26:6:0
 
 if GCC
 # Turn on all warnings except for sign comparison (we ignore sign comparison
@@ -30,7 +30,7 @@
 
 AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG)
 
-AM_LDFLAGS = $(PTHREAD_CFLAGS)
+AM_LDFLAGS = $(PTHREAD_CFLAGS) ${LIBLOG_LIBS}
 
 # If I say "dist_include_DATA", automake complains that $(includedir) is not
 # a "legitimate" directory for DATA.  Screw you, automake.
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index de52306..c405423 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -69,7 +69,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
  public:
   inline Any() : Any(nullptr) {}
-  virtual ~Any();
+  ~Any() override;
   explicit constexpr Any(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Any(const Any& from);
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index ee9f92b..5317281 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -79,7 +79,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ {
  public:
   inline Api() : Api(nullptr) {}
-  virtual ~Api();
+  ~Api() override;
   explicit constexpr Api(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Api(const Api& from);
@@ -322,7 +322,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ {
  public:
   inline Method() : Method(nullptr) {}
-  virtual ~Method();
+  ~Method() override;
   explicit constexpr Method(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Method(const Method& from);
@@ -543,7 +543,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ {
  public:
   inline Mixin() : Mixin(nullptr) {}
-  virtual ~Mixin();
+  ~Mixin() override;
   explicit constexpr Mixin(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Mixin(const Mixin& from);
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index ff1fdd0..de8dc44 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -290,7 +290,7 @@
       public DescriptorPool::ErrorCollector {
  public:
   ErrorPrinter(ErrorFormat format, DiskSourceTree* tree = NULL)
-      : format_(format), tree_(tree), found_errors_(false) {}
+      : format_(format), tree_(tree), found_errors_(false), found_warnings_(false) {}
   ~ErrorPrinter() {}
 
   // implements MultiFileErrorCollector ------------------------------
@@ -302,6 +302,7 @@
 
   void AddWarning(const std::string& filename, int line, int column,
                   const std::string& message) {
+    found_warnings_ = true;
     AddErrorOrWarning(filename, line, column, message, "warning", std::clog);
   }
 
@@ -329,6 +330,8 @@
 
   bool FoundErrors() const { return found_errors_; }
 
+  bool FoundWarnings() const { return found_warnings_; }
+
  private:
   void AddErrorOrWarning(const std::string& filename, int line, int column,
                          const std::string& message, const std::string& type,
@@ -367,6 +370,7 @@
   const ErrorFormat format_;
   DiskSourceTree* tree_;
   bool found_errors_;
+  bool found_warnings_;
 };
 
 // -------------------------------------------------------------------
@@ -584,10 +588,12 @@
 
   if (stream.GetErrno() != 0) {
     std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+    return false;
   }
 
   if (!stream.Close()) {
     std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl;
+    return false;
   }
 
   return true;
@@ -1119,7 +1125,8 @@
     }
   }
 
-  if (error_collector->FoundErrors()) {
+  if (error_collector->FoundErrors() ||
+      (fatal_warnings_ && error_collector->FoundWarnings())) {
     return 1;
   }
 
@@ -1632,7 +1639,8 @@
       *name == "--version" || *name == "--decode_raw" ||
       *name == "--print_free_field_numbers" ||
       *name == "--experimental_allow_proto3_optional" ||
-      *name == "--deterministic_output") {
+      *name == "--deterministic_output" ||
+      *name == "--fatal_warnings") {
     // HACK:  These are the only flags that don't take a value.
     //   They probably should not be hard-coded like this but for now it's
     //   not worth doing better.
@@ -1885,6 +1893,12 @@
       return PARSE_ARGUMENT_FAIL;
     }
 
+  } else if (name == "--fatal_warnings") {
+    if (fatal_warnings_) {
+      std::cerr << name << " may only be passed once." << std::endl;
+      return PARSE_ARGUMENT_FAIL;
+    }
+    fatal_warnings_ = true;
   } else if (name == "--plugin") {
     if (plugin_prefix_.empty()) {
       std::cerr << "This compiler does not support plugins." << std::endl;
@@ -2044,6 +2058,10 @@
   --error_format=FORMAT       Set the format in which to print errors.
                               FORMAT may be 'gcc' (the default) or 'msvs'
                               (Microsoft Visual Studio format).
+  --fatal_warnings            Make warnings be fatal (similar to -Werr in
+                              gcc). This flag will make protoc return
+                              with a non-zero exit code if any warnings
+                              are generated.
   --print_free_field_numbers  Print the free field numbers of the messages
                               defined in the given proto files. Groups share
                               the same field number space with the parent
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 73551f0..27178b1 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -393,6 +393,9 @@
 
   ErrorFormat error_format_ = ERROR_FORMAT_GCC;
 
+  // True if we should treat warnings as errors that fail the compilation.
+  bool fatal_warnings_ = false;
+
   std::vector<std::pair<std::string, std::string> >
       proto_path_;                        // Search path for proto files.
   std::vector<std::string> input_files_;  // Names of the input proto files.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 92f3d08..5fc111e 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -159,6 +159,11 @@
   void ExpectCapturedStdoutSubstringWithZeroReturnCode(
       const std::string& expected_substring);
 
+  // Checks that Run() returned zero and the stderr contains the given
+  // substring.
+  void ExpectCapturedStderrSubstringWithZeroReturnCode(
+      const std::string& expected_substring);
+
 #if defined(_WIN32) && !defined(__CYGWIN__)
   // Returns true if ExpectErrorSubstring(expected_substring) would pass, but
   // does not fail otherwise.
@@ -428,8 +433,8 @@
 
 void CommandLineInterfaceTest::ExpectWarningSubstring(
     const std::string& expected_substring) {
-  EXPECT_EQ(0, return_code_);
   EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
+  EXPECT_EQ(0, return_code_);
 }
 
 #if defined(_WIN32) && !defined(__CYGWIN__)
@@ -517,6 +522,13 @@
                       captured_stdout_);
 }
 
+void CommandLineInterfaceTest::ExpectCapturedStderrSubstringWithZeroReturnCode(
+    const std::string& expected_substring) {
+  EXPECT_EQ(0, return_code_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring,
+                      error_text_);
+}
+
 void CommandLineInterfaceTest::ExpectFileContent(const std::string& filename,
                                                  const std::string& content) {
   std::string path = temp_directory_ + "/" + filename;
@@ -2305,7 +2317,7 @@
 }
 
 TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
-  // Test --error_format=msvs
+  // Test invalid --error_format
 
   CreateTempFile("foo.proto",
                  "syntax = \"proto2\";\n"
@@ -2317,6 +2329,26 @@
   ExpectErrorText("Unknown error format: invalid\n");
 }
 
+TEST_F(CommandLineInterfaceTest, Warnings) {
+  // Test --fatal_warnings.
+
+  CreateTempFile("foo.proto",
+    "syntax = \"proto2\";\n"
+    "import \"bar.proto\";\n");
+  CreateTempFile("bar.proto",
+    "syntax = \"proto2\";\n");
+
+  Run("protocol_compiler --test_out=$tmpdir "
+    "--proto_path=$tmpdir foo.proto");
+  ExpectCapturedStderrSubstringWithZeroReturnCode(
+    "foo.proto:2:1: warning: Import bar.proto is unused.");
+
+  Run("protocol_compiler --test_out=$tmpdir --fatal_warnings "
+    "--proto_path=$tmpdir foo.proto");
+  ExpectErrorSubstring(
+    "foo.proto:2:1: warning: Import bar.proto is unused.");
+}
+
 // -------------------------------------------------------------------
 // Flag parsing tests
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index d47a0d6..9a0c7ab 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -856,8 +856,8 @@
       "};\n"
       // This function exists to be marked as weak.
       // It can significantly speed up compilation by breaking up LLVM's SCC in
-      // the .pb.cc tranlation units. Large translation units see a reduction of
-      // more than 35% of walltime for optimized builds.
+      // the .pb.cc translation units. Large translation units see a reduction
+      // of more than 35% of walltime for optimized builds.
       // Without the weak attribute all the messages in the file, including all
       // the vtables and everything they use become part of the same SCC through
       // a cycle like:
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 2e2c2d4..e91a497 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -1093,7 +1093,7 @@
 
   format(
       "inline $classname$() : $classname$(nullptr) {}\n"
-      "virtual ~$classname$();\n"
+      "~$classname$() override;\n"
       "explicit constexpr "
       "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
       "\n"
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 78a6d93..7c10ee6 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -115,7 +115,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ {
  public:
   inline Version() : Version(nullptr) {}
-  virtual ~Version();
+  ~Version() override;
   explicit constexpr Version(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Version(const Version& from);
@@ -308,7 +308,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ {
  public:
   inline CodeGeneratorRequest() : CodeGeneratorRequest(nullptr) {}
-  virtual ~CodeGeneratorRequest();
+  ~CodeGeneratorRequest() override;
   explicit constexpr CodeGeneratorRequest(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorRequest(const CodeGeneratorRequest& from);
@@ -522,7 +522,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ {
  public:
   inline CodeGeneratorResponse_File() : CodeGeneratorResponse_File(nullptr) {}
-  virtual ~CodeGeneratorResponse_File();
+  ~CodeGeneratorResponse_File() override;
   explicit constexpr CodeGeneratorResponse_File(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
@@ -730,7 +730,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ {
  public:
   inline CodeGeneratorResponse() : CodeGeneratorResponse(nullptr) {}
-  virtual ~CodeGeneratorResponse();
+  ~CodeGeneratorResponse() override;
   explicit constexpr CodeGeneratorResponse(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   CodeGeneratorResponse(const CodeGeneratorResponse& from);
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 4553dd5..b43cb49 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -333,7 +333,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ {
  public:
   inline FileDescriptorSet() : FileDescriptorSet(nullptr) {}
-  virtual ~FileDescriptorSet();
+  ~FileDescriptorSet() override;
   explicit constexpr FileDescriptorSet(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorSet(const FileDescriptorSet& from);
@@ -480,7 +480,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ {
  public:
   inline FileDescriptorProto() : FileDescriptorProto(nullptr) {}
-  virtual ~FileDescriptorProto();
+  ~FileDescriptorProto() override;
   explicit constexpr FileDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileDescriptorProto(const FileDescriptorProto& from);
@@ -862,7 +862,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ {
  public:
   inline DescriptorProto_ExtensionRange() : DescriptorProto_ExtensionRange(nullptr) {}
-  virtual ~DescriptorProto_ExtensionRange();
+  ~DescriptorProto_ExtensionRange() override;
   explicit constexpr DescriptorProto_ExtensionRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ExtensionRange(const DescriptorProto_ExtensionRange& from);
@@ -1040,7 +1040,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ {
  public:
   inline DescriptorProto_ReservedRange() : DescriptorProto_ReservedRange(nullptr) {}
-  virtual ~DescriptorProto_ReservedRange();
+  ~DescriptorProto_ReservedRange() override;
   explicit constexpr DescriptorProto_ReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from);
@@ -1198,7 +1198,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ {
  public:
   inline DescriptorProto() : DescriptorProto(nullptr) {}
-  virtual ~DescriptorProto();
+  ~DescriptorProto() override;
   explicit constexpr DescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DescriptorProto(const DescriptorProto& from);
@@ -1535,7 +1535,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ {
  public:
   inline ExtensionRangeOptions() : ExtensionRangeOptions(nullptr) {}
-  virtual ~ExtensionRangeOptions();
+  ~ExtensionRangeOptions() override;
   explicit constexpr ExtensionRangeOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ExtensionRangeOptions(const ExtensionRangeOptions& from);
@@ -1685,7 +1685,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ {
  public:
   inline FieldDescriptorProto() : FieldDescriptorProto(nullptr) {}
-  virtual ~FieldDescriptorProto();
+  ~FieldDescriptorProto() override;
   explicit constexpr FieldDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldDescriptorProto(const FieldDescriptorProto& from);
@@ -2102,7 +2102,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ {
  public:
   inline OneofDescriptorProto() : OneofDescriptorProto(nullptr) {}
-  virtual ~OneofDescriptorProto();
+  ~OneofDescriptorProto() override;
   explicit constexpr OneofDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofDescriptorProto(const OneofDescriptorProto& from);
@@ -2270,7 +2270,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto.EnumReservedRange) */ {
  public:
   inline EnumDescriptorProto_EnumReservedRange() : EnumDescriptorProto_EnumReservedRange(nullptr) {}
-  virtual ~EnumDescriptorProto_EnumReservedRange();
+  ~EnumDescriptorProto_EnumReservedRange() override;
   explicit constexpr EnumDescriptorProto_EnumReservedRange(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from);
@@ -2428,7 +2428,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ {
  public:
   inline EnumDescriptorProto() : EnumDescriptorProto(nullptr) {}
-  virtual ~EnumDescriptorProto();
+  ~EnumDescriptorProto() override;
   explicit constexpr EnumDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumDescriptorProto(const EnumDescriptorProto& from);
@@ -2664,7 +2664,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ {
  public:
   inline EnumValueDescriptorProto() : EnumValueDescriptorProto(nullptr) {}
-  virtual ~EnumValueDescriptorProto();
+  ~EnumValueDescriptorProto() override;
   explicit constexpr EnumValueDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueDescriptorProto(const EnumValueDescriptorProto& from);
@@ -2847,7 +2847,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ {
  public:
   inline ServiceDescriptorProto() : ServiceDescriptorProto(nullptr) {}
-  virtual ~ServiceDescriptorProto();
+  ~ServiceDescriptorProto() override;
   explicit constexpr ServiceDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceDescriptorProto(const ServiceDescriptorProto& from);
@@ -3035,7 +3035,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ {
  public:
   inline MethodDescriptorProto() : MethodDescriptorProto(nullptr) {}
-  virtual ~MethodDescriptorProto();
+  ~MethodDescriptorProto() override;
   explicit constexpr MethodDescriptorProto(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodDescriptorProto(const MethodDescriptorProto& from);
@@ -3273,7 +3273,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ {
  public:
   inline FileOptions() : FileOptions(nullptr) {}
-  virtual ~FileOptions();
+  ~FileOptions() override;
   explicit constexpr FileOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FileOptions(const FileOptions& from);
@@ -3806,7 +3806,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ {
  public:
   inline MessageOptions() : MessageOptions(nullptr) {}
-  virtual ~MessageOptions();
+  ~MessageOptions() override;
   explicit constexpr MessageOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MessageOptions(const MessageOptions& from);
@@ -4017,7 +4017,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ {
  public:
   inline FieldOptions() : FieldOptions(nullptr) {}
-  virtual ~FieldOptions();
+  ~FieldOptions() override;
   explicit constexpr FieldOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldOptions(const FieldOptions& from);
@@ -4322,7 +4322,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ {
  public:
   inline OneofOptions() : OneofOptions(nullptr) {}
-  virtual ~OneofOptions();
+  ~OneofOptions() override;
   explicit constexpr OneofOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   OneofOptions(const OneofOptions& from);
@@ -4472,7 +4472,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ {
  public:
   inline EnumOptions() : EnumOptions(nullptr) {}
-  virtual ~EnumOptions();
+  ~EnumOptions() override;
   explicit constexpr EnumOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumOptions(const EnumOptions& from);
@@ -4653,7 +4653,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ {
  public:
   inline EnumValueOptions() : EnumValueOptions(nullptr) {}
-  virtual ~EnumValueOptions();
+  ~EnumValueOptions() override;
   explicit constexpr EnumValueOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValueOptions(const EnumValueOptions& from);
@@ -4819,7 +4819,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ {
  public:
   inline ServiceOptions() : ServiceOptions(nullptr) {}
-  virtual ~ServiceOptions();
+  ~ServiceOptions() override;
   explicit constexpr ServiceOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ServiceOptions(const ServiceOptions& from);
@@ -4985,7 +4985,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ {
  public:
   inline MethodOptions() : MethodOptions(nullptr) {}
-  virtual ~MethodOptions();
+  ~MethodOptions() override;
   explicit constexpr MethodOptions(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   MethodOptions(const MethodOptions& from);
@@ -5198,7 +5198,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ {
  public:
   inline UninterpretedOption_NamePart() : UninterpretedOption_NamePart(nullptr) {}
-  virtual ~UninterpretedOption_NamePart();
+  ~UninterpretedOption_NamePart() override;
   explicit constexpr UninterpretedOption_NamePart(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption_NamePart(const UninterpretedOption_NamePart& from);
@@ -5364,7 +5364,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ {
  public:
   inline UninterpretedOption() : UninterpretedOption(nullptr) {}
-  virtual ~UninterpretedOption();
+  ~UninterpretedOption() override;
   explicit constexpr UninterpretedOption(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UninterpretedOption(const UninterpretedOption& from);
@@ -5619,7 +5619,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ {
  public:
   inline SourceCodeInfo_Location() : SourceCodeInfo_Location(nullptr) {}
-  virtual ~SourceCodeInfo_Location();
+  ~SourceCodeInfo_Location() override;
   explicit constexpr SourceCodeInfo_Location(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo_Location(const SourceCodeInfo_Location& from);
@@ -5863,7 +5863,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ {
  public:
   inline SourceCodeInfo() : SourceCodeInfo(nullptr) {}
-  virtual ~SourceCodeInfo();
+  ~SourceCodeInfo() override;
   explicit constexpr SourceCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceCodeInfo(const SourceCodeInfo& from);
@@ -6012,7 +6012,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ {
  public:
   inline GeneratedCodeInfo_Annotation() : GeneratedCodeInfo_Annotation(nullptr) {}
-  virtual ~GeneratedCodeInfo_Annotation();
+  ~GeneratedCodeInfo_Annotation() override;
   explicit constexpr GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo_Annotation(const GeneratedCodeInfo_Annotation& from);
@@ -6215,7 +6215,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ {
  public:
   inline GeneratedCodeInfo() : GeneratedCodeInfo(nullptr) {}
-  virtual ~GeneratedCodeInfo();
+  ~GeneratedCodeInfo() override;
   explicit constexpr GeneratedCodeInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   GeneratedCodeInfo(const GeneratedCodeInfo& from);
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index 0017f95..b59edab 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -69,7 +69,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ {
  public:
   inline Duration() : Duration(nullptr) {}
-  virtual ~Duration();
+  ~Duration() override;
   explicit constexpr Duration(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Duration(const Duration& from);
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index 2ee8544..9ad0eea 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -69,7 +69,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ {
  public:
   inline Empty() : Empty(nullptr) {}
-  virtual ~Empty();
+  ~Empty() override;
   explicit constexpr Empty(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Empty(const Empty& from);
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index f0cef60..e9a5126 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -69,7 +69,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
  public:
   inline FieldMask() : FieldMask(nullptr) {}
-  virtual ~FieldMask();
+  ~FieldMask() override;
   explicit constexpr FieldMask(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FieldMask(const FieldMask& from);
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index 5ce3ce0..b6c11d2 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -133,6 +133,8 @@
 #else
 #ifdef __APPLE__
 #include <machine/endian.h>  // __BYTE_ORDER
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>  // __BYTE_ORDER
 #else
 #include <endian.h>  // __BYTE_ORDER
 #endif
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
index b8e1644..00b07d9 100644
--- a/src/google/protobuf/parse_context.h
+++ b/src/google/protobuf/parse_context.h
@@ -348,7 +348,6 @@
     if (ptr - buffer_end_ > limit_) return nullptr;
     while (limit_ > kSlopBytes) {
       size_t chunk_size = buffer_end_ + kSlopBytes - ptr;
-      GOOGLE_DCHECK_GE(chunk_size, static_cast<size_t>(0));
       append(ptr, chunk_size);
       ptr = Next();
       if (ptr == nullptr) return limit_end_;
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index 6a9403f..8a98474 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -337,7 +337,7 @@
 
 // Shared google3/opensource definitions. //////////////////////////////////////
 
-#define PROTOBUF_VERSION 3015002
+#define PROTOBUF_VERSION 3015006
 #define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC 3015000
 #define PROTOBUF_MIN_PROTOC_VERSION 3015000
 #define PROTOBUF_VERSION_SUFFIX ""
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 95967cf..a763ff9 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -69,7 +69,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ {
  public:
   inline SourceContext() : SourceContext(nullptr) {}
-  virtual ~SourceContext();
+  ~SourceContext() override;
   explicit constexpr SourceContext(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   SourceContext(const SourceContext& from);
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 7f1b540..b7e6629 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -134,7 +134,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ {
  public:
   inline Struct() : Struct(nullptr) {}
-  virtual ~Struct();
+  ~Struct() override;
   explicit constexpr Struct(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Struct(const Struct& from);
@@ -278,7 +278,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ {
  public:
   inline Value() : Value(nullptr) {}
-  virtual ~Value();
+  ~Value() override;
   explicit constexpr Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Value(const Value& from);
@@ -530,7 +530,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ {
  public:
   inline ListValue() : ListValue(nullptr) {}
-  virtual ~ListValue();
+  ~ListValue() override;
   explicit constexpr ListValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   ListValue(const ListValue& from);
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 8c8fb87..2dfcc9b 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -82,7 +82,7 @@
 
 // The current version, represented as a single integer to make comparison
 // easier:  major * 10^6 + minor * 10^3 + micro
-#define GOOGLE_PROTOBUF_VERSION 3015002
+#define GOOGLE_PROTOBUF_VERSION 3015006
 
 // A suffix string for alpha, beta or rc releases. Empty for stable releases.
 #define GOOGLE_PROTOBUF_VERSION_SUFFIX ""
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
index f37048d..110ccdc 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -33,6 +33,7 @@
 
 #include <google/protobuf/stubs/macros.h>
 #include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/status.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -64,9 +65,6 @@
 };
 
 class StringPiece;
-namespace util {
-class Status;
-}
 class uint128;
 namespace internal {
 
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index b7aab40..0f3b5aa 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -59,6 +59,8 @@
 #else
 #ifdef __APPLE__
 #include <machine/endian.h>  // __BYTE_ORDER
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>  // __BYTE_ORDER
 #else
 #include <endian.h>  // __BYTE_ORDER
 #endif
diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
index 03b37c3..e071852 100644
--- a/src/google/protobuf/stubs/status.cc
+++ b/src/google/protobuf/stubs/status.cc
@@ -37,42 +37,44 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace error {
-inline std::string CodeEnumToString(error::Code code) {
+namespace status_internal {
+namespace {
+
+inline std::string StatusCodeToString(StatusCode code) {
   switch (code) {
-    case OK:
+    case StatusCode::kOk:
       return "OK";
-    case CANCELLED:
+    case StatusCode::kCancelled:
       return "CANCELLED";
-    case UNKNOWN:
+    case StatusCode::kUnknown:
       return "UNKNOWN";
-    case INVALID_ARGUMENT:
+    case StatusCode::kInvalidArgument:
       return "INVALID_ARGUMENT";
-    case DEADLINE_EXCEEDED:
+    case StatusCode::kDeadlineExceeded:
       return "DEADLINE_EXCEEDED";
-    case NOT_FOUND:
+    case StatusCode::kNotFound:
       return "NOT_FOUND";
-    case ALREADY_EXISTS:
+    case StatusCode::kAlreadyExists:
       return "ALREADY_EXISTS";
-    case PERMISSION_DENIED:
+    case StatusCode::kPermissionDenied:
       return "PERMISSION_DENIED";
-    case UNAUTHENTICATED:
+    case StatusCode::kUnauthenticated:
       return "UNAUTHENTICATED";
-    case RESOURCE_EXHAUSTED:
+    case StatusCode::kResourceExhausted:
       return "RESOURCE_EXHAUSTED";
-    case FAILED_PRECONDITION:
+    case StatusCode::kFailedPrecondition:
       return "FAILED_PRECONDITION";
-    case ABORTED:
+    case StatusCode::kAborted:
       return "ABORTED";
-    case OUT_OF_RANGE:
+    case StatusCode::kOutOfRange:
       return "OUT_OF_RANGE";
-    case UNIMPLEMENTED:
+    case StatusCode::kUnimplemented:
       return "UNIMPLEMENTED";
-    case INTERNAL:
+    case StatusCode::kInternal:
       return "INTERNAL";
-    case UNAVAILABLE:
+    case StatusCode::kUnavailable:
       return "UNAVAILABLE";
-    case DATA_LOSS:
+    case StatusCode::kDataLoss:
       return "DATA_LOSS";
   }
 
@@ -80,18 +82,15 @@
   // above switch.
   return "UNKNOWN";
 }
-}  // namespace error.
 
-const Status Status::OK = Status();
-const Status Status::CANCELLED = Status(error::CANCELLED, "");
-const Status Status::UNKNOWN = Status(error::UNKNOWN, "");
+}  // namespace
 
-Status::Status() : error_code_(error::OK) {
+Status::Status() : error_code_(StatusCode::kOk) {
 }
 
-Status::Status(error::Code error_code, StringPiece error_message)
+Status::Status(StatusCode error_code, StringPiece error_message)
     : error_code_(error_code) {
-  if (error_code != error::OK) {
+  if (error_code != StatusCode::kOk) {
     error_message_ = error_message.ToString();
   }
 }
@@ -112,23 +111,156 @@
 }
 
 std::string Status::ToString() const {
-  if (error_code_ == error::OK) {
+  if (error_code_ == StatusCode::kOk) {
     return "OK";
   } else {
     if (error_message_.empty()) {
-      return error::CodeEnumToString(error_code_);
+      return StatusCodeToString(error_code_);
     } else {
-      return error::CodeEnumToString(error_code_) + ":" +
+      return StatusCodeToString(error_code_) + ":" +
           error_message_;
     }
   }
 }
 
+Status OkStatus() {
+  return Status();
+}
+
 std::ostream& operator<<(std::ostream& os, const Status& x) {
   os << x.ToString();
   return os;
 }
 
+bool IsAborted(const Status& status) {
+  return status.code() == StatusCode::kAborted;
+}
+
+bool IsAlreadyExists(const Status& status) {
+  return status.code() == StatusCode::kAlreadyExists;
+}
+
+bool IsCancelled(const Status& status) {
+  return status.code() == StatusCode::kCancelled;
+}
+
+bool IsDataLoss(const Status& status) {
+  return status.code() == StatusCode::kDataLoss;
+}
+
+bool IsDeadlineExceeded(const Status& status) {
+  return status.code() == StatusCode::kDeadlineExceeded;
+}
+
+bool IsFailedPrecondition(const Status& status) {
+  return status.code() == StatusCode::kFailedPrecondition;
+}
+
+bool IsInternal(const Status& status) {
+  return status.code() == StatusCode::kInternal;
+}
+
+bool IsInvalidArgument(const Status& status) {
+  return status.code() == StatusCode::kInvalidArgument;
+}
+
+bool IsNotFound(const Status& status) {
+  return status.code() == StatusCode::kNotFound;
+}
+
+bool IsOutOfRange(const Status& status) {
+  return status.code() == StatusCode::kOutOfRange;
+}
+
+bool IsPermissionDenied(const Status& status) {
+  return status.code() == StatusCode::kPermissionDenied;
+}
+
+bool IsResourceExhausted(const Status& status) {
+  return status.code() == StatusCode::kResourceExhausted;
+}
+
+bool IsUnauthenticated(const Status& status) {
+  return status.code() == StatusCode::kUnauthenticated;
+}
+
+bool IsUnavailable(const Status& status) {
+  return status.code() == StatusCode::kUnavailable;
+}
+
+bool IsUnimplemented(const Status& status) {
+  return status.code() == StatusCode::kUnimplemented;
+}
+
+bool IsUnknown(const Status& status) {
+  return status.code() == StatusCode::kUnknown;
+}
+
+Status AbortedError(StringPiece message) {
+  return Status(StatusCode::kAborted, message);
+}
+
+Status AlreadyExistsError(StringPiece message) {
+  return Status(StatusCode::kAlreadyExists, message);
+}
+
+Status CancelledError(StringPiece message) {
+  return Status(StatusCode::kCancelled, message);
+}
+
+Status DataLossError(StringPiece message) {
+  return Status(StatusCode::kDataLoss, message);
+}
+
+Status DeadlineExceededError(StringPiece message) {
+  return Status(StatusCode::kDeadlineExceeded, message);
+}
+
+Status FailedPreconditionError(StringPiece message) {
+  return Status(StatusCode::kFailedPrecondition, message);
+}
+
+Status InternalError(StringPiece message) {
+  return Status(StatusCode::kInternal, message);
+}
+
+Status InvalidArgumentError(StringPiece message) {
+  return Status(StatusCode::kInvalidArgument, message);
+}
+
+Status NotFoundError(StringPiece message) {
+  return Status(StatusCode::kNotFound, message);
+}
+
+Status OutOfRangeError(StringPiece message) {
+  return Status(StatusCode::kOutOfRange, message);
+}
+
+Status PermissionDeniedError(StringPiece message) {
+  return Status(StatusCode::kPermissionDenied, message);
+}
+
+Status ResourceExhaustedError(StringPiece message) {
+  return Status(StatusCode::kResourceExhausted, message);
+}
+
+Status UnauthenticatedError(StringPiece message) {
+  return Status(StatusCode::kUnauthenticated, message);
+}
+
+Status UnavailableError(StringPiece message) {
+  return Status(StatusCode::kUnavailable, message);
+}
+
+Status UnimplementedError(StringPiece message) {
+  return Status(StatusCode::kUnimplemented, message);
+}
+
+Status UnknownError(StringPiece message) {
+  return Status(StatusCode::kUnknown, message);
+}
+
+}  // namespace status_internal
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h
index bededad..187bc27 100644
--- a/src/google/protobuf/stubs/status.h
+++ b/src/google/protobuf/stubs/status.h
@@ -27,13 +27,12 @@
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 #ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_
 #define GOOGLE_PROTOBUF_STUBS_STATUS_H_
 
-#include <iosfwd>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/stringpiece.h>
 
 #include <google/protobuf/port_def.inc>
@@ -41,28 +40,28 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace error {
+namespace status_internal {
+
 // These values must match error codes defined in google/rpc/code.proto.
-enum Code {
-  OK = 0,
-  CANCELLED = 1,
-  UNKNOWN = 2,
-  INVALID_ARGUMENT = 3,
-  DEADLINE_EXCEEDED = 4,
-  NOT_FOUND = 5,
-  ALREADY_EXISTS = 6,
-  PERMISSION_DENIED = 7,
-  UNAUTHENTICATED = 16,
-  RESOURCE_EXHAUSTED = 8,
-  FAILED_PRECONDITION = 9,
-  ABORTED = 10,
-  OUT_OF_RANGE = 11,
-  UNIMPLEMENTED = 12,
-  INTERNAL = 13,
-  UNAVAILABLE = 14,
-  DATA_LOSS = 15,
+enum class StatusCode : int {
+  kOk = 0,
+  kCancelled = 1,
+  kUnknown = 2,
+  kInvalidArgument = 3,
+  kDeadlineExceeded = 4,
+  kNotFound = 5,
+  kAlreadyExists = 6,
+  kPermissionDenied = 7,
+  kUnauthenticated = 16,
+  kResourceExhausted = 8,
+  kFailedPrecondition = 9,
+  kAborted = 10,
+  kOutOfRange = 11,
+  kUnimplemented = 12,
+  kInternal = 13,
+  kUnavailable = 14,
+  kDataLoss = 15,
 };
-}  // namespace error
 
 class PROTOBUF_EXPORT Status {
  public:
@@ -71,31 +70,20 @@
 
   // Create a status in the canonical error space with the specified
   // code, and error message.  If "code == 0", error_message is
-  // ignored and a Status object identical to Status::OK is
+  // ignored and a Status object identical to Status::kOk is
   // constructed.
-  Status(error::Code error_code, StringPiece error_message);
+  Status(StatusCode error_code, StringPiece error_message);
   Status(const Status&);
   Status& operator=(const Status& x);
   ~Status() {}
 
-  // Some pre-defined Status objects
-  static const Status OK;             // Identical to 0-arg constructor
-  static const Status CANCELLED;
-  static const Status UNKNOWN;
-
   // Accessor
   bool ok() const {
-    return error_code_ == error::OK;
+    return error_code_ == StatusCode::kOk;
   }
-  int error_code() const {
+  StatusCode code() const {
     return error_code_;
   }
-  error::Code code() const {
-    return error_code_;
-  }
-  StringPiece error_message() const {
-    return error_message_;
-  }
   StringPiece message() const {
     return error_message_;
   }
@@ -109,13 +97,100 @@
   std::string ToString() const;
 
  private:
-  error::Code error_code_;
+  StatusCode error_code_;
   std::string error_message_;
 };
 
+// Returns an OK status, equivalent to a default constructed instance. Prefer
+// usage of `OkStatus()` when constructing such an OK status.
+PROTOBUF_EXPORT Status OkStatus();
+
 // Prints a human-readable representation of 'x' to 'os'.
 PROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);
 
+// These convenience functions return `true` if a given status matches the
+// `StatusCode` error code of its associated function.
+PROTOBUF_EXPORT bool IsAborted(const Status& status);
+PROTOBUF_EXPORT bool IsAlreadyExists(const Status& status);
+PROTOBUF_EXPORT bool IsCancelled(const Status& status);
+PROTOBUF_EXPORT bool IsDataLoss(const Status& status);
+PROTOBUF_EXPORT bool IsDeadlineExceeded(const Status& status);
+PROTOBUF_EXPORT bool IsFailedPrecondition(const Status& status);
+PROTOBUF_EXPORT bool IsInternal(const Status& status);
+PROTOBUF_EXPORT bool IsInvalidArgument(const Status& status);
+PROTOBUF_EXPORT bool IsNotFound(const Status& status);
+PROTOBUF_EXPORT bool IsOutOfRange(const Status& status);
+PROTOBUF_EXPORT bool IsPermissionDenied(const Status& status);
+PROTOBUF_EXPORT bool IsResourceExhausted(const Status& status);
+PROTOBUF_EXPORT bool IsUnauthenticated(const Status& status);
+PROTOBUF_EXPORT bool IsUnavailable(const Status& status);
+PROTOBUF_EXPORT bool IsUnimplemented(const Status& status);
+PROTOBUF_EXPORT bool IsUnknown(const Status& status);
+
+// These convenience functions create an `Status` object with an error code as
+// indicated by the associated function name, using the error message passed in
+// `message`.
+//
+// These functions are intentionally named `*Error` rather than `*Status` to
+// match the names from Abseil:
+// https://github.com/abseil/abseil-cpp/blob/2e9532cc6c701a8323d0cffb468999ab804095ab/absl/status/status.h#L716
+PROTOBUF_EXPORT Status AbortedError(StringPiece message);
+PROTOBUF_EXPORT Status AlreadyExistsError(StringPiece message);
+PROTOBUF_EXPORT Status CancelledError(StringPiece message);
+PROTOBUF_EXPORT Status DataLossError(StringPiece message);
+PROTOBUF_EXPORT Status DeadlineExceededError(StringPiece message);
+PROTOBUF_EXPORT Status FailedPreconditionError(StringPiece message);
+PROTOBUF_EXPORT Status InternalError(StringPiece message);
+PROTOBUF_EXPORT Status InvalidArgumentError(StringPiece message);
+PROTOBUF_EXPORT Status NotFoundError(StringPiece message);
+PROTOBUF_EXPORT Status OutOfRangeError(StringPiece message);
+PROTOBUF_EXPORT Status PermissionDeniedError(StringPiece message);
+PROTOBUF_EXPORT Status ResourceExhaustedError(StringPiece message);
+PROTOBUF_EXPORT Status UnauthenticatedError(StringPiece message);
+PROTOBUF_EXPORT Status UnavailableError(StringPiece message);
+PROTOBUF_EXPORT Status UnimplementedError(StringPiece message);
+PROTOBUF_EXPORT Status UnknownError(StringPiece message);
+
+}  // namespace status_internal
+
+using ::google::protobuf::util::status_internal::Status;
+using ::google::protobuf::util::status_internal::StatusCode;
+
+using ::google::protobuf::util::status_internal::IsAborted;
+using ::google::protobuf::util::status_internal::IsAlreadyExists;
+using ::google::protobuf::util::status_internal::IsCancelled;
+using ::google::protobuf::util::status_internal::IsDataLoss;
+using ::google::protobuf::util::status_internal::IsDeadlineExceeded;
+using ::google::protobuf::util::status_internal::IsFailedPrecondition;
+using ::google::protobuf::util::status_internal::IsInternal;
+using ::google::protobuf::util::status_internal::IsInvalidArgument;
+using ::google::protobuf::util::status_internal::IsNotFound;
+using ::google::protobuf::util::status_internal::IsOutOfRange;
+using ::google::protobuf::util::status_internal::IsPermissionDenied;
+using ::google::protobuf::util::status_internal::IsResourceExhausted;
+using ::google::protobuf::util::status_internal::IsUnauthenticated;
+using ::google::protobuf::util::status_internal::IsUnavailable;
+using ::google::protobuf::util::status_internal::IsUnimplemented;
+using ::google::protobuf::util::status_internal::IsUnknown;
+
+using ::google::protobuf::util::status_internal::OkStatus;
+using ::google::protobuf::util::status_internal::AbortedError;
+using ::google::protobuf::util::status_internal::AlreadyExistsError;
+using ::google::protobuf::util::status_internal::CancelledError;
+using ::google::protobuf::util::status_internal::DataLossError;
+using ::google::protobuf::util::status_internal::DeadlineExceededError;
+using ::google::protobuf::util::status_internal::FailedPreconditionError;
+using ::google::protobuf::util::status_internal::InternalError;
+using ::google::protobuf::util::status_internal::InvalidArgumentError;
+using ::google::protobuf::util::status_internal::NotFoundError;
+using ::google::protobuf::util::status_internal::OutOfRangeError;
+using ::google::protobuf::util::status_internal::PermissionDeniedError;
+using ::google::protobuf::util::status_internal::ResourceExhaustedError;
+using ::google::protobuf::util::status_internal::UnauthenticatedError;
+using ::google::protobuf::util::status_internal::UnavailableError;
+using ::google::protobuf::util::status_internal::UnimplementedError;
+using ::google::protobuf::util::status_internal::UnknownError;
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
index 8f4398c..cca6c2b 100644
--- a/src/google/protobuf/stubs/status_test.cc
+++ b/src/google/protobuf/stubs/status_test.cc
@@ -37,26 +37,170 @@
 namespace google {
 namespace protobuf {
 namespace {
-TEST(Status, Empty) {
-  util::Status status;
-  EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
-  EXPECT_EQ(util::error::OK, util::Status::OK.code());
-  EXPECT_EQ("OK", util::Status::OK.ToString());
-}
 
-TEST(Status, GenericCodes) {
-  EXPECT_EQ(util::error::OK, util::Status::OK.error_code());
-  EXPECT_EQ(util::error::OK, util::Status::OK.code());
-  EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code());
-  EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.code());
-  EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code());
-  EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.code());
+TEST(Status, Constructor) {
+  EXPECT_EQ(util::StatusCode::kOk,
+            util::Status(util::StatusCode::kOk, "").code());
+  EXPECT_EQ(util::StatusCode::kCancelled,
+            util::Status(util::StatusCode::kCancelled, "").code());
+  EXPECT_EQ(util::StatusCode::kUnknown,
+            util::Status(util::StatusCode::kUnknown, "").code());
+  EXPECT_EQ(util::StatusCode::kInvalidArgument,
+            util::Status(util::StatusCode::kInvalidArgument, "").code());
+  EXPECT_EQ(util::StatusCode::kDeadlineExceeded,
+            util::Status(util::StatusCode::kDeadlineExceeded, "").code());
+  EXPECT_EQ(util::StatusCode::kNotFound,
+            util::Status(util::StatusCode::kNotFound, "").code());
+  EXPECT_EQ(util::StatusCode::kAlreadyExists,
+            util::Status(util::StatusCode::kAlreadyExists, "").code());
+  EXPECT_EQ(util::StatusCode::kPermissionDenied,
+            util::Status(util::StatusCode::kPermissionDenied, "").code());
+  EXPECT_EQ(util::StatusCode::kUnauthenticated,
+            util::Status(util::StatusCode::kUnauthenticated, "").code());
+  EXPECT_EQ(util::StatusCode::kResourceExhausted,
+            util::Status(util::StatusCode::kResourceExhausted, "").code());
+  EXPECT_EQ(util::StatusCode::kFailedPrecondition,
+            util::Status(util::StatusCode::kFailedPrecondition, "").code());
+  EXPECT_EQ(util::StatusCode::kAborted,
+            util::Status(util::StatusCode::kAborted, "").code());
+  EXPECT_EQ(util::StatusCode::kOutOfRange,
+            util::Status(util::StatusCode::kOutOfRange, "").code());
+  EXPECT_EQ(util::StatusCode::kUnimplemented,
+            util::Status(util::StatusCode::kUnimplemented, "").code());
+  EXPECT_EQ(util::StatusCode::kInternal,
+            util::Status(util::StatusCode::kInternal, "").code());
+  EXPECT_EQ(util::StatusCode::kUnavailable,
+            util::Status(util::StatusCode::kUnavailable, "").code());
+  EXPECT_EQ(util::StatusCode::kDataLoss,
+            util::Status(util::StatusCode::kDataLoss, "").code());
 }
 
 TEST(Status, ConstructorZero) {
-  util::Status status(util::error::OK, "msg");
+  util::Status status(util::StatusCode::kOk, "msg");
   EXPECT_TRUE(status.ok());
   EXPECT_EQ("OK", status.ToString());
+  EXPECT_EQ(util::OkStatus(), status);
+}
+
+TEST(Status, ConvenienceConstructors) {
+  EXPECT_EQ(util::StatusCode::kOk, util::OkStatus().code());
+  EXPECT_EQ("", util::OkStatus().message());
+
+  EXPECT_EQ(util::StatusCode::kCancelled, util::CancelledError("").code());
+  EXPECT_EQ("", util::CancelledError("").message());
+  EXPECT_EQ("foo", util::CancelledError("foo").message());
+  EXPECT_EQ("bar", util::CancelledError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnknown, util::UnknownError("").code());
+  EXPECT_EQ("", util::UnknownError("").message());
+  EXPECT_EQ("foo", util::UnknownError("foo").message());
+  EXPECT_EQ("bar", util::UnknownError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kInvalidArgument,
+            util::InvalidArgumentError("").code());
+  EXPECT_EQ("", util::InvalidArgumentError("").message());
+  EXPECT_EQ("foo", util::InvalidArgumentError("foo").message());
+  EXPECT_EQ("bar", util::InvalidArgumentError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kDeadlineExceeded,
+            util::DeadlineExceededError("").code());
+  EXPECT_EQ("", util::DeadlineExceededError("").message());
+  EXPECT_EQ("foo", util::DeadlineExceededError("foo").message());
+  EXPECT_EQ("bar", util::DeadlineExceededError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kNotFound, util::NotFoundError("").code());
+  EXPECT_EQ("", util::NotFoundError("").message());
+  EXPECT_EQ("foo", util::NotFoundError("foo").message());
+  EXPECT_EQ("bar", util::NotFoundError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kAlreadyExists,
+            util::AlreadyExistsError("").code());
+  EXPECT_EQ("", util::AlreadyExistsError("").message());
+  EXPECT_EQ("foo", util::AlreadyExistsError("foo").message());
+  EXPECT_EQ("bar", util::AlreadyExistsError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kPermissionDenied,
+            util::PermissionDeniedError("").code());
+  EXPECT_EQ("", util::PermissionDeniedError("").message());
+  EXPECT_EQ("foo", util::PermissionDeniedError("foo").message());
+  EXPECT_EQ("bar", util::PermissionDeniedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnauthenticated,
+            util::UnauthenticatedError("").code());
+  EXPECT_EQ("", util::UnauthenticatedError("").message());
+  EXPECT_EQ("foo", util::UnauthenticatedError("foo").message());
+  EXPECT_EQ("bar", util::UnauthenticatedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kResourceExhausted,
+            util::ResourceExhaustedError("").code());
+  EXPECT_EQ("", util::ResourceExhaustedError("").message());
+  EXPECT_EQ("foo", util::ResourceExhaustedError("foo").message());
+  EXPECT_EQ("bar", util::ResourceExhaustedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kFailedPrecondition,
+            util::FailedPreconditionError("").code());
+  EXPECT_EQ("", util::FailedPreconditionError("").message());
+  EXPECT_EQ("foo", util::FailedPreconditionError("foo").message());
+  EXPECT_EQ("bar", util::FailedPreconditionError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kAborted, util::AbortedError("").code());
+  EXPECT_EQ("", util::AbortedError("").message());
+  EXPECT_EQ("foo", util::AbortedError("foo").message());
+  EXPECT_EQ("bar", util::AbortedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kOutOfRange, util::OutOfRangeError("").code());
+  EXPECT_EQ("", util::OutOfRangeError("").message());
+  EXPECT_EQ("foo", util::OutOfRangeError("foo").message());
+  EXPECT_EQ("bar", util::OutOfRangeError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnimplemented,
+            util::UnimplementedError("").code());
+  EXPECT_EQ("", util::UnimplementedError("").message());
+  EXPECT_EQ("foo", util::UnimplementedError("foo").message());
+  EXPECT_EQ("bar", util::UnimplementedError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kInternal, util::InternalError("").code());
+  EXPECT_EQ("", util::InternalError("").message());
+  EXPECT_EQ("foo", util::InternalError("foo").message());
+  EXPECT_EQ("bar", util::InternalError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kUnavailable, util::UnavailableError("").code());
+  EXPECT_EQ("", util::UnavailableError("").message());
+  EXPECT_EQ("foo", util::UnavailableError("foo").message());
+  EXPECT_EQ("bar", util::UnavailableError("bar").message());
+
+  EXPECT_EQ(util::StatusCode::kDataLoss, util::DataLossError("").code());
+  EXPECT_EQ("", util::DataLossError("").message());
+  EXPECT_EQ("foo", util::DataLossError("foo").message());
+  EXPECT_EQ("bar", util::DataLossError("bar").message());
+}
+
+TEST(Status, ConvenienceTests) {
+  EXPECT_TRUE(util::OkStatus().ok());
+  EXPECT_TRUE(util::IsCancelled(util::CancelledError("")));
+  EXPECT_TRUE(util::IsUnknown(util::UnknownError("")));
+  EXPECT_TRUE(util::IsInvalidArgument(util::InvalidArgumentError("")));
+  EXPECT_TRUE(util::IsDeadlineExceeded(util::DeadlineExceededError("")));
+  EXPECT_TRUE(util::IsNotFound(util::NotFoundError("")));
+  EXPECT_TRUE(util::IsAlreadyExists(util::AlreadyExistsError("")));
+  EXPECT_TRUE(util::IsPermissionDenied(util::PermissionDeniedError("")));
+  EXPECT_TRUE(util::IsUnauthenticated(util::UnauthenticatedError("")));
+  EXPECT_TRUE(util::IsResourceExhausted(util::ResourceExhaustedError("")));
+  EXPECT_TRUE(util::IsFailedPrecondition(util::FailedPreconditionError("")));
+  EXPECT_TRUE(util::IsAborted(util::AbortedError("")));
+  EXPECT_TRUE(util::IsOutOfRange(util::OutOfRangeError("")));
+  EXPECT_TRUE(util::IsUnimplemented(util::UnimplementedError("")));
+  EXPECT_TRUE(util::IsInternal(util::InternalError("")));
+  EXPECT_TRUE(util::IsUnavailable(util::UnavailableError("")));
+  EXPECT_TRUE(util::IsDataLoss(util::DataLossError("")));
+}
+
+TEST(Status, Empty) {
+  util::Status status;
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(util::OkStatus(), status);
+  EXPECT_EQ(util::StatusCode::kOk, status.code());
+  EXPECT_EQ("OK", status.ToString());
 }
 
 TEST(Status, CheckOK) {
@@ -67,38 +211,35 @@
 }
 
 TEST(Status, ErrorMessage) {
-  util::Status status(util::error::INVALID_ARGUMENT, "");
+  util::Status status = util::InvalidArgumentError("");
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ("", status.error_message().ToString());
   EXPECT_EQ("", status.message().ToString());
   EXPECT_EQ("INVALID_ARGUMENT", status.ToString());
-  status = util::Status(util::error::INVALID_ARGUMENT, "msg");
+  status = util::InvalidArgumentError("msg");
   EXPECT_FALSE(status.ok());
-  EXPECT_EQ("msg", status.error_message().ToString());
   EXPECT_EQ("msg", status.message().ToString());
   EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString());
-  status = util::Status(util::error::OK, "msg");
+  status = util::Status(util::StatusCode::kOk, "msg");
   EXPECT_TRUE(status.ok());
-  EXPECT_EQ("", status.error_message().ToString());
   EXPECT_EQ("", status.message().ToString());
   EXPECT_EQ("OK", status.ToString());
 }
 
 TEST(Status, Copy) {
-  util::Status a(util::error::UNKNOWN, "message");
+  util::Status a = util::UnknownError("message");
   util::Status b(a);
   ASSERT_EQ(a.ToString(), b.ToString());
 }
 
 TEST(Status, Assign) {
-  util::Status a(util::error::UNKNOWN, "message");
+  util::Status a = util::UnknownError("message");
   util::Status b;
   b = a;
   ASSERT_EQ(a.ToString(), b.ToString());
 }
 
 TEST(Status, AssignEmpty) {
-  util::Status a(util::error::UNKNOWN, "message");
+  util::Status a = util::UnknownError("message");
   util::Status b;
   a = b;
   ASSERT_EQ(std::string("OK"), a.ToString());
@@ -107,32 +248,33 @@
 }
 
 TEST(Status, EqualsOK) {
-  ASSERT_EQ(util::Status::OK, util::Status());
+  ASSERT_EQ(util::OkStatus(), util::Status());
 }
 
 TEST(Status, EqualsSame) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
-  const util::Status b = util::Status(util::error::CANCELLED, "message");
+  const util::Status a = util::CancelledError("message");
+  const util::Status b = util::CancelledError("message");
   ASSERT_EQ(a, b);
 }
 
 TEST(Status, EqualsCopy) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
+  const util::Status a = util::CancelledError("message");
   const util::Status b = a;
   ASSERT_EQ(a, b);
 }
 
 TEST(Status, EqualsDifferentCode) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
-  const util::Status b = util::Status(util::error::UNKNOWN, "message");
+  const util::Status a = util::CancelledError("message");
+  const util::Status b = util::UnknownError("message");
   ASSERT_NE(a, b);
 }
 
 TEST(Status, EqualsDifferentMessage) {
-  const util::Status a = util::Status(util::error::CANCELLED, "message");
-  const util::Status b = util::Status(util::error::CANCELLED, "another");
+  const util::Status a = util::CancelledError("message");
+  const util::Status b = util::CancelledError("another");
   ASSERT_NE(a, b);
 }
+
 }  // namespace
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index c02e89a..6d8aea5 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -32,7 +32,7 @@
 // object. StatusOr models the concept of an object that is either a
 // usable value, or an error Status explaining why such a value is
 // not present. To this end, StatusOr<T> does not allow its Status
-// value to be Status::OK. Further, StatusOr<T*> does not allow the
+// value to be OkStatus(). Further, StatusOr<T*> does not allow the
 // contained pointer to be nullptr.
 //
 // The primary use-case for StatusOr<T> is as the return value of a
@@ -72,8 +72,7 @@
 //
 //  StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
 //    if (arg <= 0) {
-//      return ::util::Status(::util::error::INVALID_ARGUMENT,
-//                            "Arg must be positive");
+//      return InvalidArgumentError("Arg must be positive");
 //    } else {
 //      return new Foo(arg);
 //    }
@@ -100,7 +99,7 @@
   template<typename U> friend class StatusOr;
 
  public:
-  // Construct a new StatusOr with Status::UNKNOWN status
+  // Construct a new StatusOr with UnknownError() status.
   StatusOr();
 
   // Construct a new StatusOr with the given non-ok status. After calling
@@ -110,8 +109,8 @@
   // value, so it is convenient and sensible to be able to do 'return
   // Status()' when the return type is StatusOr<T>.
   //
-  // REQUIRES: status != Status::OK. This requirement is DCHECKed.
-  // In optimized builds, passing Status::OK here will have the effect
+  // REQUIRES: status != OkStatus(). This requirement is DCHECKed.
+  // In optimized builds, passing OkStatus() here will have the effect
   // of passing PosixErrorSpace::EINVAL as a fallback.
   StatusOr(const Status& status);  // NOLINT
 
@@ -143,7 +142,7 @@
   StatusOr& operator=(const StatusOr<U>& other);
 
   // Returns a reference to our status. If this contains a T, then
-  // returns Status::OK.
+  // returns OkStatus().
   const Status& status() const;
 
   // Returns this->status().ok()
@@ -190,13 +189,13 @@
 
 template<typename T>
 inline StatusOr<T>::StatusOr()
-    : status_(util::Status::UNKNOWN) {
+    : status_(util::UnknownError("")) {
 }
 
 template<typename T>
 inline StatusOr<T>::StatusOr(const Status& status) {
   if (status.ok()) {
-    status_ = Status(error::INTERNAL, "Status::OK is not a valid argument.");
+    status_ = util::InternalError("OkStatus() is not a valid argument.");
   } else {
     status_ = status;
   }
@@ -205,9 +204,9 @@
 template<typename T>
 inline StatusOr<T>::StatusOr(const T& value) {
   if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
-    status_ = Status(error::INTERNAL, "nullptr is not a valid argument.");
+    status_ = util::InternalError("nullptr is not a valid argument.");
   } else {
-    status_ = Status::OK;
+    status_ = util::OkStatus();
     value_ = value;
   }
 }
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
index 6e2a9e5..683900c 100644
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -71,13 +71,13 @@
 TEST(StatusOr, TestDefaultCtor) {
   StatusOr<int> thing;
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::UNKNOWN, thing.status());
+  EXPECT_EQ(util::UnknownError(""), thing.status());
 }
 
 TEST(StatusOr, TestStatusCtor) {
-  StatusOr<int> thing(Status::CANCELLED);
+  StatusOr<int> thing(util::CancelledError(""));
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::CANCELLED, thing.status());
+  EXPECT_EQ(util::CancelledError(""), thing.status());
 }
 
 TEST(StatusOr, TestValueCtor) {
@@ -96,7 +96,7 @@
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOk) {
-  StatusOr<int> original(Status::CANCELLED);
+  StatusOr<int> original(util::CancelledError(""));
   StatusOr<int> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -110,7 +110,7 @@
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
-  StatusOr<int>    original(Status::CANCELLED);
+  StatusOr<int>    original(util::CancelledError(""));
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -125,7 +125,7 @@
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOk) {
-  StatusOr<int> source(Status::CANCELLED);
+  StatusOr<int> source(util::CancelledError(""));
   StatusOr<int> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -141,7 +141,7 @@
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
-  StatusOr<int>    source(Status::CANCELLED);
+  StatusOr<int>    source(util::CancelledError(""));
   StatusOr<double> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -150,9 +150,9 @@
 TEST(StatusOr, TestStatus) {
   StatusOr<int> good(4);
   EXPECT_TRUE(good.ok());
-  StatusOr<int> bad(Status::CANCELLED);
+  StatusOr<int> bad(util::CancelledError(""));
   EXPECT_FALSE(bad.ok());
-  EXPECT_EQ(Status::CANCELLED, bad.status());
+  EXPECT_EQ(util::CancelledError(""), bad.status());
 }
 
 TEST(StatusOr, TestValue) {
@@ -170,13 +170,13 @@
 TEST(StatusOr, TestPointerDefaultCtor) {
   StatusOr<int*> thing;
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::UNKNOWN, thing.status());
+  EXPECT_EQ(util::UnknownError(""), thing.status());
 }
 
 TEST(StatusOr, TestPointerStatusCtor) {
-  StatusOr<int*> thing(Status::CANCELLED);
+  StatusOr<int*> thing(util::CancelledError(""));
   EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(Status::CANCELLED, thing.status());
+  EXPECT_EQ(util::CancelledError(""), thing.status());
 }
 
 TEST(StatusOr, TestPointerValueCtor) {
@@ -195,7 +195,7 @@
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
-  StatusOr<int*> original(Status::CANCELLED);
+  StatusOr<int*> original(util::CancelledError(""));
   StatusOr<int*> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -210,7 +210,7 @@
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
-  StatusOr<Derived*> original(Status::CANCELLED);
+  StatusOr<Derived*> original(util::CancelledError(""));
   StatusOr<Base2*>   copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -225,7 +225,7 @@
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
-  StatusOr<int*> source(Status::CANCELLED);
+  StatusOr<int*> source(util::CancelledError(""));
   StatusOr<int*> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -242,7 +242,7 @@
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
-  StatusOr<Derived*> source(Status::CANCELLED);
+  StatusOr<Derived*> source(util::CancelledError(""));
   StatusOr<Base2*>   target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -252,8 +252,8 @@
   const int kI = 0;
   StatusOr<const int*> good(&kI);
   EXPECT_TRUE(good.ok());
-  StatusOr<const int*> bad(Status::CANCELLED);
-  EXPECT_EQ(Status::CANCELLED, bad.status());
+  StatusOr<const int*> bad(util::CancelledError(""));
+  EXPECT_EQ(util::CancelledError(""), bad.status());
 }
 
 TEST(StatusOr, TestPointerValue) {
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index fbcb20a..0a426fe 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -426,49 +426,6 @@
 // allow StringPiece to be logged
 extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
 
-namespace internal {
-// StringPiece is not a POD and can not be used in an union (pre C++11). We
-// need a POD version of it.
-struct StringPiecePod {
-  // Create from a StringPiece.
-  static StringPiecePod CreateFromStringPiece(StringPiece str) {
-    StringPiecePod pod;
-    pod.data_ = str.data();
-    pod.size_ = str.size();
-    return pod;
-  }
-
-  // Cast to StringPiece.
-  operator StringPiece() const { return StringPiece(data_, size_); }
-
-  bool operator==(const char* value) const {
-    return StringPiece(data_, size_) == StringPiece(value);
-  }
-
-  char operator[](stringpiece_ssize_type i) const {
-    assert(0 <= i);
-    assert(i < size_);
-    return data_[i];
-  }
-
-  const char* data() const { return data_; }
-
-  stringpiece_ssize_type size() const {
-    return size_;
-  }
-
-  std::string ToString() const {
-    return std::string(data_, static_cast<size_t>(size_));
-  }
-
-  explicit operator std::string() const { return ToString(); }
-
- private:
-  const char* data_;
-  stringpiece_ssize_type size_;
-};
-
-}  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 8ce81f2..31c5489 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -664,9 +664,6 @@
   AlphaNum(StringPiece str)
       : piece_data_(str.data()), piece_size_(str.size()) {}
 
-  AlphaNum(internal::StringPiecePod str)
-      : piece_data_(str.data()), piece_size_(str.size()) {}
-
   size_t size() const { return piece_size_; }
   const char *data() const { return piece_data_; }
 
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 5a58db5..a299c12 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -69,7 +69,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ {
  public:
   inline Timestamp() : Timestamp(nullptr) {}
-  virtual ~Timestamp();
+  ~Timestamp() override;
   explicit constexpr Timestamp(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Timestamp(const Timestamp& from);
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 06a30c8..f5b7f24 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -182,7 +182,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Type) */ {
  public:
   inline Type() : Type(nullptr) {}
-  virtual ~Type();
+  ~Type() override;
   explicit constexpr Type(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Type(const Type& from);
@@ -415,7 +415,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Field) */ {
  public:
   inline Field() : Field(nullptr) {}
-  virtual ~Field();
+  ~Field() override;
   explicit constexpr Field(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Field(const Field& from);
@@ -772,7 +772,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Enum) */ {
  public:
   inline Enum() : Enum(nullptr) {}
-  virtual ~Enum();
+  ~Enum() override;
   explicit constexpr Enum(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Enum(const Enum& from);
@@ -979,7 +979,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValue) */ {
  public:
   inline EnumValue() : EnumValue(nullptr) {}
-  virtual ~EnumValue();
+  ~EnumValue() override;
   explicit constexpr EnumValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   EnumValue(const EnumValue& from);
@@ -1146,7 +1146,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Option) */ {
  public:
   inline Option() : Option(nullptr) {}
-  virtual ~Option();
+  ~Option() override;
   explicit constexpr Option(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Option(const Option& from);
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index d3a98e5..4384b79 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -48,21 +48,16 @@
 namespace converter {
 
 using util::Status;
-using util::error::Code;
 
 namespace {
 
-inline Status InvalidArgument(StringPiece value_str) {
-  return Status(util::error::INVALID_ARGUMENT, value_str);
-}
-
 template <typename To, typename From>
 util::StatusOr<To> ValidateNumberConversion(To after, From before) {
   if (after == before &&
       MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
     return after;
   } else {
-    return InvalidArgument(std::is_integral<From>::value
+    return util::InvalidArgumentError(std::is_integral<From>::value
                                ? ValueAsString(before)
                                : std::is_same<From, double>::value
                                      ? DoubleAsString(before)
@@ -107,7 +102,7 @@
   } else if (before > std::numeric_limits<float>::max() ||
              before < -std::numeric_limits<float>::max()) {
     // Double value outside of the range of float.
-    return InvalidArgument(DoubleAsString(before));
+    return util::InvalidArgumentError(DoubleAsString(before));
   } else {
     return static_cast<float>(before);
   }
@@ -179,7 +174,7 @@
     if (value.ok() && !std::isfinite(value.value())) {
       // safe_strtod converts out-of-range values to +inf/-inf, but we want
       // to report them as errors.
-      return InvalidArgument(StrCat("\"", str_, "\""));
+      return util::InvalidArgumentError(StrCat("\"", str_, "\""));
     } else {
       return value;
     }
@@ -209,7 +204,7 @@
     case TYPE_STRING:
       return StringToNumber<bool>(safe_strtob);
     default:
-      return InvalidArgument(
+      return util::InvalidArgumentError(
           ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
   }
 }
@@ -224,7 +219,7 @@
       return base64;
     }
     default:
-      return InvalidArgument(
+      return util::InvalidArgumentError(
           ValueAsStringOrDefault("Cannot convert to string."));
   }
 }
@@ -265,11 +260,11 @@
   if (type_ == TYPE_STRING) {
     std::string decoded;
     if (!DecodeBase64(str_, &decoded)) {
-      return InvalidArgument(ValueAsStringOrDefault("Invalid data in input."));
+      return util::InvalidArgumentError(ValueAsStringOrDefault("Invalid data in input."));
     }
     return decoded;
   } else {
-    return InvalidArgument(ValueAsStringOrDefault(
+    return util::InvalidArgumentError(ValueAsStringOrDefault(
         "Wrong type. Only String or Bytes can be converted to Bytes."));
   }
 }
@@ -329,7 +324,7 @@
     // enum because we preserve unknown enum values as well.
     return ToInt32();
   }
-  return InvalidArgument(
+  return util::InvalidArgumentError(
       ValueAsStringOrDefault("Cannot find enum with given value."));
 }
 
@@ -349,7 +344,7 @@
     case TYPE_FLOAT:
       return NumberConvertAndCheck<To, float>(float_);
     default:  // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL
-      return InvalidArgument(ValueAsStringOrDefault(
+      return util::InvalidArgumentError(ValueAsStringOrDefault(
           "Wrong type. Bool, Enum, String and Cord not supported in "
           "GenericConvert."));
   }
@@ -359,11 +354,11 @@
 util::StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece,
                                                           To*)) const {
   if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
-    return InvalidArgument(StrCat("\"", str_, "\""));
+    return util::InvalidArgumentError(StrCat("\"", str_, "\""));
   }
   To result;
   if (func(str_, &result)) return result;
-  return InvalidArgument(StrCat("\"", std::string(str_), "\""));
+  return util::InvalidArgumentError(StrCat("\"", std::string(str_), "\""));
 }
 
 bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const {
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
index 0b345ae..c27ea5c 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -94,12 +94,12 @@
       : type_(TYPE_BOOL), bool_(value), use_strict_base64_decoding_(false) {}
   DataPiece(StringPiece value, bool use_strict_base64_decoding)
       : type_(TYPE_STRING),
-        str_(StringPiecePod::CreateFromStringPiece(value)),
+        str_(value),
         use_strict_base64_decoding_(use_strict_base64_decoding) {}
   // Constructor for bytes. The second parameter is not used.
   DataPiece(StringPiece value, bool dummy, bool use_strict_base64_decoding)
       : type_(TYPE_BYTES),
-        str_(StringPiecePod::CreateFromStringPiece(value)),
+        str_(value),
         use_strict_base64_decoding_(use_strict_base64_decoding) {}
 
   DataPiece(const DataPiece& r) : type_(r.type_) { InternalCopy(r); }
@@ -192,8 +192,6 @@
   // Data type for this piece of data.
   Type type_;
 
-  typedef ::google::protobuf::internal::StringPiecePod StringPiecePod;
-
   // Stored piece of data.
   union {
     int32_t i32_;
@@ -203,7 +201,7 @@
     double double_;
     float float_;
     bool bool_;
-    StringPiecePod str_;
+    StringPiece str_;
   };
 
   // Uses a stricter version of base64 decoding for byte fields.
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index 0beff99..cd194e8 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -134,8 +134,7 @@
         }
         // Un-escaped '"' must be followed with a ']'.
         if (i >= length - 1 || paths[i + 1] != ']') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
+          return util::InvalidArgumentError(
               StrCat(
                   "Invalid FieldMask '", paths,
                   "'. Map keys should be represented as [\"some_key\"]."));
@@ -147,8 +146,7 @@
         // Checks whether the key ends at the end of a path segment.
         if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' &&
             paths[i + 1] != ')' && paths[i + 1] != '(') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
+          return util::InvalidArgumentError(
               StrCat(
                   "Invalid FieldMask '", paths,
                   "'. Map keys should be at the end of a path segment."));
@@ -160,8 +158,7 @@
       // We are not in a map key, look for the start of one.
       if (paths[i] == '[') {
         if (i >= length - 1 || paths[i + 1] != '\"') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
+          return util::InvalidArgumentError(
               StrCat(
                   "Invalid FieldMask '", paths,
                   "'. Map keys should be represented as [\"some_key\"]."));
@@ -197,8 +194,7 @@
     // Removes the last prefix after seeing a ')'.
     if (i < length && paths[i] == ')') {
       if (prefix.empty()) {
-        return util::Status(
-            util::error::INVALID_ARGUMENT,
+        return util::InvalidArgumentError(
             StrCat("Invalid FieldMask '", paths,
                          "'. Cannot find matching '(' for all ')'."));
       }
@@ -207,14 +203,12 @@
     previous_position = i + 1;
   }
   if (in_map_key) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Invalid FieldMask '", paths,
                      "'. Cannot find matching ']' for all '['."));
   }
   if (!prefix.empty()) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Invalid FieldMask '", paths,
                      "'. Cannot find matching ')' for all '('."));
   }
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index dc0baca..f38b68a 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -302,14 +302,12 @@
         break;
 
       default:
-        result = util::Status(util::error::INTERNAL,
-                              StrCat("Unknown parse type: ", type));
+        result = util::InternalError(StrCat("Unknown parse type: ", type));
         break;
     }
     if (!result.ok()) {
       // If we were cancelled, save our state and try again later.
-      if (!finishing_ &&
-          result == util::Status(util::error::CANCELLED, "")) {
+      if (!finishing_ && util::IsCancelled(result)) {
         stack_.push(type);
         // If we have a key we still need to render, make sure to save off the
         // contents in our own storage.
@@ -353,7 +351,7 @@
       // don't know if the next char would be e, completing it, or something
       // else, making it invalid.
       if (!finishing_ && p_.length() < kKeywordFalse.length()) {
-        return util::Status(util::error::CANCELLED, "");
+        return util::CancelledError("");
       }
       return ReportFailure("Unexpected token.",
                            ParseErrorType::UNEXPECTED_TOKEN);
@@ -392,7 +390,7 @@
       // depending on if we expect more data later.
       if (p_.length() == 1) {
         if (!finishing_) {
-          return util::Status(util::error::CANCELLED, "");
+          return util::CancelledError("");
         }
         return ReportFailure("Closing quote expected in string.",
                              ParseErrorType::EXPECTED_CLOSING_QUOTE);
@@ -461,7 +459,7 @@
   }
   // If we didn't find the closing quote but we expect more data, cancel for now
   if (!finishing_) {
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
   // End of string reached without a closing quote, report an error.
   string_open_ = 0;
@@ -479,7 +477,7 @@
 util::Status JsonStreamParser::ParseUnicodeEscape() {
   if (p_.length() < kUnicodeEscapedLength) {
     if (!finishing_) {
-      return util::Status(util::error::CANCELLED, "");
+      return util::CancelledError("");
     }
     return ReportFailure("Illegal hex string.",
                          ParseErrorType::ILLEGAL_HEX_STRING);
@@ -498,7 +496,7 @@
       code <= JsonEscaping::kMaxHighSurrogate) {
     if (p_.length() < 2 * kUnicodeEscapedLength) {
       if (!finishing_) {
-        return util::Status(util::error::CANCELLED, "");
+        return util::CancelledError("");
       }
       if (!coerce_to_utf8_) {
         return ReportFailure("Missing low surrogate.",
@@ -612,7 +610,7 @@
   // If the entire input is a valid number, and we may have more content in the
   // future, we abort for now and resume when we know more.
   if (index == length && !finishing_) {
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
 
   // Create a string containing just the number, so we can use safe_strtoX
@@ -799,7 +797,7 @@
   // empty-null array value is relying on this ARRAY_MID token.
   stack_.push(ARRAY_MID);
   util::Status result = ParseValue(type);
-  if (result == util::Status(util::error::CANCELLED, "")) {
+  if (util::IsCancelled(result)) {
     // If we were cancelled, pop back off the ARRAY_MID so we don't try to
     // push it on again when we try over.
     stack_.pop();
@@ -874,18 +872,15 @@
   StringPiece segment(begin, end - begin);
   std::string location(p_start - begin, ' ');
   location.push_back('^');
-  auto status =
-      util::Status(util::error::INVALID_ARGUMENT,
-                   StrCat(message, "\n", segment, "\n", location));
-
-  return status;
+  return util::InvalidArgumentError(
+      StrCat(message, "\n", segment, "\n", location));
 }
 
 util::Status JsonStreamParser::ReportUnknown(StringPiece message,
                                              ParseErrorType parse_code) {
   // If we aren't finishing the parse, cancel parsing and try later.
   if (!finishing_) {
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
   if (p_.empty()) {
     return ReportFailure(StrCat("Unexpected end of string. ", message),
@@ -897,8 +892,7 @@
 util::Status JsonStreamParser::IncrementRecursionDepth(
     StringPiece key) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Message too deep. Max recursion depth reached for key '",
                      key, "'"));
   }
@@ -940,7 +934,7 @@
   // we can't know if the key was complete or not.
   if (!finishing_ && p_.empty()) {
     p_ = original;
-    return util::Status(util::error::CANCELLED, "");
+    return util::CancelledError("");
   }
   // Since we aren't using the key storage, clear it out.
   key_storage_.clear();
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
index 4c93d77..47dfe82 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -244,7 +244,7 @@
                              ParseErrorType parse_code);
 
   // Helper function to check recursion depth and increment it. It will return
-  // Status::OK if the current depth is allowed. Otherwise an error is returned.
+  // OkStatus() if the current depth is allowed. Otherwise an error is returned.
   // key is used for error reporting.
   util::Status IncrementRecursionDepth(StringPiece key) const;
 
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
index 21620c2..4bb1025 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -138,8 +138,8 @@
       std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
       }) {
     util::Status result = RunTest(json, split, setup);
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.code());
-    StringPiece error_message(result.error_message());
+    EXPECT_TRUE(util::IsInvalidArgument(result));
+    StringPiece error_message(result.message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
 
@@ -149,8 +149,8 @@
       std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
       }) {
     util::Status result = RunTest(json, split, setup);
-    EXPECT_EQ(util::error::INVALID_ARGUMENT, result.code());
-    StringPiece error_message(result.error_message());
+    EXPECT_TRUE(util::IsInvalidArgument(result));
+    StringPiece error_message(result.message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
 
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 8821dbe..ff4fe54 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -55,8 +55,6 @@
 
 using io::CodedOutputStream;
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
-using util::error::INVALID_ARGUMENT;
-
 
 ProtoWriter::ProtoWriter(TypeResolver* type_resolver,
                          const google::protobuf::Type& type,
@@ -695,8 +693,7 @@
       break;
     }
     default:  // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN.
-      status = util::Status(util::error::INVALID_ARGUMENT,
-                            data.ValueAsStringOrDefault(""));
+      status = util::InvalidArgumentError(data.ValueAsStringOrDefault(""));
   }
 
   if (!status.ok()) {
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 472aa41..b98a14c 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -60,11 +60,8 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace error {
-using util::error::Code;
-using util::error::INTERNAL;
-}  // namespace error
 namespace converter {
+
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat;
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
 
@@ -105,7 +102,7 @@
     case google::protobuf::Field::TYPE_STRING:
       return std::string();
     default:
-      return util::Status(util::error::INTERNAL, "Invalid map key type.");
+      return util::InternalError("Invalid map key type.");
   }
 }
 }  // namespace
@@ -285,8 +282,7 @@
           if (key_field == nullptr) {
             // The Type info for this map entry is incorrect. It should always
             // have a field named "key" and with field number 1.
-            return util::Status(util::error::INTERNAL,
-                                "Invalid map entry.");
+            return util::InternalError("Invalid map entry.");
           }
           ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
         }
@@ -294,7 +290,7 @@
       } else {
         // The Type info for this map entry is incorrect. It should contain
         // exactly two fields with field number 1 and 2.
-        return util::Status(util::error::INTERNAL, "Invalid map entry.");
+        return util::InternalError("Invalid map entry.");
       }
     }
     stream_->PopLimit(old_limit);
@@ -321,15 +317,12 @@
   int64_t seconds = p.first;
   int32_t nanos = p.second;
   if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
-    return util::Status(
-        util::error::INTERNAL,
-        StrCat("Timestamp seconds exceeds limit for field: ",
-                     field_name));
+    return util::InternalError(
+        StrCat("Timestamp seconds exceeds limit for field: ", field_name));
   }
 
   if (nanos < 0 || nanos >= kNanosPerSecond) {
-    return util::Status(
-        util::error::INTERNAL,
+    return util::InternalError(
         StrCat("Timestamp nanos exceeds limit for field: ", field_name));
   }
 
@@ -346,22 +339,19 @@
   int64_t seconds = p.first;
   int32_t nanos = p.second;
   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds) {
-    return util::Status(
-        util::error::INTERNAL,
+    return util::InternalError(
         StrCat("Duration seconds exceeds limit for field: ", field_name));
   }
 
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return util::Status(
-        util::error::INTERNAL,
+    return util::InternalError(
         StrCat("Duration nanos exceeds limit for field: ", field_name));
   }
 
   std::string sign = "";
   if (seconds < 0) {
     if (nanos > 0) {
-      return util::Status(
-          util::error::INTERNAL,
+      return util::InternalError(
           StrCat("Duration nanos is non-negative, but seconds is "
                        "negative for field: ",
                        field_name));
@@ -614,8 +604,7 @@
   // If there is a value but no type, we cannot render it, so report an error.
   if (type_url.empty()) {
     // TODO(sven): Add an external message once those are ready.
-    return util::Status(util::error::INTERNAL,
-                        "Invalid Any, the type_url is missing.");
+    return util::InternalError("Invalid Any, the type_url is missing.");
   }
 
   util::StatusOr<const google::protobuf::Type*> resolved_type =
@@ -624,8 +613,7 @@
   if (!resolved_type.ok()) {
     // Convert into an internal error, since this means the backend gave us
     // an invalid response (missing or invalid type information).
-    return util::Status(util::error::INTERNAL,
-                        resolved_type.status().message());
+    return util::InternalError(resolved_type.status().message());
   }
   // nested_type cannot be null at this time.
   const google::protobuf::Type* nested_type = resolved_type.value();
@@ -662,8 +650,7 @@
       }
     }
     if (paths_field_tag != tag) {
-      return util::Status(util::error::INTERNAL,
-                          "Invalid FieldMask, unexpected field.");
+      return util::InternalError("Invalid FieldMask, unexpected field.");
     }
     std::string str;
     os->stream_->ReadVarint32(&buffer32);  // string size.
@@ -747,8 +734,7 @@
     const google::protobuf::Type* type =
         typeinfo_->GetTypeByTypeUrl(field->type_url());
     if (type == nullptr) {
-      return util::Status(
-          util::error::INTERNAL,
+      return util::InternalError(
           StrCat("Invalid configuration. Could not find the type: ",
                        field->type_url()));
     }
@@ -765,8 +751,7 @@
     --recursion_depth_;
 
     if (!stream_->ConsumedEntireMessage()) {
-      return util::Status(
-          util::error::INVALID_ARGUMENT,
+      return util::InvalidArgumentError(
           "Nested protocol message not parsed in its entirety.");
     }
     stream_->PopLimit(old_limit);
@@ -1065,8 +1050,7 @@
 util::Status ProtoStreamObjectSource::IncrementRecursionDepth(
     StringPiece type_name, StringPiece field_name) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
+    return util::InvalidArgumentError(
         StrCat("Message too deep. Max recursion depth reached for type '",
                      type_name, "', field '", field_name, "'"));
   }
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 441e4fd..60eaf4e 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -287,7 +287,7 @@
       const google::protobuf::Type& type) const;
 
   // Helper function to check recursion depth and increment it. It will return
-  // Status::OK if the current depth is allowed. Otherwise an error is returned.
+  // OkStatus() if the current depth is allowed. Otherwise an error is returned.
   // type_name and field_name are used for error reporting.
   util::Status IncrementRecursionDepth(StringPiece type_name,
                                        StringPiece field_name) const;
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
index 5bd5a91..6ea8b29 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -597,7 +597,7 @@
   }
 
   util::Status status = ExecuteTest(cyclic, Cyclic::descriptor());
-  EXPECT_EQ(util::error::INVALID_ARGUMENT, status.code());
+  EXPECT_TRUE(util::IsInvalidArgument(status));
 }
 
 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
@@ -943,7 +943,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
@@ -959,7 +959,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
@@ -975,7 +975,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
@@ -1108,7 +1108,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
@@ -1119,7 +1119,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
@@ -1130,7 +1130,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
@@ -1141,7 +1141,7 @@
   ow_.StartObject("");
 
   util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_EQ(util::error::INTERNAL, status.code());
+  EXPECT_TRUE(util::IsInternal(status));
 }
 
 TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index 56ca3ca..772e698 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -59,7 +59,6 @@
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
 using std::placeholders::_1;
 using util::Status;
-using util::error::INVALID_ARGUMENT;
 
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
@@ -144,14 +143,14 @@
   // conversion to 'nanos', rather than a double, so that there is no
   // loss of precision.
   if (!s_nanos.empty() && !safe_strto32(s_nanos, &i_nanos)) {
-    return Status(util::error::INVALID_ARGUMENT, parse_failure_message);
+    return util::InvalidArgumentError(parse_failure_message);
   }
   if (i_nanos > kNanosPerSecond || i_nanos < 0) {
-    return Status(util::error::INVALID_ARGUMENT, exceeded_limit_message);
+    return util::InvalidArgumentError(exceeded_limit_message);
   }
   // s_nanos should only have digits. No whitespace.
   if (s_nanos.find_first_not_of("0123456789") != StringPiece::npos) {
-    return Status(util::error::INVALID_ARGUMENT, parse_failure_message);
+    return util::InvalidArgumentError(parse_failure_message);
   }
 
   if (i_nanos > 0) {
@@ -191,8 +190,7 @@
         conversion = 1;
         break;
       default:
-        return Status(util::error::INVALID_ARGUMENT,
-                      exceeded_limit_message);
+        return util::InvalidArgumentError(exceeded_limit_message);
     }
     *nanos = i_nanos * conversion;
   }
@@ -1013,9 +1011,9 @@
       break;
     }
     default: {
-      return Status(util::error::INVALID_ARGUMENT,
-                    "Invalid struct data type. Only number, string, boolean or "
-                    "null values are supported.");
+      return util::InvalidArgumentError(
+          "Invalid struct data type. Only number, string, boolean or  null "
+          "values are supported.");
     }
   }
   ow->ProtoWriter::RenderDataPiece(struct_field_name, data);
@@ -1026,9 +1024,10 @@
                                                 const DataPiece& data) {
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  StrCat("Invalid data type for timestamp, value is ",
-                               data.ValueAsStringOrDefault("")));
+    return util::InvalidArgumentError(
+        StrCat(
+            "Invalid data type for timestamp, value is ",
+            data.ValueAsStringOrDefault("")));
   }
 
   StringPiece value(data.str());
@@ -1037,7 +1036,7 @@
   int32 nanos;
   if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds,
                                                &nanos)) {
-    return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value));
+    return util::InvalidArgumentError(StrCat("Invalid time format: ", value));
   }
 
 
@@ -1057,9 +1056,10 @@
                                                 const DataPiece& data) {
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  StrCat("Invalid data type for field mask, value is ",
-                               data.ValueAsStringOrDefault("")));
+    return util::InvalidArgumentError(
+        StrCat(
+            "Invalid data type for field mask, value is ",
+            data.ValueAsStringOrDefault("")));
   }
 
   // TODO(tsun): figure out how to do proto descriptor based snake case
@@ -1073,16 +1073,17 @@
                                                const DataPiece& data) {
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  StrCat("Invalid data type for duration, value is ",
-                               data.ValueAsStringOrDefault("")));
+    return util::InvalidArgumentError(
+        StrCat(
+            "Invalid data type for duration, value is ",
+            data.ValueAsStringOrDefault("")));
   }
 
   StringPiece value(data.str());
 
   if (!HasSuffixString(value, "s")) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  "Illegal duration format; duration must end with 's'");
+    return util::InvalidArgumentError(
+        "Illegal duration format; duration must end with 's'");
   }
   value = value.substr(0, value.size() - 1);
   int sign = 1;
@@ -1095,8 +1096,8 @@
   SplitSecondsAndNanos(value, &s_secs, &s_nanos);
   uint64_t unsigned_seconds;
   if (!safe_strtou64(s_secs, &unsigned_seconds)) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  "Invalid duration format, failed to parse seconds");
+    return util::InvalidArgumentError(
+        "Invalid duration format, failed to parse seconds");
   }
 
   int32_t nanos = 0;
@@ -1111,8 +1112,7 @@
   int64_t seconds = sign * unsigned_seconds;
   if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
       nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return Status(util::error::INVALID_ARGUMENT,
-                  "Duration value exceeds limits");
+    return util::InvalidArgumentError("Duration value exceeds limits");
   }
 
   ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index eb81b65..2e7b78d 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -140,25 +140,23 @@
     if (!loc_string.empty()) {
       loc_string.append(" ");
     }
-    status_ =
-        util::Status(util::error::INVALID_ARGUMENT,
-                     StrCat(loc_string, unknown_name, ": ", message));
+    status_ = util::InvalidArgumentError(
+        StrCat(loc_string, unknown_name, ": ", message));
   }
 
   void InvalidValue(const converter::LocationTrackerInterface& loc,
                     StringPiece type_name,
                     StringPiece value) override {
-    status_ = util::Status(
-        util::error::INVALID_ARGUMENT,
+    status_ = util::InvalidArgumentError(
         StrCat(GetLocString(loc), ": invalid value ", std::string(value),
                      " for type ", std::string(type_name)));
   }
 
   void MissingField(const converter::LocationTrackerInterface& loc,
                     StringPiece missing_name) override {
-    status_ = util::Status(util::error::INVALID_ARGUMENT,
-                           StrCat(GetLocString(loc), ": missing field ",
-                                        std::string(missing_name)));
+    status_ = util::InvalidArgumentError(
+        StrCat(
+            GetLocString(loc), ": missing field ", std::string(missing_name)));
   }
 
  private:
@@ -271,8 +269,8 @@
   util::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message),
                                            input, &binary, options);
   if (result.ok() && !message->ParseFromString(binary)) {
-    result = util::Status(util::error::INVALID_ARGUMENT,
-                          "JSON transcoder produced invalid protobuf output.");
+    result = util::InvalidArgumentError(
+        "JSON transcoder produced invalid protobuf output.");
   }
   if (pool != DescriptorPool::generated_pool()) {
     delete resolver;
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index a736ea8..c5d8315 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -633,8 +633,7 @@
   delete resolver;
 
   EXPECT_FALSE(result_status.ok());
-  EXPECT_EQ(result_status.code(),
-            util::error::INVALID_ARGUMENT);
+  EXPECT_TRUE(util::IsInvalidArgument(result_status));
 }
 
 TEST_F(JsonUtilTest, HtmlEscape) {
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index addb334..80fe341 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -64,9 +64,6 @@
 using google::protobuf::UInt32Value;
 using google::protobuf::UInt64Value;
 
-using util::error::INVALID_ARGUMENT;
-using util::error::NOT_FOUND;
-
 class DescriptorPoolTypeResolver : public TypeResolver {
  public:
   DescriptorPoolTypeResolver(const std::string& url_prefix,
@@ -83,8 +80,8 @@
 
     const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
     if (descriptor == NULL) {
-      return util::Status(util::error::NOT_FOUND,
-                          "Invalid type URL, unknown type: " + type_name);
+      return util::NotFoundError(
+          "Invalid type URL, unknown type: " + type_name);
     }
     ConvertDescriptor(descriptor, type);
     return util::Status();
@@ -100,8 +97,8 @@
 
     const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
     if (descriptor == NULL) {
-      return util::Status(util::error::NOT_FOUND,
-                          "Invalid type URL, unknown type: " + type_name);
+      return util::InvalidArgumentError(
+          "Invalid type URL, unknown type: " + type_name);
     }
     ConvertEnumDescriptor(descriptor, enum_type);
     return util::Status();
@@ -309,8 +306,7 @@
   util::Status ParseTypeUrl(const std::string& type_url,
                             std::string* type_name) {
     if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") {
-      return util::Status(
-          util::error::INVALID_ARGUMENT,
+      return util::InvalidArgumentError(
           StrCat("Invalid type URL, type URLs must be of the form '",
                        url_prefix_, "/<typename>', got: ", type_url));
     }
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index 65978a8..6ce1c48 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -13,7 +13,7 @@
 #error incompatible with your Protocol Buffer headers. Please update
 #error your headers.
 #endif
-#if 3015002 < PROTOBUF_MIN_PROTOC_VERSION
+#if 3015006 < PROTOBUF_MIN_PROTOC_VERSION
 #error This file was generated by an older version of protoc which is
 #error incompatible with your Protocol Buffer headers. Please
 #error regenerate this file with a newer version of protoc.
@@ -101,7 +101,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DoubleValue) */ {
  public:
   inline DoubleValue() : DoubleValue(nullptr) {}
-  virtual ~DoubleValue();
+  ~DoubleValue() override;
   explicit constexpr DoubleValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   DoubleValue(const DoubleValue& from);
@@ -232,7 +232,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FloatValue) */ {
  public:
   inline FloatValue() : FloatValue(nullptr) {}
-  virtual ~FloatValue();
+  ~FloatValue() override;
   explicit constexpr FloatValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   FloatValue(const FloatValue& from);
@@ -363,7 +363,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int64Value) */ {
  public:
   inline Int64Value() : Int64Value(nullptr) {}
-  virtual ~Int64Value();
+  ~Int64Value() override;
   explicit constexpr Int64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Int64Value(const Int64Value& from);
@@ -494,7 +494,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt64Value) */ {
  public:
   inline UInt64Value() : UInt64Value(nullptr) {}
-  virtual ~UInt64Value();
+  ~UInt64Value() override;
   explicit constexpr UInt64Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UInt64Value(const UInt64Value& from);
@@ -625,7 +625,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int32Value) */ {
  public:
   inline Int32Value() : Int32Value(nullptr) {}
-  virtual ~Int32Value();
+  ~Int32Value() override;
   explicit constexpr Int32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   Int32Value(const Int32Value& from);
@@ -756,7 +756,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt32Value) */ {
  public:
   inline UInt32Value() : UInt32Value(nullptr) {}
-  virtual ~UInt32Value();
+  ~UInt32Value() override;
   explicit constexpr UInt32Value(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   UInt32Value(const UInt32Value& from);
@@ -887,7 +887,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BoolValue) */ {
  public:
   inline BoolValue() : BoolValue(nullptr) {}
-  virtual ~BoolValue();
+  ~BoolValue() override;
   explicit constexpr BoolValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   BoolValue(const BoolValue& from);
@@ -1018,7 +1018,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.StringValue) */ {
  public:
   inline StringValue() : StringValue(nullptr) {}
-  virtual ~StringValue();
+  ~StringValue() override;
   explicit constexpr StringValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   StringValue(const StringValue& from);
@@ -1154,7 +1154,7 @@
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BytesValue) */ {
  public:
   inline BytesValue() : BytesValue(nullptr) {}
-  virtual ~BytesValue();
+  ~BytesValue() override;
   explicit constexpr BytesValue(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized);
 
   BytesValue(const BytesValue& from);