Merge branch 'master' into 3.15.x
diff --git a/.github/mergeable.yml b/.github/mergeable.yml
index 8577f08..ade6c67 100644
--- a/.github/mergeable.yml
+++ b/.github/mergeable.yml
@@ -11,8 +11,8 @@
                 regex: 'release notes: yes'
                 message: 'Please include release notes: yes'
             - must_include:
-                regex: '^(c#|c\+\+|cleanup|conformance tests|integration|java|javascript|go|objective-c|php|python|ruby|bazel|cmake|protoc)'
-                message: 'Please include at least a language label (e.g., c++, java, python). Or apply one of the following labels: bazel, cmake, cleanup, conformance tests, integration, protoc.'
+                regex: '^(autotools|bazel|c#|c\+\+|cleanup|cmake|conformance tests|integration|go|java|javascript|objective-c|php|protoc|python|ruby|kotlin)'
+                message: 'Please include at least a language label (e.g., c++, java, python). Or apply one of the following labels: autotools, bazel, cmake, cleanup, conformance tests, integration, protoc.'
           - must_include:
               regex: 'release notes: no'
               message: 'Please include release notes: no'
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
index a138098..5d252fa 100644
--- a/.github/workflows/codespell.yml
+++ b/.github/workflows/codespell.yml
@@ -13,4 +13,4 @@
         with:
           check_filenames: true
           skip: ./.git,./conformance/third_party,*.snk,*.pb,*.pb.cc,*.pb.h,./src/google/protobuf/testdata,./objectivec/Tests,./python/compatibility_tests/v2.5.0/tests/google/protobuf/internal
-          ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od"
+          ignore_words_list: "alow,alse,ba,cleare,copyable,cloneable,dedup,dur,errorprone,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,OptIn"
diff --git a/.gitignore b/.gitignore
index 44ab2d4..4880c49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,6 +83,7 @@
 
 # JavaBuild output.
 java/core/target
+java/lite/target
 java/util/target
 javanano/target
 java/.idea
diff --git a/BUILD b/BUILD
index 1124321..07ee629 100644
--- a/BUILD
+++ b/BUILD
@@ -14,38 +14,6 @@
 # build configuration
 ################################################################################
 
-# TODO(yannic): Remove in 3.14.0.
-string_flag(
-    name = "incompatible_use_com_google_googletest",
-    build_setting_default = "true",
-    values = ["true", "false"]
-)
-
-config_setting(
-    name = "use_com_google_googletest",
-    flag_values = {
-        "//:incompatible_use_com_google_googletest": "true"
-    },
-)
-
-GTEST = select({
-    "//:use_com_google_googletest": [
-        "@com_google_googletest//:gtest",
-    ],
-    "//conditions:default": [
-        "//external:gtest",
-    ],
-})
-
-GTEST_MAIN = select({
-    "//:use_com_google_googletest": [
-        "@com_google_googletest//:gtest_main",
-    ],
-    "//conditions:default": [
-        "//external:gtest_main",
-    ],
-})
-
 ################################################################################
 # ZLIB configuration
 ################################################################################
@@ -571,6 +539,7 @@
 
 cc_binary(
     name = "test_plugin",
+    testonly = True,
     srcs = [
         # AUTOGEN(test_plugin_srcs)
         "src/google/protobuf/compiler/mock_code_generator.cc",
@@ -580,7 +549,8 @@
     deps = [
         ":protobuf",
         ":protoc_lib",
-    ] + GTEST,
+        "@com_google_googletest//:gtest",
+    ],
 )
 
 cc_test(
@@ -592,7 +562,9 @@
     ],
     deps = [
         ":protobuf_lite",
-    ] + GTEST_MAIN,
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
 )
 
 cc_test(
@@ -695,7 +667,9 @@
         ":cc_test_protos",
         ":protobuf",
         ":protoc_lib",
-    ] + PROTOBUF_DEPS + GTEST_MAIN,
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ] + PROTOBUF_DEPS,
 )
 
 ################################################################################
diff --git a/CHANGES.txt b/CHANGES.txt
index b6490ce..aff04e6 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,45 @@
+Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
+
+  C++
+  * The ::pb namespace is no longer exposed due to conflicts.
+  * Allow MessageDifferencer::TreatAsSet() (and friends) to override previous
+    calls instead of crashing.
+  * Reduce the size of generated proto headers for protos with `string` or
+    `bytes` fields.
+  * Move arena() operation on uncommon path to out-of-line routine
+  * For iterator-pair function parameter types, take both iterators by value.
+  * Code-space savings and perhaps some modest performance improvements in
+    RepeatedPtrField.
+  * Eliminate nullptr check from every tag parse.
+  * Remove unused _$name$_cached_byte_size_ fields.
+  * Serialize extension ranges together when not broken by a proto field in the
+    middle.
+  * Do out-of-line allocation and deallocation of string object in ArenaString.
+  * Streamline ParseContext::ParseMessage<T> to avoid code bloat and improve
+    performance.
+  * New member functions RepeatedField::Assign, RepeatedPtrField::{Add, Assign}.
+  * Fix undefined behavior warning due to innocuous uninitialization of value
+    on an error path.
+  * Avoid expensive inlined code space for encoding message length for messages
+    >= 128 bytes and instead do a procedure call to a shared out-of-line routine.
+  * util::DefaultFieldComparator will be final in a future version of protobuf.
+    Subclasses should inherit from SimpleFieldComparator instead.
+
+  Java:
+  * Detect invalid overflow of byteLimit and return InvalidProtocolBufferException as documented.
+  * Exceptions thrown while reading from an InputStream in parseFrom are now
+    included as causes.
+  * Support potentially more efficient proto parsing from RopeByteStrings.
+  * Clarify runtime of ByteString.Output.toStringBuffer().
+
+  Python
+  * Fixed a bug in text format where a trailing colon was printed for repeated field.
+  * When TextFormat encounters a duplicate message map key, replace the current
+    one instead of merging.
+
+  JavaScript
+  * Make Any.pack() chainable.
+
 2021-04-02 version 3.15.7 (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
 
   C++
diff --git a/Makefile.am b/Makefile.am
index 53b2594..9151842 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -529,7 +529,6 @@
   java/core/src/test/proto/com/google/protobuf/test_check_utf8.proto               \
   java/core/src/test/proto/com/google/protobuf/test_check_utf8_size.proto          \
   java/core/src/test/proto/com/google/protobuf/test_custom_options.proto           \
-  java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto         \
   java/core/src/test/proto/com/google/protobuf/wrappers_test.proto                 \
   java/lite.md                                                                     \
   java/lite/BUILD                                                                  \
diff --git a/WORKSPACE b/WORKSPACE
index 5a767a9..4346dbd 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -17,6 +17,15 @@
     ],
 )
 
+http_archive(
+    name = "com_github_google_benchmark",
+    sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c",
+    strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677",
+    urls = [
+        "https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip",
+    ],
+)
+
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 load("//:protobuf_deps.bzl", "protobuf_deps")
 
@@ -29,18 +38,6 @@
     actual = "//util/python:python_headers",
 )
 
-# TODO(yannic): Remove in 3.14.0.
-bind(
-    name = "gtest",
-    actual = "@com_google_googletest//:gtest",
-)
-
-# TODO(yannic): Remove in 3.14.0.
-bind(
-    name = "gtest_main",
-    actual = "@com_google_googletest//:gtest_main",
-)
-
 jvm_maven_import_external(
     name = "guava_maven",
     artifact = "com.google.guava:guava:18.0",
diff --git a/benchmarks/BUILD b/benchmarks/BUILD
new file mode 100644
index 0000000..8e6063b
--- /dev/null
+++ b/benchmarks/BUILD
@@ -0,0 +1,65 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+proto_library(
+    name = "benchmarks_proto",
+    srcs = [
+        "benchmarks.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmarks_cc_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "benchmarks_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmarks_java_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "benchmarks_proto",
+    ],
+)
+
+proto_library(
+    name = "google_size_proto",
+    srcs = [
+        "google_size.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+)
+
+cc_proto_library(
+    name = "google_size_cc_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "google_size_proto",
+    ],
+)
+
+java_proto_library(
+    name = "google_size_java_proto",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "google_size_proto",
+    ],
+)
diff --git a/benchmarks/cpp/BUILD b/benchmarks/cpp/BUILD
new file mode 100644
index 0000000..b744f89
--- /dev/null
+++ b/benchmarks/cpp/BUILD
@@ -0,0 +1,15 @@
+load("@rules_cc//cc:defs.bzl", "cc_binary")
+
+cc_binary(
+    name = "cpp",
+    srcs = [
+        "cpp_benchmark.cc",
+    ],
+    tags = ["benchmark"],
+    deps = [
+        "//:protobuf",
+        "//benchmarks:benchmarks_cc_proto",
+        "//benchmarks/datasets:cc_protos",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
diff --git a/benchmarks/datasets/BUILD b/benchmarks/datasets/BUILD
new file mode 100644
index 0000000..f29a276
--- /dev/null
+++ b/benchmarks/datasets/BUILD
@@ -0,0 +1,59 @@
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@rules_java//java:defs.bzl", "java_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "//benchmarks/datasets/google_message1/proto2:datasets",
+        "//benchmarks/datasets/google_message1/proto3:datasets",
+        "//benchmarks/datasets/google_message2:datasets",
+        "//benchmarks/datasets/google_message3:datasets",
+        "//benchmarks/datasets/google_message4:datasets",
+    ],
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+)
+
+proto_library(
+    name = "protos",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "//benchmarks/datasets/google_message1/proto2:benchmark_message1_proto2_proto",
+        "//benchmarks/datasets/google_message1/proto3:benchmark_message1_proto3_proto",
+        "//benchmarks/datasets/google_message2:benchmark_message2_proto",
+        "//benchmarks/datasets/google_message3:benchmark_message3_proto",
+        "//benchmarks/datasets/google_message4:benchmark_message4_proto",
+    ],
+)
+
+cc_library(
+    name = "cc_protos",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    deps = [
+        "//benchmarks/datasets/google_message1/proto2:benchmark_message1_proto2_cc_proto",
+        "//benchmarks/datasets/google_message1/proto3:benchmark_message1_proto3_cc_proto",
+        "//benchmarks/datasets/google_message2:benchmark_message2_cc_proto",
+        "//benchmarks/datasets/google_message3:benchmark_message3_cc_proto",
+        "//benchmarks/datasets/google_message4:benchmark_message4_cc_proto",
+    ],
+)
+
+java_library(
+    name = "java_protos",
+    visibility = [
+        "//benchmarks:__subpackages__",
+    ],
+    exports = [
+        "//benchmarks/datasets/google_message1/proto2:benchmark_message1_proto2_java_proto",
+        "//benchmarks/datasets/google_message1/proto3:benchmark_message1_proto3_java_proto",
+        "//benchmarks/datasets/google_message2:benchmark_message2_java_proto",
+        "//benchmarks/datasets/google_message3:benchmark_message3_java_proto",
+        "//benchmarks/datasets/google_message4:benchmark_message4_java_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message1/proto2/BUILD b/benchmarks/datasets/google_message1/proto2/BUILD
new file mode 100644
index 0000000..d4d38ce
--- /dev/null
+++ b/benchmarks/datasets/google_message1/proto2/BUILD
@@ -0,0 +1,44 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "dataset.google_message1_proto2.pb",
+    ],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message1_proto2_proto",
+    srcs = [
+        "benchmark_message1_proto2.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message1_proto2_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto2_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message1_proto2_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto2_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message1/proto3/BUILD b/benchmarks/datasets/google_message1/proto3/BUILD
new file mode 100644
index 0000000..c2d627a
--- /dev/null
+++ b/benchmarks/datasets/google_message1/proto3/BUILD
@@ -0,0 +1,44 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "dataset.google_message1_proto3.pb",
+    ],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message1_proto3_proto",
+    srcs = [
+        "benchmark_message1_proto3.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message1_proto3_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto3_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message1_proto3_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message1_proto3_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message2/BUILD b/benchmarks/datasets/google_message2/BUILD
new file mode 100644
index 0000000..1ca87fb
--- /dev/null
+++ b/benchmarks/datasets/google_message2/BUILD
@@ -0,0 +1,44 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [
+        "dataset.google_message2.pb",
+    ],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message2_proto",
+    srcs = [
+        "benchmark_message2.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message2_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message2_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message2_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message2_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message3/BUILD b/benchmarks/datasets/google_message3/BUILD
new file mode 100644
index 0000000..9a00294
--- /dev/null
+++ b/benchmarks/datasets/google_message3/BUILD
@@ -0,0 +1,50 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message3_proto",
+    srcs = [
+        "benchmark_message3.proto",
+        "benchmark_message3_1.proto",
+        "benchmark_message3_2.proto",
+        "benchmark_message3_3.proto",
+        "benchmark_message3_4.proto",
+        "benchmark_message3_5.proto",
+        "benchmark_message3_6.proto",
+        "benchmark_message3_7.proto",
+        "benchmark_message3_8.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message3_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message3_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message3_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message3_proto",
+    ],
+)
diff --git a/benchmarks/datasets/google_message4/BUILD b/benchmarks/datasets/google_message4/BUILD
new file mode 100644
index 0000000..b23a4c9
--- /dev/null
+++ b/benchmarks/datasets/google_message4/BUILD
@@ -0,0 +1,45 @@
+load("@rules_cc//cc:defs.bzl", "cc_proto_library")
+load("@rules_java//java:defs.bzl", "java_proto_library")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+filegroup(
+    name = "datasets",
+    srcs = [],
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "benchmark_message4_proto",
+    srcs = [
+        "benchmark_message4.proto",
+        "benchmark_message4_1.proto",
+        "benchmark_message4_2.proto",
+        "benchmark_message4_3.proto",
+    ],
+    strip_import_prefix = "/benchmarks",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+)
+
+cc_proto_library(
+    name = "benchmark_message4_cc_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message4_proto",
+    ],
+)
+
+java_proto_library(
+    name = "benchmark_message4_java_proto",
+    visibility = [
+        "//benchmarks/datasets:__pkg__",
+    ],
+    deps = [
+        "benchmark_message4_proto",
+    ],
+)
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 9bd8565..0f4b091 100644
--- a/configure.ac
+++ b/configure.ac
@@ -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/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc
index 4a0d8e8..48bfa96 100644
--- a/conformance/binary_json_conformance_suite.cc
+++ b/conformance/binary_json_conformance_suite.cc
@@ -300,7 +300,7 @@
 }
 
 string UpperCase(string str) {
-  for (int i = 0; i < str.size(); i++) {
+  for (size_t i = 0; i < str.size(); i++) {
     str[i] = toupper(str[i]);
   }
   return str;
diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc
index 9546518..5782789 100644
--- a/conformance/conformance_cpp.cc
+++ b/conformance/conformance_cpp.cc
@@ -55,6 +55,7 @@
 using google::protobuf::util::NewTypeResolverForDescriptorPool;
 using google::protobuf::util::TypeResolver;
 using protobuf_test_messages::proto3::TestAllTypesProto3;
+using protobuf_test_messages::proto2::TestAllTypesProto2;
 using std::string;
 
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
@@ -102,6 +103,8 @@
 
 void DoTest(const ConformanceRequest& request, ConformanceResponse* response) {
   Message *test_message;
+  google::protobuf::LinkMessageReflection<TestAllTypesProto2>();
+  google::protobuf::LinkMessageReflection<TestAllTypesProto3>();
   const Descriptor *descriptor = DescriptorPool::generated_pool()->FindMessageTypeByName(
       request.message_type());
   if (!descriptor) {
@@ -131,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;
       }
 
@@ -186,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/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index 9f893cb..1572ac0 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -297,7 +297,7 @@
 
     std::vector<const char *> argv;
     argv.push_back(executable.get());
-    for (int i = 0; i < executable_args_.size(); ++i) {
+    for (size_t i = 0; i < executable_args_.size(); ++i) {
       argv.push_back(executable_args_[i].c_str());
     }
     argv.push_back(nullptr);
@@ -307,7 +307,7 @@
 }
 
 void ForkPipeRunner::CheckedWrite(int fd, const void *buf, size_t len) {
-  if (write(fd, buf, len) != len) {
+  if (static_cast<size_t>(write(fd, buf, len)) != len) {
     GOOGLE_LOG(FATAL) << current_test_name_
                << ": error writing to test program: " << strerror(errno);
   }
diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc
index 4c9dc7d..460bc24 100644
--- a/conformance/text_format_conformance_suite.cc
+++ b/conformance/text_format_conformance_suite.cc
@@ -451,6 +451,27 @@
       }
       )",
                                     prototype);
+
+  prototype.Clear();
+  ConformanceRequestSetting setting_map(
+      REQUIRED, conformance::TEXT_FORMAT, conformance::PROTOBUF,
+      conformance::TEXT_FORMAT_TEST, prototype, "DuplicateMapKey", R"(
+      map_string_nested_message {
+        key: "duplicate"
+        value: { a: 123 }
+      }
+      map_string_nested_message {
+        key: "duplicate"
+        value: { corecursive: {} }
+      }
+      )");
+  // The last-specified value will be retained in a parsed map
+  RunValidInputTest(setting_map, R"(
+      map_string_nested_message {
+        key: "duplicate"
+        value: { corecursive: {} }
+      }
+      )");
 }
 
 }  // namespace protobuf
diff --git a/csharp/install_dotnet_sdk.ps1 b/csharp/install_dotnet_sdk.ps1
index 8bc967c..c78655c 100755
--- a/csharp/install_dotnet_sdk.ps1
+++ b/csharp/install_dotnet_sdk.ps1
@@ -17,4 +17,4 @@
 # The SDK versions to install should be kept in sync with versions
 # installed by kokoro/linux/dockerfile/test/csharp/Dockerfile
 &$InstallScriptPath -Version 2.1.802
-&$InstallScriptPath -Version 3.1.301
+&$InstallScriptPath -Version 5.0.102
diff --git a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
index 73042f3..ac8e009a 100644
--- a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
+++ b/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFramework>net5.0</TargetFramework>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
     <IsPackable>False</IsPackable>
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
index 7d3a238..b56c99e 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
@@ -25,49 +25,54 @@
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
             "Ci5nb29nbGUvcHJvdG9idWYvdW5pdHRlc3RfcHJvdG8zX29wdGlvbmFsLnBy",
-            "b3RvEhFwcm90b2J1Zl91bml0dGVzdCKxCgoSVGVzdFByb3RvM09wdGlvbmFs",
-            "EhsKDm9wdGlvbmFsX2ludDMyGAEgASgFSACIAQESGwoOb3B0aW9uYWxfaW50",
-            "NjQYAiABKANIAYgBARIcCg9vcHRpb25hbF91aW50MzIYAyABKA1IAogBARIc",
-            "Cg9vcHRpb25hbF91aW50NjQYBCABKARIA4gBARIcCg9vcHRpb25hbF9zaW50",
-            "MzIYBSABKBFIBIgBARIcCg9vcHRpb25hbF9zaW50NjQYBiABKBJIBYgBARId",
-            "ChBvcHRpb25hbF9maXhlZDMyGAcgASgHSAaIAQESHQoQb3B0aW9uYWxfZml4",
-            "ZWQ2NBgIIAEoBkgHiAEBEh4KEW9wdGlvbmFsX3NmaXhlZDMyGAkgASgPSAiI",
-            "AQESHgoRb3B0aW9uYWxfc2ZpeGVkNjQYCiABKBBICYgBARIbCg5vcHRpb25h",
-            "bF9mbG9hdBgLIAEoAkgKiAEBEhwKD29wdGlvbmFsX2RvdWJsZRgMIAEoAUgL",
-            "iAEBEhoKDW9wdGlvbmFsX2Jvb2wYDSABKAhIDIgBARIcCg9vcHRpb25hbF9z",
-            "dHJpbmcYDiABKAlIDYgBARIbCg5vcHRpb25hbF9ieXRlcxgPIAEoDEgOiAEB",
-            "Eh4KDW9wdGlvbmFsX2NvcmQYECABKAlCAggBSA+IAQESWQoXb3B0aW9uYWxf",
-            "bmVzdGVkX21lc3NhZ2UYEiABKAsyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0",
-            "UHJvdG8zT3B0aW9uYWwuTmVzdGVkTWVzc2FnZUgQiAEBElkKE2xhenlfbmVz",
-            "dGVkX21lc3NhZ2UYEyABKAsyMy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJv",
-            "dG8zT3B0aW9uYWwuTmVzdGVkTWVzc2FnZUICKAFIEYgBARJTChRvcHRpb25h",
-            "bF9uZXN0ZWRfZW51bRgVIAEoDjIwLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQ",
-            "cm90bzNPcHRpb25hbC5OZXN0ZWRFbnVtSBKIAQESFgoOc2luZ3VsYXJfaW50",
-            "MzIYFiABKAUSFgoOc2luZ3VsYXJfaW50NjQYFyABKAMaJwoNTmVzdGVkTWVz",
-            "c2FnZRIPCgJiYhgBIAEoBUgAiAEBQgUKA19iYiJKCgpOZXN0ZWRFbnVtEg8K",
-            "C1VOU1BFQ0lGSUVEEAASBwoDRk9PEAESBwoDQkFSEAISBwoDQkFaEAMSEAoD",
-            "TkVHEP///////////wFCEQoPX29wdGlvbmFsX2ludDMyQhEKD19vcHRpb25h",
-            "bF9pbnQ2NEISChBfb3B0aW9uYWxfdWludDMyQhIKEF9vcHRpb25hbF91aW50",
-            "NjRCEgoQX29wdGlvbmFsX3NpbnQzMkISChBfb3B0aW9uYWxfc2ludDY0QhMK",
-            "EV9vcHRpb25hbF9maXhlZDMyQhMKEV9vcHRpb25hbF9maXhlZDY0QhQKEl9v",
-            "cHRpb25hbF9zZml4ZWQzMkIUChJfb3B0aW9uYWxfc2ZpeGVkNjRCEQoPX29w",
-            "dGlvbmFsX2Zsb2F0QhIKEF9vcHRpb25hbF9kb3VibGVCEAoOX29wdGlvbmFs",
-            "X2Jvb2xCEgoQX29wdGlvbmFsX3N0cmluZ0IRCg9fb3B0aW9uYWxfYnl0ZXNC",
-            "EAoOX29wdGlvbmFsX2NvcmRCGgoYX29wdGlvbmFsX25lc3RlZF9tZXNzYWdl",
-            "QhYKFF9sYXp5X25lc3RlZF9tZXNzYWdlQhcKFV9vcHRpb25hbF9uZXN0ZWRf",
-            "ZW51bSKJAgoZVGVzdFByb3RvM09wdGlvbmFsTWVzc2FnZRJSCg5uZXN0ZWRf",
-            "bWVzc2FnZRgBIAEoCzI6LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQcm90bzNP",
-            "cHRpb25hbE1lc3NhZ2UuTmVzdGVkTWVzc2FnZRJgChdvcHRpb25hbF9uZXN0",
-            "ZWRfbWVzc2FnZRgCIAEoCzI6LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQcm90",
-            "bzNPcHRpb25hbE1lc3NhZ2UuTmVzdGVkTWVzc2FnZUgAiAEBGhoKDU5lc3Rl",
-            "ZE1lc3NhZ2USCQoBcxgBIAEoCUIaChhfb3B0aW9uYWxfbmVzdGVkX21lc3Nh",
-            "Z2VCJQohY29tLmdvb2dsZS5wcm90b2J1Zi50ZXN0aW5nLnByb3RvUAFiBnBy",
-            "b3RvMw=="));
+            "b3RvEhFwcm90b2J1Zl91bml0dGVzdBogZ29vZ2xlL3Byb3RvYnVmL2Rlc2Ny",
+            "aXB0b3IucHJvdG8isQoKElRlc3RQcm90bzNPcHRpb25hbBIbCg5vcHRpb25h",
+            "bF9pbnQzMhgBIAEoBUgAiAEBEhsKDm9wdGlvbmFsX2ludDY0GAIgASgDSAGI",
+            "AQESHAoPb3B0aW9uYWxfdWludDMyGAMgASgNSAKIAQESHAoPb3B0aW9uYWxf",
+            "dWludDY0GAQgASgESAOIAQESHAoPb3B0aW9uYWxfc2ludDMyGAUgASgRSASI",
+            "AQESHAoPb3B0aW9uYWxfc2ludDY0GAYgASgSSAWIAQESHQoQb3B0aW9uYWxf",
+            "Zml4ZWQzMhgHIAEoB0gGiAEBEh0KEG9wdGlvbmFsX2ZpeGVkNjQYCCABKAZI",
+            "B4gBARIeChFvcHRpb25hbF9zZml4ZWQzMhgJIAEoD0gIiAEBEh4KEW9wdGlv",
+            "bmFsX3NmaXhlZDY0GAogASgQSAmIAQESGwoOb3B0aW9uYWxfZmxvYXQYCyAB",
+            "KAJICogBARIcCg9vcHRpb25hbF9kb3VibGUYDCABKAFIC4gBARIaCg1vcHRp",
+            "b25hbF9ib29sGA0gASgISAyIAQESHAoPb3B0aW9uYWxfc3RyaW5nGA4gASgJ",
+            "SA2IAQESGwoOb3B0aW9uYWxfYnl0ZXMYDyABKAxIDogBARIeCg1vcHRpb25h",
+            "bF9jb3JkGBAgASgJQgIIAUgPiAEBElkKF29wdGlvbmFsX25lc3RlZF9tZXNz",
+            "YWdlGBIgASgLMjMucHJvdG9idWZfdW5pdHRlc3QuVGVzdFByb3RvM09wdGlv",
+            "bmFsLk5lc3RlZE1lc3NhZ2VIEIgBARJZChNsYXp5X25lc3RlZF9tZXNzYWdl",
+            "GBMgASgLMjMucHJvdG9idWZfdW5pdHRlc3QuVGVzdFByb3RvM09wdGlvbmFs",
+            "Lk5lc3RlZE1lc3NhZ2VCAigBSBGIAQESUwoUb3B0aW9uYWxfbmVzdGVkX2Vu",
+            "dW0YFSABKA4yMC5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJvdG8zT3B0aW9u",
+            "YWwuTmVzdGVkRW51bUgSiAEBEhYKDnNpbmd1bGFyX2ludDMyGBYgASgFEhYK",
+            "DnNpbmd1bGFyX2ludDY0GBcgASgDGicKDU5lc3RlZE1lc3NhZ2USDwoCYmIY",
+            "ASABKAVIAIgBAUIFCgNfYmIiSgoKTmVzdGVkRW51bRIPCgtVTlNQRUNJRklF",
+            "RBAAEgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADEhAKA05FRxD/////////",
+            "//8BQhEKD19vcHRpb25hbF9pbnQzMkIRCg9fb3B0aW9uYWxfaW50NjRCEgoQ",
+            "X29wdGlvbmFsX3VpbnQzMkISChBfb3B0aW9uYWxfdWludDY0QhIKEF9vcHRp",
+            "b25hbF9zaW50MzJCEgoQX29wdGlvbmFsX3NpbnQ2NEITChFfb3B0aW9uYWxf",
+            "Zml4ZWQzMkITChFfb3B0aW9uYWxfZml4ZWQ2NEIUChJfb3B0aW9uYWxfc2Zp",
+            "eGVkMzJCFAoSX29wdGlvbmFsX3NmaXhlZDY0QhEKD19vcHRpb25hbF9mbG9h",
+            "dEISChBfb3B0aW9uYWxfZG91YmxlQhAKDl9vcHRpb25hbF9ib29sQhIKEF9v",
+            "cHRpb25hbF9zdHJpbmdCEQoPX29wdGlvbmFsX2J5dGVzQhAKDl9vcHRpb25h",
+            "bF9jb3JkQhoKGF9vcHRpb25hbF9uZXN0ZWRfbWVzc2FnZUIWChRfbGF6eV9u",
+            "ZXN0ZWRfbWVzc2FnZUIXChVfb3B0aW9uYWxfbmVzdGVkX2VudW0iiQIKGVRl",
+            "c3RQcm90bzNPcHRpb25hbE1lc3NhZ2USUgoObmVzdGVkX21lc3NhZ2UYASAB",
+            "KAsyOi5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJvdG8zT3B0aW9uYWxNZXNz",
+            "YWdlLk5lc3RlZE1lc3NhZ2USYAoXb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2UY",
+            "AiABKAsyOi5wcm90b2J1Zl91bml0dGVzdC5UZXN0UHJvdG8zT3B0aW9uYWxN",
+            "ZXNzYWdlLk5lc3RlZE1lc3NhZ2VIAIgBARoaCg1OZXN0ZWRNZXNzYWdlEgkK",
+            "AXMYASABKAlCGgoYX29wdGlvbmFsX25lc3RlZF9tZXNzYWdlIqkBChhQcm90",
+            "bzNPcHRpb25hbEV4dGVuc2lvbnMyPAoPZXh0X25vX29wdGlvbmFsEh8uZ29v",
+            "Z2xlLnByb3RvYnVmLk1lc3NhZ2VPcHRpb25zGIjN2akBIAEoBTJBChFleHRf",
+            "d2l0aF9vcHRpb25hbBIfLmdvb2dsZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9u",
+            "cxiJzdmpASABKAWIAQE6DMDozM0KCMjozM0KEEIlCiFjb20uZ29vZ2xlLnBy",
+            "b3RvYnVmLnRlc3RpbmcucHJvdG9QAWIGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { },
+          new pbr::FileDescriptor[] { global::Google.Protobuf.Reflection.DescriptorReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
             new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional), global::ProtobufUnittest.TestProto3Optional.Parser, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum", "SingularInt32", "SingularInt64" }, new[]{ "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalCord", "OptionalNestedMessage", "LazyNestedMessage", "OptionalNestedEnum" }, new[]{ typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedEnum) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage), global::ProtobufUnittest.TestProto3Optional.Types.NestedMessage.Parser, new[]{ "Bb" }, new[]{ "Bb" }, null, null, null)}),
-            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Parser, new[]{ "NestedMessage", "OptionalNestedMessage" }, new[]{ "OptionalNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage.Parser, new[]{ "S" }, null, null, null, null)})
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Parser, new[]{ "NestedMessage", "OptionalNestedMessage" }, new[]{ "OptionalNestedMessage" }, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage), global::ProtobufUnittest.TestProto3OptionalMessage.Types.NestedMessage.Parser, new[]{ "S" }, null, null, null, null)}),
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufUnittest.Proto3OptionalExtensions), global::ProtobufUnittest.Proto3OptionalExtensions.Parser, null, null, null, new pb::Extension[] { global::ProtobufUnittest.Proto3OptionalExtensions.Extensions.ExtNoOptional, global::ProtobufUnittest.Proto3OptionalExtensions.Extensions.ExtWithOptional }, null)
           }));
     }
     #endregion
@@ -1789,6 +1794,153 @@
 
   }
 
+  public sealed partial class Proto3OptionalExtensions : pb::IMessage<Proto3OptionalExtensions>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<Proto3OptionalExtensions> _parser = new pb::MessageParser<Proto3OptionalExtensions>(() => new Proto3OptionalExtensions());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static pb::MessageParser<Proto3OptionalExtensions> Parser { get { return _parser; } }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static pbr::MessageDescriptor Descriptor {
+      get { return global::ProtobufUnittest.UnittestProto3OptionalReflection.Descriptor.MessageTypes[2]; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    pbr::MessageDescriptor pb::IMessage.Descriptor {
+      get { return Descriptor; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public Proto3OptionalExtensions() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public Proto3OptionalExtensions(Proto3OptionalExtensions other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public Proto3OptionalExtensions Clone() {
+      return new Proto3OptionalExtensions(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override bool Equals(object other) {
+      return Equals(other as Proto3OptionalExtensions);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public bool Equals(Proto3OptionalExtensions other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      return Equals(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override int GetHashCode() {
+      int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
+      return hash;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public override string ToString() {
+      return pb::JsonFormatter.ToDiagnosticString(this);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void WriteTo(pb::CodedOutputStream output) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      output.WriteRawMessage(this);
+    #else
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(ref output);
+      }
+    }
+    #endif
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public int CalculateSize() {
+      int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void MergeFrom(Proto3OptionalExtensions other) {
+      if (other == null) {
+        return;
+      }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public void MergeFrom(pb::CodedInputStream input) {
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      input.ReadRawMessage(this);
+    #else
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+            break;
+        }
+      }
+    #endif
+    }
+
+    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+      uint tag;
+      while ((tag = input.ReadTag()) != 0) {
+        switch(tag) {
+          default:
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+            break;
+        }
+      }
+    }
+    #endif
+
+    #region Extensions
+    /// <summary>Container for extensions for other messages declared in the Proto3OptionalExtensions message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public static partial class Extensions {
+      public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int> ExtNoOptional =
+        new pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int>(355886728, pb::FieldCodec.ForInt32(2847093824, 0));
+      public static readonly pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int> ExtWithOptional =
+        new pb::Extension<global::Google.Protobuf.Reflection.MessageOptions, int>(355886729, pb::FieldCodec.ForInt32(2847093832, 0));
+    }
+    #endregion
+
+  }
+
   #endregion
 
 }
diff --git a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs
index 5b9913b..a36a951 100644
--- a/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs
+++ b/csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs
@@ -42,7 +42,7 @@
     /// ArrayBufferWriter is originally from corefx, and has been contributed to Protobuf
     /// https://github.com/dotnet/runtime/blob/071da4c41aa808c949a773b92dca6f88de9d11f3/src/libraries/Common/src/System/Buffers/ArrayBufferWriter.cs
     /// </summary>
-    internal sealed class ArrayBufferWriter<T> : IBufferWriter<T>
+    internal sealed class TestArrayBufferWriter<T> : IBufferWriter<T>
     {
         private T[] _buffer;
         private int _index;
@@ -50,10 +50,10 @@
         private const int DefaultInitialBufferSize = 256;
 
         /// <summary>
-        /// Creates an instance of an <see cref="ArrayBufferWriter{T}"/>, in which data can be written to,
+        /// Creates an instance of an <see cref="TestArrayBufferWriter{T}"/>, in which data can be written to,
         /// with the default initial capacity.
         /// </summary>
-        public ArrayBufferWriter()
+        public TestArrayBufferWriter()
         {
             _buffer = new T[0];
             _index = 0;
@@ -66,14 +66,14 @@
         public int? MaxGrowBy { get; set; }
 
         /// <summary>
-        /// Creates an instance of an <see cref="ArrayBufferWriter{T}"/>, in which data can be written to,
+        /// Creates an instance of an <see cref="TestArrayBufferWriter{T}"/>, in which data can be written to,
         /// with an initial capacity specified.
         /// </summary>
         /// <param name="initialCapacity">The minimum capacity with which to initialize the underlying buffer.</param>
         /// <exception cref="ArgumentException">
         /// Thrown when <paramref name="initialCapacity"/> is not positive (i.e. less than or equal to 0).
         /// </exception>
-        public ArrayBufferWriter(int initialCapacity)
+        public TestArrayBufferWriter(int initialCapacity)
         {
             if (initialCapacity <= 0)
                 throw new ArgumentException(nameof(initialCapacity));
@@ -111,7 +111,7 @@
         /// Clears the data written to the underlying buffer.
         /// </summary>
         /// <remarks>
-        /// You must clear the <see cref="ArrayBufferWriter{T}"/> before trying to re-use it.
+        /// You must clear the <see cref="TestArrayBufferWriter{T}"/> before trying to re-use it.
         /// </remarks>
         public void Clear()
         {
diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 1e5333c..1444009 100644
--- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -58,7 +58,7 @@
                 Assert.AreEqual(data, rawOutput.ToArray());

 

                 // IBufferWriter

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                 ctx.WriteUInt32((uint) value);

                 ctx.Flush();

@@ -77,7 +77,7 @@
                 Assert.AreEqual(data, rawOutput.ToArray());

 

                 // IBufferWriter

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                 ctx.WriteUInt64(value);

                 ctx.Flush();

@@ -100,7 +100,7 @@
                     output.Flush();

                     Assert.AreEqual(data, rawOutput.ToArray());

 

-                    var bufferWriter = new ArrayBufferWriter<byte>();

+                    var bufferWriter = new TestArrayBufferWriter<byte>();

                     bufferWriter.MaxGrowBy = bufferSize;

                     WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                     ctx.WriteUInt32((uint) value);

@@ -115,7 +115,7 @@
                     output.Flush();

                     Assert.AreEqual(data, rawOutput.ToArray());

 

-                    var bufferWriter = new ArrayBufferWriter<byte>();

+                    var bufferWriter = new TestArrayBufferWriter<byte>();

                     bufferWriter.MaxGrowBy = bufferSize;

                     WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                     ctx.WriteUInt64(value);

@@ -174,7 +174,7 @@
                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

 

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                 ctx.WriteFixed32(value);

                 ctx.Flush();

@@ -190,7 +190,7 @@
                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

 

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 bufferWriter.MaxGrowBy = bufferSize;

                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                 ctx.WriteFixed32(value);

@@ -212,7 +212,7 @@
                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

 

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                 ctx.WriteFixed64(value);

                 ctx.Flush();

@@ -228,7 +228,7 @@
                 output.Flush();

                 Assert.AreEqual(data, rawOutput.ToArray());

 

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 bufferWriter.MaxGrowBy = blockSize;

                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);

                 ctx.WriteFixed64(value);

@@ -270,7 +270,7 @@
                 output.Flush();

                 Assert.AreEqual(rawBytes, rawOutput.ToArray());

 

-                var bufferWriter = new ArrayBufferWriter<byte>();

+                var bufferWriter = new TestArrayBufferWriter<byte>();

                 bufferWriter.MaxGrowBy = blockSize;

                 message.WriteTo(bufferWriter);

                 Assert.AreEqual(rawBytes, bufferWriter.WrittenSpan.ToArray()); 

@@ -292,7 +292,7 @@
             output.Flush();

             byte[] expectedBytes2 = expectedOutput.ToArray();

 

-            var bufferWriter = new ArrayBufferWriter<byte>();

+            var bufferWriter = new TestArrayBufferWriter<byte>();

             WriteContext.Initialize(bufferWriter, out WriteContext ctx);

             ctx.WriteMessage(message);

             ctx.Flush();

@@ -519,7 +519,21 @@
         }

 

         [Test]

-        public void WriteStringsOfDifferentSizes()

+        public void WriteString_AsciiSmall_MaxUtf8SizeExceedsBuffer()

+        {

+            var buffer = new byte[5];

+            var output = new CodedOutputStream(buffer);

+            output.WriteString("ABC");

+

+            output.Flush();

+

+            // Verify written content

+            var input = new CodedInputStream(buffer);

+            Assert.AreEqual("ABC", input.ReadString());

+        }

+

+        [Test]

+        public void WriteStringsOfDifferentSizes_Ascii()

         {

             for (int i = 1; i <= 1024; i++)

             {

@@ -540,5 +554,30 @@
                 Assert.AreEqual(s, input.ReadString());

             }

         }

+

+        [Test]

+        public void WriteStringsOfDifferentSizes_Unicode()

+        {

+            for (int i = 1; i <= 1024; i++)

+            {

+                var buffer = new byte[4096];

+                var output = new CodedOutputStream(buffer);

+                var sb = new StringBuilder();

+                for (int j = 0; j < i; j++)

+                {

+                    char c = (char)((j % 10) + 10112);

+                    sb.Append(c.ToString()); // incrementing unicode numbers, repeating

+                }

+                var s = sb.ToString();

+                output.WriteString(s);

+

+                output.Flush();

+

+                // Verify written content

+                var input = new CodedInputStream(buffer);

+

+                Assert.AreEqual(s, input.ReadString());

+            }

+        }

     }

 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
index 7bd3f84..cdfa98e 100644
--- a/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+++ b/csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>net451;netcoreapp2.1</TargetFrameworks>
+    <TargetFrameworks>net451;netcoreapp2.1;net50</TargetFrameworks>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
     <IsPackable>False</IsPackable>
diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
index e170fcc..69c9eb6 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -551,9 +551,13 @@
         }
 
         [Test]
+        // Skip these test cases in .NET 5 because floating point parsing supports bigger values.
+        // These big values won't throw an error in the test.
+#if !NET5_0
         [TestCase("1.7977e308")]
         [TestCase("-1.7977e308")]
         [TestCase("1e309")]
+#endif
         [TestCase("1,0")]
         [TestCase("1.0.0")]
         [TestCase("+1")]
diff --git a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
index df43eff..0cbc0a4 100644
--- a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
@@ -199,8 +199,12 @@
         [TestCase("1e-")]
         [TestCase("--")]
         [TestCase("--1")]
+        // Skip these test cases in .NET 5 because floating point parsing supports bigger values.
+        // These big values won't throw an error in the test.
+#if !NET5_0
         [TestCase("-1.7977e308")]
         [TestCase("1.7977e308")]
+#endif
         public void InvalidNumberValue(string json)
         {
             AssertThrowsAfter(json);
diff --git a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
index da7b4a8..22adcaa 100644
--- a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
+++ b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
@@ -141,7 +141,7 @@
             };
             var exception = Assert.Throws<InvalidProtocolBufferException>(() =>
             {
-                WriteContext.Initialize(new ArrayBufferWriter<byte>(), out WriteContext writeCtx);
+                WriteContext.Initialize(new TestArrayBufferWriter<byte>(), out WriteContext writeCtx);
                 ((IBufferMessage)message).InternalWriteTo(ref writeCtx);
             });
             Assert.AreEqual($"Message {typeof(LegacyGeneratedCodeMessageA).Name} doesn't provide the generated method that enables WriteContext-based serialization. You might need to regenerate the generated protobuf code.", exception.Message);
diff --git a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
index 36a2f02..65d2fe0 100644
--- a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
+++ b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
@@ -83,7 +83,7 @@
             var bytes = message.ToByteArray();
 
             // also serialize using IBufferWriter and check it leads to the same data
-            var bufferWriter = new ArrayBufferWriter<byte>();
+            var bufferWriter = new TestArrayBufferWriter<byte>();
             message.WriteTo(bufferWriter);
             Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray(), "Both serialization approaches need to result in the same data.");
 
@@ -112,7 +112,7 @@
             Assert.AreEqual(message.CalculateSize(), bytes.Length);
 
             // serialize using IBufferWriter and check it leads to the same output
-            var bufferWriter = new ArrayBufferWriter<byte>();
+            var bufferWriter = new TestArrayBufferWriter<byte>();
             message.WriteTo(bufferWriter);
             Assert.AreEqual(bytes, bufferWriter.WrittenSpan.ToArray());
 
@@ -124,7 +124,7 @@
             // test for different IBufferWriter.GetSpan() segment sizes
             for (int blockSize = 1; blockSize < 256; blockSize *= 2)
             {
-                var segmentedBufferWriter = new ArrayBufferWriter<byte>();
+                var segmentedBufferWriter = new TestArrayBufferWriter<byte>();
                 segmentedBufferWriter.MaxGrowBy = blockSize;
                 message.WriteTo(segmentedBufferWriter);
                 Assert.AreEqual(bytes, segmentedBufferWriter.WrittenSpan.ToArray());
diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb
index 1569c1e..42ecd3a 100644
--- a/csharp/src/Google.Protobuf.Test/testprotos.pb
+++ b/csharp/src/Google.Protobuf.Test/testprotos.pb
Binary files differ
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index e5aa0b4..1a5f342 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <Description>C# runtime library for Protocol Buffers - Google's data interchange format.</Description>
@@ -8,7 +8,7 @@
     <!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
     <LangVersion>7.2</LangVersion>
     <Authors>Google Inc.</Authors>
-    <TargetFrameworks>netstandard1.1;netstandard2.0;net45</TargetFrameworks>
+    <TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
@@ -27,15 +27,23 @@
     <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING</DefineConstants>
   </PropertyGroup>
 
+  <PropertyGroup Condition=" '$(TargetFramework)' == 'net50' ">
+    <DefineConstants>$(DefineConstants);GOOGLE_PROTOBUF_SUPPORT_FAST_STRING;GOOGLE_PROTOBUF_SIMD</DefineConstants>
+  </PropertyGroup>
+
   <ItemGroup>
-    <PackageReference Include="System.Memory" Version="4.5.3"/>
     <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0"/>
     <!-- Needed for the net45 build to work on Unix. See https://github.com/dotnet/designs/pull/33 -->
     <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0"/>
   </ItemGroup>
 
-  <!-- Needed for netcoreapp2.1 to work correctly. .NET is not able to load the assembly without this -->
+  <ItemGroup Condition=" '$(TargetFramework)' == 'net45' OR '$(TargetFramework)' == 'netstandard1.1' ">
+    <PackageReference Include="System.Memory" Version="4.5.3"/>
+  </ItemGroup>
+
   <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
+    <PackageReference Include="System.Memory" Version="4.5.3"/>
+    <!-- Needed for netcoreapp2.1 to work correctly. .NET is not able to load the assembly without this -->
     <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.2"/>
   </ItemGroup>
 
diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
index 0a1f4a7..a1ad559 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
@@ -107,57 +107,58 @@
             "eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
             "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w",
             "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf",
-            "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECci8gEKDk1lc3NhZ2VPcHRpb25z",
+            "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECcihAIKDk1lc3NhZ2VPcHRpb25z",
             "EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u",
             "b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ",
             "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS",
             "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
-            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAgQCUoECAkQ",
-            "CiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMuZ29vZ2xlLnBy",
-            "b3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4KBnBhY2tlZBgC",
-            "IAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29nbGUucHJvdG9idWYuRmllbGRP",
-            "cHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMKBGxhenkYBSABKAg6BWZhbHNl",
-            "EhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhMKBHdlYWsYCiABKAg6BWZh",
-            "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w",
-            "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIi8KBUNUeXBlEgoKBlNUUklO",
-            "RxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElFQ0UQAiI1CgZKU1R5cGUSDQoJ",
-            "SlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAESDQoJSlNfTlVNQkVSEAIqCQjo",
-            "BxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlvbnMSQwoUdW5pbnRlcnByZXRl",
-            "ZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0",
-            "ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51bU9wdGlvbnMSEwoLYWxsb3df",
-            "YWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USQwoUdW5p",
-            "bnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVu",
-            "aW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAUQBiJ9ChBFbnVtVmFs",
-            "dWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMKFHVuaW50",
-            "ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5Vbmlu",
-            "dGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9wdGlvbnMS",
-            "GQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9v",
-            "cHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRP",
-            "cHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9kT3B0aW9ucxIZCgpkZXByZWNh",
-            "dGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90ZW5jeV9sZXZlbBgiIAEoDjIv",
-            "Lmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zLklkZW1wb3RlbmN5TGV2",
-            "ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoUdW5pbnRlcnByZXRlZF9vcHRp",
-            "b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
-            "b24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJREVNUE9URU5DWV9VTktOT1dO",
-            "EAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoKSURFTVBPVEVOVBACKgkI6AcQ",
-            "gICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgCIAMoCzIt",
-            "Lmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5hbWVQYXJ0",
-            "EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVfaW50X3Zh",
-            "bHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIUCgxkb3Vi",
-            "bGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcKD2FnZ3Jl",
-            "Z2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3BhcnQYASAC",
-            "KAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2RlSW5mbxI6",
-            "Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2Rl",
-            "SW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMoBUICEAES",
-            "EAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgDIAEoCRIZ",
-            "ChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2RldGFjaGVk",
-            "X2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0ZWRDb2RlSW5mbxJBCgphbm5v",
-            "dGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3RvYnVmLkdlbmVyYXRlZENvZGVJ",
-            "bmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlvbhIQCgRwYXRoGAEgAygFQgIQ",
-            "ARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgViZWdpbhgDIAEoBRILCgNlbmQY",
-            "BCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRvclByb3Rv",
-            "c0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90b2J1Zi90eXBlcy9kZXNjcmlw",
-            "dG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJvdG9idWYuUmVmbGVjdGlvbg=="));
+            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAQQBUoECAUQ",
+            "BkoECAYQB0oECAgQCUoECAkQCiKeAwoMRmllbGRPcHRpb25zEjoKBWN0eXBl",
+            "GAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToG",
+            "U1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29n",
+            "bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMK",
+            "BGxhenkYBSABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNl",
+            "EhMKBHdlYWsYCiABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u",
+            "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u",
+            "Ii8KBUNUeXBlEgoKBlNUUklORxAAEggKBENPUkQQARIQCgxTVFJJTkdfUElF",
+            "Q0UQAiI1CgZKU1R5cGUSDQoJSlNfTk9STUFMEAASDQoJSlNfU1RSSU5HEAES",
+            "DQoJSlNfTlVNQkVSEAIqCQjoBxCAgICAAkoECAQQBSJeCgxPbmVvZk9wdGlv",
+            "bnMSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy",
+            "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKTAQoLRW51",
+            "bU9wdGlvbnMSEwoLYWxsb3dfYWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgD",
+            "IAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQu",
+            "Z29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICA",
+            "AkoECAUQBiJ9ChBFbnVtVmFsdWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASAB",
+            "KAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdv",
+            "b2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi",
+            "ewoOU2VydmljZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2US",
+            "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
+            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiKtAgoNTWV0aG9k",
+            "T3B0aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJfChFpZGVtcG90",
+            "ZW5jeV9sZXZlbBgiIAEoDjIvLmdvb2dsZS5wcm90b2J1Zi5NZXRob2RPcHRp",
+            "b25zLklkZW1wb3RlbmN5TGV2ZWw6E0lERU1QT1RFTkNZX1VOS05PV04SQwoU",
+            "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
+            "LlVuaW50ZXJwcmV0ZWRPcHRpb24iUAoQSWRlbXBvdGVuY3lMZXZlbBIXChNJ",
+            "REVNUE9URU5DWV9VTktOT1dOEAASEwoPTk9fU0lERV9FRkZFQ1RTEAESDgoK",
+            "SURFTVBPVEVOVBACKgkI6AcQgICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRp",
+            "b24SOwoEbmFtZRgCIAMoCzItLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJl",
+            "dGVkT3B0aW9uLk5hbWVQYXJ0EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkS",
+            "GgoScG9zaXRpdmVfaW50X3ZhbHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92",
+            "YWx1ZRgFIAEoAxIUCgxkb3VibGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3Zh",
+            "bHVlGAcgASgMEhcKD2FnZ3JlZ2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFy",
+            "dBIRCgluYW1lX3BhcnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUB",
+            "Cg5Tb3VyY2VDb2RlSW5mbxI6Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5w",
+            "cm90b2J1Zi5Tb3VyY2VDb2RlSW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24S",
+            "EAoEcGF0aBgBIAMoBUICEAESEAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGlu",
+            "Z19jb21tZW50cxgDIAEoCRIZChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIh",
+            "ChlsZWFkaW5nX2RldGFjaGVkX2NvbW1lbnRzGAYgAygJIqcBChFHZW5lcmF0",
+            "ZWRDb2RlSW5mbxJBCgphbm5vdGF0aW9uGAEgAygLMi0uZ29vZ2xlLnByb3Rv",
+            "YnVmLkdlbmVyYXRlZENvZGVJbmZvLkFubm90YXRpb24aTwoKQW5ub3RhdGlv",
+            "bhIQCgRwYXRoGAEgAygFQgIQARITCgtzb3VyY2VfZmlsZRgCIAEoCRINCgVi",
+            "ZWdpbhgDIAEoBRILCgNlbmQYBCABKAVCfgoTY29tLmdvb2dsZS5wcm90b2J1",
+            "ZkIQRGVzY3JpcHRvclByb3Rvc0gBWi1nb29nbGUuZ29sYW5nLm9yZy9wcm90",
+            "b2J1Zi90eXBlcy9kZXNjcmlwdG9ycGL4AQGiAgNHUEKqAhpHb29nbGUuUHJv",
+            "dG9idWYuUmVmbGVjdGlvbg=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
@@ -4795,11 +4796,11 @@
 
     private string javaOuterClassname_;
     /// <summary>
-    /// If set, all the classes from the .proto file are wrapped in a single
-    /// outer class with the given name.  This applies to both Proto1
-    /// (equivalent to the old "--one_java_file" option) and Proto2 (where
-    /// a .proto always translates to a single class, but you may want to
-    /// explicitly choose the class name).
+    /// Controls the name of the wrapper Java class generated for the .proto file.
+    /// That class will always contain the .proto file's getDescriptor() method as
+    /// well as any top-level extensions defined in the .proto file.
+    /// If java_multiple_files is disabled, then all the other classes from the
+    /// .proto file will be nested inside the single wrapper outer class.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public string JavaOuterClassname {
@@ -4825,10 +4826,10 @@
 
     private bool javaMultipleFiles_;
     /// <summary>
-    /// If set true, then the Java code generator will generate a separate .java
+    /// If enabled, then the Java code generator will generate a separate .java
     /// file for each top-level message, enum, and service defined in the .proto
-    /// file.  Thus, these types will *not* be nested inside the outer class
-    /// named by java_outer_classname.  However, the outer class will still be
+    /// file.  Thus, these types will *not* be nested inside the wrapper class
+    /// named by java_outer_classname.  However, the wrapper class will still be
     /// generated to contain the file's getDescriptor() method as well as any
     /// top-level extensions defined in the file.
     /// </summary>
diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs
index cf8fc7b..8beefc5 100644
--- a/csharp/src/Google.Protobuf/WritingPrimitives.cs
+++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs
@@ -32,8 +32,14 @@
 
 using System;
 using System.Buffers.Binary;
+using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
+#if GOOGLE_PROTOBUF_SIMD
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.Arm;
+using System.Runtime.Intrinsics.X86;
+#endif
 using System.Security;
 using System.Text;
 
@@ -45,8 +51,11 @@
     [SecuritySafeCritical]
     internal static class WritingPrimitives
     {
-        // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
-        internal static readonly Encoding Utf8Encoding = Encoding.UTF8;
+#if NET5_0
+        internal static Encoding Utf8Encoding => Encoding.UTF8; // allows JIT to devirtualize
+#else
+        internal static readonly Encoding Utf8Encoding = Encoding.UTF8; // "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
+#endif
 
         #region Writing of values (not including tags)
 
@@ -186,11 +195,7 @@
             {
                 if (length == value.Length) // Must be all ASCII...
                 {
-                    for (int i = 0; i < length; i++)
-                    {
-                        buffer[state.position + i] = (byte)value[i];
-                    }
-                    state.position += length;
+                    WriteAsciiStringToBuffer(buffer, ref state, value, length);
                 }
                 else
                 {
@@ -208,6 +213,104 @@
             }
         }
 
+        // Calling this method with non-ASCII content will break.
+        // Content must be verified to be all ASCII before using this method.
+        private static void WriteAsciiStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value, int length)
+        {
+            ref char sourceChars = ref MemoryMarshal.GetReference(value.AsSpan());
+            ref byte destinationBytes = ref MemoryMarshal.GetReference(buffer.Slice(state.position));
+
+            int currentIndex = 0;
+            // If 64bit, process 4 chars at a time.
+            // The logic inside this check will be elided by JIT in 32bit programs.
+            if (IntPtr.Size == 8)
+            {
+                // Need at least 4 chars available to use this optimization. 
+                if (length >= 4)
+                {
+                    ref byte sourceBytes = ref Unsafe.As<char, byte>(ref sourceChars);
+
+                    // Process 4 chars at a time until there are less than 4 remaining.
+                    // We already know all characters are ASCII so there is no need to validate the source.
+                    int lastIndexWhereCanReadFourChars = value.Length - 4;
+                    do
+                    {
+                        NarrowFourUtf16CharsToAsciiAndWriteToBuffer(
+                            ref Unsafe.AddByteOffset(ref destinationBytes, (IntPtr)currentIndex),
+                            Unsafe.ReadUnaligned<ulong>(ref Unsafe.AddByteOffset(ref sourceBytes, (IntPtr)(currentIndex * 2))));
+
+                    } while ((currentIndex += 4) <= lastIndexWhereCanReadFourChars);
+                }
+            }
+
+            // Process any remaining, 1 char at a time.
+            // Avoid bounds checking with ref + Unsafe
+            for (; currentIndex < length; currentIndex++)
+            {
+                Unsafe.AddByteOffset(ref destinationBytes, (IntPtr)currentIndex) = (byte)Unsafe.AddByteOffset(ref sourceChars, (IntPtr)(currentIndex * 2));
+            }
+
+            state.position += length;
+        }
+
+        // Copied with permission from https://github.com/dotnet/runtime/blob/1cdafd27e4afd2c916af5df949c13f8b373c4335/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIUtility.cs#L1119-L1171
+        //
+        /// <summary>
+        /// Given a QWORD which represents a buffer of 4 ASCII chars in machine-endian order,
+        /// narrows each WORD to a BYTE, then writes the 4-byte result to the output buffer
+        /// also in machine-endian order.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputBuffer, ulong value)
+        {
+#if GOOGLE_PROTOBUF_SIMD
+            if (Sse2.X64.IsSupported)
+            {
+                // Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
+                // [ b0 b1 b2 b3 b0 b1 b2 b3 ], then writes 4 bytes (32 bits) to the destination.
+
+                Vector128<short> vecWide = Sse2.X64.ConvertScalarToVector128UInt64(value).AsInt16();
+                Vector128<uint> vecNarrow = Sse2.PackUnsignedSaturate(vecWide, vecWide).AsUInt32();
+                Unsafe.WriteUnaligned<uint>(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow));
+            }
+            else if (AdvSimd.IsSupported)
+            {
+                // Narrows a vector of words [ w0 w1 w2 w3 ] to a vector of bytes
+                // [ b0 b1 b2 b3 * * * * ], then writes 4 bytes (32 bits) to the destination.
+
+                Vector128<short> vecWide = Vector128.CreateScalarUnsafe(value).AsInt16();
+                Vector64<byte> lower = AdvSimd.ExtractNarrowingSaturateUnsignedLower(vecWide);
+                Unsafe.WriteUnaligned<uint>(ref outputBuffer, lower.AsUInt32().ToScalar());
+            }
+            else
+#endif
+            {
+                // Fallback to non-SIMD approach when SIMD is not available.
+                // This could happen either because the APIs are not available, or hardware doesn't support it.
+                // Processing 4 chars at a time in this fallback is still faster than casting one char at a time.
+                if (BitConverter.IsLittleEndian)
+                {
+                    outputBuffer = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 1) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 2) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 3) = (byte)value;
+                }
+                else
+                {
+                    Unsafe.Add(ref outputBuffer, 3) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 2) = (byte)value;
+                    value >>= 16;
+                    Unsafe.Add(ref outputBuffer, 1) = (byte)value;
+                    value >>= 16;
+                    outputBuffer = (byte)value;
+                }
+            }
+        }
+
         private static int WriteStringToBuffer(Span<byte> buffer, ref WriterInternalState state, string value)
         {
 #if NETSTANDARD1_1
diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md
index 73f21a3..ae8b369 100644
--- a/docs/implementing_proto3_presence.md
+++ b/docs/implementing_proto3_presence.md
@@ -261,7 +261,7 @@
 Old:
 
 ```c++
-bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) {
+bool FieldIsInOneof(const google::protobuf::FieldDescriptor* field) {
   return field->containing_oneof() != nullptr;
 }
 ```
@@ -269,7 +269,7 @@
 New:
 
 ```c++
-bool FieldIsInOneof(const google::protobuf::FielDescriptor* field) {
+bool FieldIsInOneof(const google::protobuf::FieldDescriptor* field) {
   // real_containing_oneof() returns nullptr for synthetic oneofs.
   return field->real_containing_oneof() != nullptr;
 }
diff --git a/docs/jvm_aot.md b/docs/jvm_aot.md
new file mode 100644
index 0000000..4eb682f
--- /dev/null
+++ b/docs/jvm_aot.md
@@ -0,0 +1,18 @@
+# Ahead Of Time (AOT) compilation for the Java Virtual Machine (JVM)"
+
+Ahead Of Time (AOT) compilation build tools such as those provided by [GraalVM's `native-image`](https://www.graalvm.org/reference-manual/native-image/) can require some configuration when using protobuf.
+Protobuf for the JVM uses reflection and some of its target classes are not possible to determine in advance.
+Historically, there were good reasons to use reflection based on APIs that were published effectively requiring them, and this situation is unlikely to change.
+
+[The Lite version of protobuf for the JVM](https://github.com/protocolbuffers/protobuf/blob/master/java/lite.md)
+avoids reflection and may be better suited for use with AOT compilation tooling. This Lite version was originally targeted for use on Android which has similar AOT compilation
+goals as GraalVM's native-image tool.
+
+## GraalVM native-image
+
+This section addresses GraalVM's `native-image` configuration specifically as this AOT compilation tool due to its popularity. The `native-image` tool can be configured
+with respect to: the [Java Native Interface](https://en.wikipedia.org/wiki/Java_Native_Interface) (JNI), http proxying, reflection, and other resources. While these
+considerations can be manually declared as JSON files, we recommend that a JVM application is exercised along with 
+[the assisted configuration agent](https://www.graalvm.org/reference-manual/native-image/BuildConfiguration/#assisted-configuration-of-native-image-builds). The agent
+will generate files that you can then subsequently point at when invoking `native-image`. We recommend that the generated files are retained with a project's source
+code.
diff --git a/docs/options.md b/docs/options.md
index 361216f..79a085e 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -263,8 +263,16 @@
 
 1. Protoc-gen-psql
    * Website: https://github.com/Intrinsec/protoc-gen-psql
-   * Extension: 1091
+   * Extension: 1091-1101
 
 1. Protoc-gen-sanitize
    * Website: https://github.com/Intrinsec/protoc-gen-sanitize
-   * Extension: 1092
+   * Extension: 1102-1106
+
+1. Coach Client Connect (planned release in March 2021)
+   * Website: https://www.coachclientconnect.com
+   * Extension: 1107
+
+1. Kratos API Errors
+   * Website: https://go-kratos.dev
+   * Extension: 1108
diff --git a/docs/third_party.md b/docs/third_party.md
index 7799e30..9d490c0 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -11,6 +11,7 @@
 * Action Script: https://code.google.com/p/protoc-gen-as3/
 * Action Script: https://github.com/matrix3d/JProtoc
 * Action Script: https://github.com/zhongfq/protobuf-as3/
+* Ada: https://github.com/reznikmm/protobuf
 * C: https://github.com/protobuf-c/protobuf-c
 * C: http://koti.kapsi.fi/jpa/nanopb/
 * C: https://github.com/cloudwu/pbc/
@@ -101,7 +102,6 @@
 * Solidity: https://github.com/celer-network/pb3-gen-sol
 * Swift: https://github.com/alexeyxo/protobuf-swift
 * Swift: https://github.com/apple/swift-protobuf/
-* Typescript: https://github.com/y3llowcake/protoc-gen-ts
 * Vala: https://launchpad.net/protobuf-vala
 * Visual Basic: http://code.google.com/p/protobuf-net/
 
diff --git a/global.json b/global.json
index 16f71a7..d29e29a 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
 {
   "sdk": {
-    "version": "3.0.100",
+    "version": "5.0.102",
     "rollForward": "latestMinor"
   }
 }
diff --git a/java/README.md b/java/README.md
index c805089..c343414 100644
--- a/java/README.md
+++ b/java/README.md
@@ -23,7 +23,7 @@
 <dependency>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java</artifactId>
-  <version>3.11.0</version>
+  <version>3.15.3</version>
 </dependency>
 ```
 
@@ -37,7 +37,7 @@
 <dependency>
   <groupId>com.google.protobuf</groupId>
   <artifactId>protobuf-java-util</artifactId>
-  <version>3.11.0</version>
+  <version>3.15.3</version>
 </dependency>
 ```
 
diff --git a/java/core/BUILD b/java/core/BUILD
index e7778f9..fa074c0 100644
--- a/java/core/BUILD
+++ b/java/core/BUILD
@@ -85,6 +85,7 @@
     "src/main/java/com/google/protobuf/UnknownFieldSetLite.java",
     "src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java",
     "src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java",
+    "src/main/java/com/google/protobuf/UnsafeByteOperations.java",
     "src/main/java/com/google/protobuf/UnsafeUtil.java",
     "src/main/java/com/google/protobuf/Utf8.java",
     "src/main/java/com/google/protobuf/WireFormat.java",
diff --git a/java/core/src/main/java/com/google/protobuf/ByteString.java b/java/core/src/main/java/com/google/protobuf/ByteString.java
index 17b7c98..74c9a71 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -1043,8 +1043,10 @@
     }
 
     /**
-     * Creates a byte string. Its size is the current size of this output stream and its output has
-     * been copied to it.
+     * Creates a byte string with the size and contents of this output stream. This does not create
+     * a new copy of the underlying bytes. If the stream size grows dynamically, the runtime is
+     * O(log n) in respect to the number of bytes written to the {@link Output}. If the stream size
+     * stays within the initial capacity, the runtime is O(1).
      *
      * @return the current contents of this output stream, as a byte string.
      */
diff --git a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index ff81e00..37b986d 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -1185,6 +1185,9 @@
         throw InvalidProtocolBufferException.negativeSize();
       }
       byteLimit += getTotalBytesRead();
+      if (byteLimit < 0) {
+        throw InvalidProtocolBufferException.parseFailure();
+      }
       final int oldLimit = currentLimit;
       if (byteLimit > oldLimit) {
         throw InvalidProtocolBufferException.truncatedMessage();
@@ -2055,6 +2058,44 @@
       totalBytesRetired = 0;
     }
 
+    /*
+     * The following wrapper methods exist so that InvalidProtocolBufferExceptions thrown by the
+     * InputStream can be differentiated from ones thrown by CodedInputStream itself. Each call to
+     * an InputStream method that can throw IOException must be wrapped like this. We do this
+     * because we sometimes need to modify IPBE instances after they are thrown far away from where
+     * they are thrown (ex. to add unfinished messages) and we use this signal elsewhere in the
+     * exception catch chain to know when to perform these operations directly or to wrap the
+     * exception in their own IPBE so the extra information can be communicated without trampling
+     * downstream information.
+     */
+    private static int read(InputStream input, byte[] data, int offset, int length)
+        throws IOException {
+      try {
+        return input.read(data, offset, length);
+      } catch (InvalidProtocolBufferException e) {
+        e.setThrownFromInputStream();
+        throw e;
+      }
+    }
+
+    private static long skip(InputStream input, long length) throws IOException {
+      try {
+        return input.skip(length);
+      } catch (InvalidProtocolBufferException e) {
+        e.setThrownFromInputStream();
+        throw e;
+      }
+    }
+
+    private static int available(InputStream input) throws IOException {
+      try {
+        return input.available();
+      } catch (InvalidProtocolBufferException e) {
+        e.setThrownFromInputStream();
+        throw e;
+      }
+    }
+
     @Override
     public int readTag() throws IOException {
       if (isAtEnd()) {
@@ -2783,7 +2824,8 @@
 
       // Here we should refill the buffer as many bytes as possible.
       int bytesRead =
-          input.read(
+          read(
+              input,
               buffer,
               bufferSize,
               Math.min(
@@ -2905,7 +2947,7 @@
       // Determine the number of bytes we need to read from the input stream.
       int sizeLeft = size - bufferedBytes;
       // TODO(nathanmittler): Consider using a value larger than DEFAULT_BUFFER_SIZE.
-      if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= input.available()) {
+      if (sizeLeft < DEFAULT_BUFFER_SIZE || sizeLeft <= available(input)) {
         // Either the bytes we need are known to be available, or the required buffer is
         // within an allowed threshold - go ahead and allocate the buffer now.
         final byte[] bytes = new byte[size];
@@ -2919,7 +2961,7 @@
         // Fill the remaining bytes from the input stream.
         int tempPos = bufferedBytes;
         while (tempPos < bytes.length) {
-          int n = input.read(bytes, tempPos, size - tempPos);
+          int n = read(input, bytes, tempPos, size - tempPos);
           if (n == -1) {
             throw InvalidProtocolBufferException.truncatedMessage();
           }
@@ -3047,7 +3089,7 @@
         try {
           while (totalSkipped < size) {
             int toSkip = size - totalSkipped;
-            long skipped = input.skip(toSkip);
+            long skipped = skip(input, toSkip);
             if (skipped < 0 || skipped > toSkip) {
               throw new IllegalStateException(
                   input.getClass()
@@ -3484,9 +3526,25 @@
           return ByteString.wrap(bytes);
         }
       } else if (size > 0 && size <= remaining()) {
-        byte[] temp = new byte[size];
-        readRawBytesTo(temp, 0, size);
-        return ByteString.wrap(temp);
+        if (immutable && enableAliasing) {
+          ArrayList<ByteString> byteStrings = new ArrayList<>();
+          int l = size;
+          while (l > 0) {
+            if (currentRemaining() == 0) {
+              getNextByteBuffer();
+            }
+            int bytesToCopy = Math.min(l, (int) currentRemaining());
+            int idx = (int) (currentByteBufferPos - currentAddress);
+            byteStrings.add(ByteString.wrap(slice(idx, idx + bytesToCopy)));
+            l -= bytesToCopy;
+            currentByteBufferPos += bytesToCopy;
+          }
+          return ByteString.copyFrom(byteStrings);
+        } else {
+          byte[] temp = new byte[size];
+          readRawBytesTo(temp, 0, size);
+          return ByteString.wrap(temp);
+        }
       }
 
       if (size == 0) {
diff --git a/java/core/src/main/java/com/google/protobuf/FieldSet.java b/java/core/src/main/java/com/google/protobuf/FieldSet.java
index 1d8592f..f64b50a 100644
--- a/java/core/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -282,7 +282,7 @@
 
       // Wrap the contents in a new list so that the caller cannot change
       // the list's contents after setting it.
-      final List newList = new ArrayList();
+      final List newList = new ArrayList<>();
       newList.addAll((List) value);
       for (final Object element : newList) {
         verifyType(descriptor, element);
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
index 5e3ee0f..7db8f32 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -1537,11 +1537,16 @@
       Schema<T> schema = Protobuf.getInstance().schemaFor(result);
       schema.mergeFrom(result, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
       schema.makeImmutable(result);
+    } catch (InvalidProtocolBufferException e) {
+      if (e.getThrownFromInputStream()) {
+        e = new InvalidProtocolBufferException(e);
+      }
+      throw e.setUnfinishedMessage(result);
     } catch (IOException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
       }
-      throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
+      throw new InvalidProtocolBufferException(e).setUnfinishedMessage(result);
     } catch (RuntimeException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
@@ -1565,11 +1570,16 @@
       if (result.memoizedHashCode != 0) {
         throw new RuntimeException();
       }
+    } catch (InvalidProtocolBufferException e) {
+      if (e.getThrownFromInputStream()) {
+        e = new InvalidProtocolBufferException(e);
+      }
+      throw e.setUnfinishedMessage(result);
     } catch (IOException e) {
       if (e.getCause() instanceof InvalidProtocolBufferException) {
         throw (InvalidProtocolBufferException) e.getCause();
       }
-      throw new InvalidProtocolBufferException(e.getMessage()).setUnfinishedMessage(result);
+      throw new InvalidProtocolBufferException(e).setUnfinishedMessage(result);
     } catch (IndexOutOfBoundsException e) {
       throw InvalidProtocolBufferException.truncatedMessage().setUnfinishedMessage(result);
     }
@@ -1727,8 +1737,13 @@
         return null;
       }
       size = CodedInputStream.readRawVarint32(firstByte, input);
+    } catch (InvalidProtocolBufferException e) {
+      if (e.getThrownFromInputStream()) {
+        e = new InvalidProtocolBufferException(e);
+      }
+      throw e;
     } catch (IOException e) {
-      throw new InvalidProtocolBufferException(e.getMessage());
+      throw new InvalidProtocolBufferException(e);
     }
     InputStream limitedInput = new LimitedInputStream(input, size);
     CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput);
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 22f31bb..4b43033 100644
--- a/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
+++ b/java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
@@ -41,6 +41,7 @@
 public class InvalidProtocolBufferException extends IOException {
   private static final long serialVersionUID = -1616151763072450476L;
   private MessageLite unfinishedMessage = null;
+  private boolean wasThrownFromInputStream;
 
   public InvalidProtocolBufferException(final String description) {
     super(description);
@@ -72,6 +73,28 @@
     return unfinishedMessage;
   }
 
+  /** Set by CodedInputStream */
+  void setThrownFromInputStream() {
+    /* 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
+     * 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
+     * and cause a write.
+     */
+    wasThrownFromInputStream = true;
+  }
+
+  /**
+   * Allows code catching IOException from CodedInputStream to tell whether this instance was thrown
+   * by a delegate InputStream, rather than directly by a parse failure.
+   */
+  boolean getThrownFromInputStream() {
+    return wasThrownFromInputStream;
+  }
+
   /**
    * Unwraps the underlying {@link IOException} if this exception was caused by an I/O problem.
    * Otherwise, returns {@code this}.
diff --git a/java/core/src/main/java/com/google/protobuf/RopeByteString.java b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
index cc6e044..f584164 100644
--- a/java/core/src/main/java/com/google/protobuf/RopeByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/RopeByteString.java
@@ -603,7 +603,12 @@
 
   @Override
   public CodedInputStream newCodedInput() {
-    return CodedInputStream.newInstance(new RopeInputStream());
+    // Passing along direct references to internal ByteBuffers can support more efficient parsing
+    // via aliasing in CodedInputStream for users who wish to use it.
+    //
+    // Otherwise we force data copies, both in copying as an input stream and in buffering in the
+    // CodedInputSteam.
+    return CodedInputStream.newInstance(asReadOnlyByteBufferList(), /* bufferIsImmutable= */ true);
   }
 
   @Override
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
index 0acf22e..dd459f0 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeUtil.java
@@ -346,7 +346,7 @@
     return MEMORY_ACCESSOR.supportsUnsafeByteBufferOperations();
   }
 
-  private static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
+  static boolean determineAndroidSupportByAddressSize(Class<?> addressClass) {
     if (!Android.isOnAndroidDevice()) {
       return false;
     }
diff --git a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
index cc979ac..4bc8d10 100644
--- a/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java
@@ -283,7 +283,7 @@
     Message.Builder abstractMessageBuilder =
         new AbstractMessageWrapper.Builder(TestRequiredForeign.newBuilder());
     // mergeFrom() should not throw initialization error.
-    abstractMessageBuilder.mergeFrom(bytes).buildPartial();
+    Message unused1 = abstractMessageBuilder.mergeFrom(bytes).buildPartial();
     try {
       abstractMessageBuilder.mergeFrom(bytes).build();
       fail();
@@ -295,7 +295,7 @@
     Message.Builder dynamicMessageBuilder =
         DynamicMessage.newBuilder(TestRequiredForeign.getDescriptor());
     // mergeFrom() should not throw initialization error.
-    dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
+    Message unused2 = dynamicMessageBuilder.mergeFrom(bytes).buildPartial();
     try {
       dynamicMessageBuilder.mergeFrom(bytes).build();
       fail();
diff --git a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index 532052c..10d156e 100644
--- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -1142,6 +1142,39 @@
     }
   }
 
+  public void testIterableByteBufferInputStreamReadBytesWithAlias() throws Exception {
+    ByteArrayOutputStream byteArrayStream = new ByteArrayOutputStream();
+    CodedOutputStream output = CodedOutputStream.newInstance(byteArrayStream);
+    // A bytes field large enough that won't fit into the default block buffer.
+    // 4.5 is to test the case where the total size of input is not aligned with DEFAULT_BLOCK_SIZE.
+    final int bytesLength = DEFAULT_BLOCK_SIZE * 4 + (DEFAULT_BLOCK_SIZE / 2);
+    byte[] bytes = new byte[bytesLength];
+    for (int i = 0; i < bytesLength; i++) {
+      bytes[i] = (byte) (i % 256);
+    }
+    output.writeByteArrayNoTag(bytes);
+    output.flush();
+
+    // Input data is split into multiple ByteBuffers so that a single bytes spans across them.
+    // CodedInputStream with aliasing will decode it as a consequent rope by wrapping ByteBuffers.
+    byte[] data = byteArrayStream.toByteArray();
+    ArrayList<ByteBuffer> input = new ArrayList<>();
+    for (int i = 0; i < data.length; i += DEFAULT_BLOCK_SIZE) {
+      int rl = Math.min(DEFAULT_BLOCK_SIZE, data.length - i);
+      ByteBuffer rb = ByteBuffer.allocateDirect(rl);
+      rb.put(data, i, rl);
+      rb.flip();
+      input.add(rb);
+    }
+    final CodedInputStream inputStream = CodedInputStream.newInstance(input, true);
+    inputStream.enableAliasing(true);
+
+    ByteString result = inputStream.readBytes();
+    for (int i = 0; i < bytesLength; i++) {
+      assertEquals((byte) (i % 256), result.byteAt(i));
+    }
+  }
+
   public void testCompatibleTypes() throws Exception {
     long data = 0x100000000L;
     Int64Message message = Int64Message.newBuilder().setData(data).build();
@@ -1196,7 +1229,7 @@
       // Expected
     }
   }
-  
+
   public void testMaliciousInputStream() throws Exception {
     ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     CodedOutputStream codedOutputStream = CodedOutputStream.newInstance(outputStream);
@@ -1210,17 +1243,17 @@
         return super.read(b, off, len);
       }
     };
-    
+
     // test ByteString
-    
+
     CodedInputStream codedInputStream = CodedInputStream.newInstance(inputStream, 1);
     ByteString byteString = codedInputStream.readBytes();
     assertEquals(0x0, byteString.byteAt(0));
     maliciousCapture.get(1)[0] = 0x9;
     assertEquals(0x0, byteString.byteAt(0));
-    
+
     // test ByteBuffer
-    
+
     inputStream.reset();
     maliciousCapture.clear();
     codedInputStream = CodedInputStream.newInstance(inputStream, 1);
@@ -1228,10 +1261,10 @@
     assertEquals(0x0, byteBuffer.get(0));
     maliciousCapture.get(1)[0] = 0x9;
     assertEquals(0x0, byteBuffer.get(0));
-    
+
 
     // test byte[]
-    
+
     inputStream.reset();
     maliciousCapture.clear();
     codedInputStream = CodedInputStream.newInstance(inputStream, 1);
@@ -1241,7 +1274,7 @@
     assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
 
     // test rawBytes
-    
+
     inputStream.reset();
     maliciousCapture.clear();
     codedInputStream = CodedInputStream.newInstance(inputStream, 1);
@@ -1251,4 +1284,33 @@
     maliciousCapture.get(1)[0] = 0x9;
     assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
   }
+
+  public void testInvalidInputYieldsInvalidProtocolBufferException_readTag() throws Exception {
+    byte[] input = new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x77};
+    CodedInputStream inputStream = CodedInputStream.newInstance(input);
+    try {
+      inputStream.readTag();
+      int size = inputStream.readRawVarint32();
+      inputStream.pushLimit(size);
+      inputStream.readTag();
+      fail();
+    } catch (InvalidProtocolBufferException ex) {
+      // Expected.
+    }
+  }
+
+  public void testInvalidInputYieldsInvalidProtocolBufferException_readBytes() throws Exception {
+    byte[] input =
+        new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x67, 0x1a, 0x1a};
+    CodedInputStream inputStream = CodedInputStream.newInstance(input);
+    try {
+      inputStream.readTag();
+      int size = inputStream.readRawVarint32();
+      inputStream.pushLimit(size);
+      inputStream.readBytes();
+      fail();
+    } catch (InvalidProtocolBufferException ex) {
+      // Expected.
+    }
+  }
 }
diff --git a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
index fe37ea8..cd40ffa 100644
--- a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -69,7 +69,7 @@
     Message.Builder builder = DynamicMessage.newBuilder(TestAllTypes.getDescriptor());
     Message firstMessage = builder.build();
     // double build()
-    builder.build();
+    Message unused = builder.build();
     // clear() after build()
     builder.clear();
     // setters after build()
diff --git a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
index 9261a36..840e13e 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -76,6 +76,7 @@
  *
  * @author kenton@google.com Kenton Varda
  */
+@SuppressWarnings({"ProtoBuilderReturnValueIgnored", "ReturnValueIgnored"})
 public class GeneratedMessageTest extends TestCase {
   TestUtil.ReflectionTester reflectionTester =
       new TestUtil.ReflectionTester(TestAllTypes.getDescriptor(), null);
diff --git a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
index d2565ca..25c5625 100644
--- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -1163,8 +1163,8 @@
   }
 
   public void testReservedWordsFieldNames() {
-    ReservedAsMapField.newBuilder().build();
-    ReservedAsMapFieldWithEnumValue.newBuilder().build();
+    ReservedAsMapField unused1 = ReservedAsMapField.newBuilder().build();
+    ReservedAsMapFieldWithEnumValue unused2 = ReservedAsMapFieldWithEnumValue.newBuilder().build();
   }
 
   public void testGetMap() {
diff --git a/java/core/src/test/java/com/google/protobuf/MapTest.java b/java/core/src/test/java/com/google/protobuf/MapTest.java
index 2f55328..c3b1fa3 100644
--- a/java/core/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -1294,8 +1294,8 @@
   }
 
   public void testReservedWordsFieldNames() {
-    ReservedAsMapField.newBuilder().build();
-    ReservedAsMapFieldWithEnumValue.newBuilder().build();
+    ReservedAsMapField unused1 = ReservedAsMapField.newBuilder().build();
+    ReservedAsMapFieldWithEnumValue unused2 = ReservedAsMapFieldWithEnumValue.newBuilder().build();
   }
 
   public void testDeterministicSerialziation() throws Exception {
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
index 3d82c5f..08a23ba 100644
--- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -43,8 +43,10 @@
 
   public void testCompilation() {
     // If this compiles, it means the generation was correct.
-    TestBadIdentifiersProto.Deprecated.newBuilder();
-    TestBadIdentifiersProto.Override.newBuilder();
+    TestBadIdentifiersProto.Deprecated unused1 =
+        TestBadIdentifiersProto.Deprecated.newBuilder().build();
+    TestBadIdentifiersProto.Override unused2 =
+        TestBadIdentifiersProto.Override.getDefaultInstance();
   }
 
   public void testGetDescriptor() {
diff --git a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
index 798d7ca..523e23a 100644
--- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java
@@ -45,8 +45,10 @@
 
   public void testCompilation() {
     // If this compiles, it means the generation was correct.
-    TestBadIdentifiersProto.Deprecated.newBuilder();
-    TestBadIdentifiersProto.Override.newBuilder();
+    TestBadIdentifiersProto.Deprecated.Builder builder1 =
+        TestBadIdentifiersProto.Deprecated.newBuilder();
+    TestBadIdentifiersProto.Override.Builder builder2 =
+        TestBadIdentifiersProto.Override.newBuilder();
   }
 
   public void testConflictingFieldNames() throws Exception {
diff --git a/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto b/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
deleted file mode 100644
index d41b7a1..0000000
--- a/java/core/src/test/proto/com/google/protobuf/test_extra_interfaces.proto
+++ /dev/null
@@ -1,56 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Darick Tong (darick@google.com)
-syntax = "proto2";
-
-package protobuf_unittest;
-
-message Proto1 {
-  option experimental_java_message_interface =
-      "com.google.protobuf.ExtraInterfaces.HasBoolValue";
-  option experimental_java_message_interface =
-      "com.google.protobuf.ExtraInterfaces.HasStringValue<Proto1>";
-  option experimental_java_builder_interface =
-      "com.google.protobuf.ExtraInterfaces.HasStringValueBuilder"
-      "<Proto1, Builder>";
-
-  optional string string_value = 1;
-  optional bool bool_value = 2;
-  optional bytes byte_value = 3;
-  optional int32 int_value = 4;
-}
-
-message Proto2 {
-  option experimental_java_message_interface =
-      "com.google.protobuf.ExtraInterfaces.HasBoolValue";
-
-  optional bool bool_value = 1;
-}
diff --git a/java/lite/generate-test-sources-build.xml b/java/lite/generate-test-sources-build.xml
index 62bca93..65e62ce 100644
--- a/java/lite/generate-test-sources-build.xml
+++ b/java/lite/generate-test-sources-build.xml
@@ -4,6 +4,7 @@
         <arg value="--java_out=lite:${generated.testsources.dir}"/>
         <arg value="--proto_path=${protobuf.source.dir}"/>
         <arg value="--proto_path=${protobuf.basedir}/java/core/${test.proto.dir}"/>
+        <arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_import.proto"/>
         <arg value="${protobuf.source.dir}/google/protobuf/unittest_import_lite.proto"/>
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index d60a480..2074003 100644
--- a/java/lite/pom.xml
+++ b/java/lite/pom.xml
@@ -173,6 +173,7 @@
                     <include>UnknownFieldSetLite.java</include>
                     <include>UnknownFieldSetLiteSchema.java</include>
                     <include>UnmodifiableLazyStringList.java</include>
+                    <include>UnsafeByteOperations.java</include>
                     <include>UnsafeUtil.java</include>
                     <include>Utf8.java</include>
                     <include>WireFormat.java</include>
diff --git a/java/lite/src/test/java/com/google/protobuf/LiteTest.java b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
index 140df72..f2ce461 100644
--- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
@@ -38,6 +38,7 @@
 import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
 import com.google.protobuf.UnittestLite.ForeignEnumLite;
 import com.google.protobuf.UnittestLite.ForeignMessageLite;
+import com.google.protobuf.UnittestLite.RecursiveMessage;
 import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
 import com.google.protobuf.UnittestLite.TestAllTypesLite;
 import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedEnum;
@@ -61,6 +62,7 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
 import java.nio.ByteBuffer;
@@ -1638,6 +1640,160 @@
     }
   }
 
+  public void testParseFromStream_IOExceptionNotLost() throws Exception {
+    final IOException readException = new IOException();
+    try {
+      TestAllTypesLite.parseFrom(
+          CodedInputStream.newInstance(
+              new InputStream() {
+                @Override
+                public int read() throws IOException {
+                  throw readException;
+                }
+              }));
+      fail();
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception == readException) {
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+    }
+  }
+
+  public void testParseDelimitedFromStream_IOExceptionNotLost() throws Exception {
+    final IOException readException = new IOException();
+    try {
+      TestAllTypesLite.parseDelimitedFrom(
+          new InputStream() {
+            @Override
+            public int read() throws IOException {
+              throw readException;
+            }
+          });
+      fail();
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception == readException) {
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+    }
+  }
+
+  public void testParseFromArray_manyNestedMessagesError() throws Exception {
+    RecursiveMessage.Builder recursiveMessage =
+        RecursiveMessage.newBuilder().setPayload(ByteString.copyFrom(new byte[1]));
+    for (int i = 0; i < 20; i++) {
+      recursiveMessage = RecursiveMessage.newBuilder().setRecurse(recursiveMessage.build());
+    }
+    byte[] result = recursiveMessage.build().toByteArray();
+    result[
+            result.length
+                - CodedOutputStream.computeTagSize(RecursiveMessage.PAYLOAD_FIELD_NUMBER)
+                - CodedOutputStream.computeLengthDelimitedFieldSize(1)] =
+        0; // Set invalid tag
+    try {
+      RecursiveMessage.parseFrom(result);
+      fail("Result was: " + Arrays.toString(result));
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      int exceptionCount = 0;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception instanceof InvalidProtocolBufferException) {
+          exceptionCount++;
+        }
+        for (StackTraceElement element : exception.getStackTrace()) {
+          if (InvalidProtocolBufferException.class.getName().equals(element.getClassName())
+              && "invalidTag".equals(element.getMethodName())) {
+            found = true;
+          } else if (Android.isOnAndroidDevice()
+              && "decodeUnknownField".equals(element.getMethodName())) {
+            // Android is missing the first element of the stack trace - b/181147885
+            found = true;
+          }
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+      if (exceptionCount > 1) {
+        throw new AssertionError(exceptionCount + " nested parsing exceptions", expected);
+      }
+    }
+  }
+
+  public void testParseFromStream_manyNestedMessagesError() throws Exception {
+    RecursiveMessage.Builder recursiveMessage =
+        RecursiveMessage.newBuilder().setPayload(ByteString.copyFrom(new byte[1]));
+    for (int i = 0; i < 20; i++) {
+      recursiveMessage = RecursiveMessage.newBuilder().setRecurse(recursiveMessage.build());
+    }
+    byte[] result = recursiveMessage.build().toByteArray();
+    result[
+            result.length
+                - CodedOutputStream.computeTagSize(RecursiveMessage.PAYLOAD_FIELD_NUMBER)
+                - CodedOutputStream.computeLengthDelimitedFieldSize(1)] =
+        0; // Set invalid tag
+    try {
+      RecursiveMessage.parseFrom(CodedInputStream.newInstance(new ByteArrayInputStream(result)));
+      fail("Result was: " + Arrays.toString(result));
+    } catch (InvalidProtocolBufferException expected) {
+      boolean found = false;
+      int exceptionCount = 0;
+      for (Throwable exception = expected; exception != null; exception = exception.getCause()) {
+        if (exception instanceof InvalidProtocolBufferException) {
+          exceptionCount++;
+        }
+        for (StackTraceElement element : exception.getStackTrace()) {
+          if (InvalidProtocolBufferException.class.getName().equals(element.getClassName())
+              && "invalidTag".equals(element.getMethodName())) {
+            found = true;
+          } else if (Android.isOnAndroidDevice() && "readTag".equals(element.getMethodName())) {
+            // Android is missing the first element of the stack trace - b/181147885
+            found = true;
+          }
+        }
+      }
+      if (!found) {
+        throw new AssertionError("Lost cause of parsing error", expected);
+      }
+      if (exceptionCount > 1) {
+        throw new AssertionError(exceptionCount + " nested parsing exceptions", expected);
+      }
+    }
+  }
+
+  public void testParseFromStream_sneakyNestedException() throws Exception {
+    final InvalidProtocolBufferException sketchy =
+        new InvalidProtocolBufferException("Created in a sketchy way!")
+            .setUnfinishedMessage(TestAllTypesLite.getDefaultInstance());
+    try {
+      RecursiveMessage.parseFrom(
+          CodedInputStream.newInstance(
+              new InputStream() {
+                @Override
+                public int read() throws IOException {
+                  throw sketchy;
+                }
+              }));
+      fail();
+    } catch (InvalidProtocolBufferException expected) {
+      assertNotSame(expected, sketchy);
+    }
+    assertEquals(sketchy.getUnfinishedMessage(), TestAllTypesLite.getDefaultInstance());
+  }
+
   public void testMergeFrom_sanity() throws Exception {
     TestAllTypesLite one = TestUtilLite.getAllLiteSetBuilder().build();
     byte[] bytes = one.toByteArray();
@@ -2250,24 +2406,26 @@
   }
 
   public void testAddAllIteratesOnce() {
-    TestAllTypesLite.newBuilder()
-        .addAllRepeatedBool(new OneTimeIterableList<>(false))
-        .addAllRepeatedInt32(new OneTimeIterableList<>(0))
-        .addAllRepeatedInt64(new OneTimeIterableList<>(0L))
-        .addAllRepeatedFloat(new OneTimeIterableList<>(0f))
-        .addAllRepeatedDouble(new OneTimeIterableList<>(0d))
-        .addAllRepeatedBytes(new OneTimeIterableList<>(ByteString.EMPTY))
-        .addAllRepeatedString(new OneTimeIterableList<>(""))
-        .addAllRepeatedNestedMessage(new OneTimeIterableList<>(NestedMessage.getDefaultInstance()))
-        .addAllRepeatedBool(new OneTimeIterable<>(false))
-        .addAllRepeatedInt32(new OneTimeIterable<>(0))
-        .addAllRepeatedInt64(new OneTimeIterable<>(0L))
-        .addAllRepeatedFloat(new OneTimeIterable<>(0f))
-        .addAllRepeatedDouble(new OneTimeIterable<>(0d))
-        .addAllRepeatedBytes(new OneTimeIterable<>(ByteString.EMPTY))
-        .addAllRepeatedString(new OneTimeIterable<>(""))
-        .addAllRepeatedNestedMessage(new OneTimeIterable<>(NestedMessage.getDefaultInstance()))
-        .build();
+    TestAllTypesLite unused =
+        TestAllTypesLite.newBuilder()
+            .addAllRepeatedBool(new OneTimeIterableList<>(false))
+            .addAllRepeatedInt32(new OneTimeIterableList<>(0))
+            .addAllRepeatedInt64(new OneTimeIterableList<>(0L))
+            .addAllRepeatedFloat(new OneTimeIterableList<>(0f))
+            .addAllRepeatedDouble(new OneTimeIterableList<>(0d))
+            .addAllRepeatedBytes(new OneTimeIterableList<>(ByteString.EMPTY))
+            .addAllRepeatedString(new OneTimeIterableList<>(""))
+            .addAllRepeatedNestedMessage(
+                new OneTimeIterableList<>(NestedMessage.getDefaultInstance()))
+            .addAllRepeatedBool(new OneTimeIterable<>(false))
+            .addAllRepeatedInt32(new OneTimeIterable<>(0))
+            .addAllRepeatedInt64(new OneTimeIterable<>(0L))
+            .addAllRepeatedFloat(new OneTimeIterable<>(0f))
+            .addAllRepeatedDouble(new OneTimeIterable<>(0d))
+            .addAllRepeatedBytes(new OneTimeIterable<>(ByteString.EMPTY))
+            .addAllRepeatedString(new OneTimeIterable<>(""))
+            .addAllRepeatedNestedMessage(new OneTimeIterable<>(NestedMessage.getDefaultInstance()))
+            .build();
   }
 
   public void testAddAllIteratesOnce_throwsOnNull() {
diff --git a/java/pom.xml b/java/pom.xml
index b7669d0..b93d8ea 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -75,7 +75,7 @@
       <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
-        <version>4.13.1</version>
+        <version>4.13.2</version>
         <scope>test</scope>
       </dependency>
       <dependency>
@@ -93,18 +93,18 @@
       <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava</artifactId>
-        <version>30.0-android</version>
+        <version>30.1-android</version>
       </dependency>
       <dependency>
         <groupId>com.google.guava</groupId>
         <artifactId>guava-testlib</artifactId>
-        <version>30.0-android</version>
+        <version>30.1-android</version>
         <scope>test</scope>
       </dependency>
       <dependency>
         <groupId>com.google.truth</groupId>
         <artifactId>truth</artifactId>
-        <version>1.0.1</version>
+        <version>1.1.2</version>
         <scope>test</scope>
       </dependency>
     </dependencies>
diff --git a/java/util/src/main/java/com/google/protobuf/util/Durations.java b/java/util/src/main/java/com/google/protobuf/util/Durations.java
index 7470960..fd13771 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Durations.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Durations.java
@@ -149,6 +149,12 @@
     return (duration.getSeconds() == 0) ? duration.getNanos() < 0 : duration.getSeconds() < 0;
   }
 
+  /** Returns whether the given {@link Duration} is positive or not. */
+  public static boolean isPositive(Duration duration) {
+    checkValid(duration);
+    return !isNegative(duration) && !duration.equals(ZERO);
+  }
+
   /**
    * Ensures that the given {@link Duration} is not negative.
    *
@@ -157,7 +163,6 @@
    */
   @CanIgnoreReturnValue
   public static Duration checkNotNegative(Duration duration) {
-    checkValid(duration);
     checkArgument(!isNegative(duration), "duration (%s) must not be negative", toString(duration));
     return duration;
   }
@@ -170,11 +175,7 @@
    */
   @CanIgnoreReturnValue
   public static Duration checkPositive(Duration duration) {
-    checkValid(duration);
-    checkArgument(
-        !isNegative(duration) && !duration.equals(ZERO),
-        "duration (%s) must be positive",
-        toString(duration));
+    checkArgument(isPositive(duration), "duration (%s) must be positive", toString(duration));
     return duration;
   }
 
diff --git a/kokoro/linux/dockerfile/test/csharp/Dockerfile b/kokoro/linux/dockerfile/test/csharp/Dockerfile
index 95bd653..37edbfd 100644
--- a/kokoro/linux/dockerfile/test/csharp/Dockerfile
+++ b/kokoro/linux/dockerfile/test/csharp/Dockerfile
@@ -1,4 +1,4 @@
-FROM debian:stretch
+FROM debian:buster
 
 # Install dependencies.  We start with the basic ones require to build protoc
 # and the C++ build
@@ -22,14 +22,18 @@
   wget \
   && apt-get clean
 
+# Update ca-certificates to fix known buster + .NET 5 issue
+# https://github.com/NuGet/Announcements/issues/49
+RUN apt-get update && apt-get install -y ca-certificates && apt-get clean
+
 # dotnet SDK prerequisites
-RUN apt-get update && apt-get install -y libunwind8 libicu57 && apt-get clean
+RUN apt-get update && apt-get install -y libunwind8 libicu63 && apt-get clean
 
 # Install dotnet SDK via install script
 RUN wget -q https://dot.net/v1/dotnet-install.sh && \
     chmod u+x dotnet-install.sh && \
     ./dotnet-install.sh --version 2.1.802 && \
-    ./dotnet-install.sh --version 3.1.301 && \
+    ./dotnet-install.sh --version 5.0.102 && \
     ln -s /root/.dotnet/dotnet /usr/local/bin
 
 RUN wget -q www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe
diff --git a/kokoro/linux/python/build.sh b/kokoro/linux/python/build.sh
deleted file mode 100755
index 86964f5..0000000
--- a/kokoro/linux/python/build.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-#
-# This is the top-level script we give to Kokoro as the entry point for
-# running the "pull request" project:
-#
-# This script selects a specific Dockerfile (for building a Docker image) and
-# a script to run inside that image.  Then we delegate to the general
-# build_and_run_docker.sh script.
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-export DOCKERFILE_DIR=kokoro/linux/64-bit
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python/continuous.cfg b/kokoro/linux/python/continuous.cfg
deleted file mode 100644
index e2fc413..0000000
--- a/kokoro/linux/python/continuous.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
diff --git a/kokoro/linux/python/presubmit.cfg b/kokoro/linux/python/presubmit.cfg
deleted file mode 100644
index e2fc413..0000000
--- a/kokoro/linux/python/presubmit.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
diff --git a/kokoro/release/protoc/linux/build.sh b/kokoro/release/protoc/linux/build.sh
index efc3ee6..44a95aa 100755
--- a/kokoro/release/protoc/linux/build.sh
+++ b/kokoro/release/protoc/linux/build.sh
@@ -23,7 +23,7 @@
 protoc-artifacts/build-protoc.sh linux ppcle_64 protoc
 
 sudo apt install -y g++-s390x-linux-gnu
-protoc-artifacts/build-protoc.sh linux s390x protoc
+protoc-artifacts/build-protoc.sh linux s390_64 protoc
 
 # Use docker image to build linux artifacts.
 DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
diff --git a/kokoro/release/python/linux/build_artifacts.sh b/kokoro/release/python/linux/build_artifacts.sh
index a35fc6f..b676e0e 100755
--- a/kokoro/release/python/linux/build_artifacts.sh
+++ b/kokoro/release/python/linux/build_artifacts.sh
@@ -49,9 +49,31 @@
   sudo rm -rf $REPO_DIR
 }
 
+build_crosscompiled_aarch64_artifact_version() {
+  # crosscompilation is only supported with the dockcross manylinux2014 image
+  DOCKER_IMAGE=dockcross/manylinux2014-aarch64
+  PLAT=aarch64
+
+  # TODO(jtatermusch): currently when crosscompiling, "auditwheel repair" will be disabled
+  # since auditwheel doesn't work for crosscomiled wheels.
+  build_artifact_version $@
+}
+
 build_artifact_version 2.7
 build_artifact_version 3.5
 build_artifact_version 3.6
 build_artifact_version 3.7
 build_artifact_version 3.8
 build_artifact_version 3.9
+
+build_crosscompiled_aarch64_artifact_version 3.7
+build_crosscompiled_aarch64_artifact_version 3.8
+build_crosscompiled_aarch64_artifact_version 3.9
+
+# Put the aarch64 manylinux wheels under the "unofficial" subdirectory.
+# Only wheels directly under the artifacts/ directory will be published
+# to PyPI as part of the protobuf release process.
+# TODO(jtattermusch): include aarch64 wheels in the release
+# once they are sufficiently tested.
+mkdir -p $ARTIFACT_DIR/unofficial
+mv $ARTIFACT_DIR/protobuf-*-manylinux*_aarch64.whl $ARTIFACT_DIR/unofficial
diff --git a/kokoro/release/python/linux/config.sh b/kokoro/release/python/linux/config.sh
index 7a8f663..e29eb58 100644
--- a/kokoro/release/python/linux/config.sh
+++ b/kokoro/release/python/linux/config.sh
@@ -6,15 +6,38 @@
     # Runs in the root directory of this repository.
     pushd protobuf
 
-    yum install -y devtoolset-2-libatomic-devel
+    if [ "$PLAT" == "aarch64" ]
+    then
+      local configure_host_flag="--host=aarch64"
+    else
+      yum install -y devtoolset-2-libatomic-devel
+    fi
 
-    # Build protoc
+    # Build protoc and libprotobuf
     ./autogen.sh
-    ./configure
-
-    CXXFLAGS="-fPIC -g -O2" ./configure
+    CXXFLAGS="-fPIC -g -O2" ./configure $configure_host_flag
     make -j8
 
+    if [ "$PLAT" == "aarch64" ]
+    then
+      # we are crosscompiling for aarch64 while running on x64
+      # the simplest way for build_py command to be able to generate
+      # the protos is by running the protoc process under
+      # an emulator. That way we don't have to build a x64 version
+      # of protoc. The qemu-arm emulator is already included
+      # in the dockcross docker image.
+      # Running protoc under an emulator is fast as protoc doesn't
+      # really do much.
+
+      # create a simple shell wrapper that runs crosscompiled protoc under qemu
+      echo '#!/bin/bash' >protoc_qemu_wrapper.sh
+      echo 'exec qemu-aarch64 "../src/protoc" "$@"' >>protoc_qemu_wrapper.sh
+      chmod ugo+x protoc_qemu_wrapper.sh
+
+      # PROTOC variable is by build_py step that runs under ./python directory
+      export PROTOC=../protoc_qemu_wrapper.sh
+    fi
+
     # Generate python dependencies.
     pushd python
     python setup.py build_py
@@ -35,7 +58,20 @@
     # Modify build version
     pwd
     ls
-    python setup.py bdist_wheel --cpp_implementation --compile_static_extension
+
+    if [ "$PLAT" == "aarch64" ]
+    then
+      # when crosscompiling for aarch64, --plat-name needs to be set explicitly
+      # to end up with correctly named wheel file
+      # the value should be manylinuxABC_ARCH and dockcross docker image
+      # conveniently provides the value in the AUDITWHEEL_PLAT env
+      local plat_name_flag="--plat-name=$AUDITWHEEL_PLAT"
+
+      # override the value of EXT_SUFFIX to make sure the crosscompiled .so files in the wheel have the correct filename suffix
+      export PROTOCOL_BUFFERS_OVERRIDE_EXT_SUFFIX="$(python -c 'import sysconfig; print(sysconfig.get_config_var("EXT_SUFFIX").replace("-x86_64-linux-gnu.so", "-aarch64-linux-gnu.so"))')"
+    fi
+
+    python setup.py bdist_wheel --cpp_implementation --compile_static_extension $plat_name_flag
     cp dist/*.whl $abs_wheelhouse
 }
 
@@ -48,3 +84,12 @@
     python --version
     python -c "from google.protobuf.pyext import _message;"
 }
+
+if [ "$PLAT" == "aarch64" ]
+then
+  # when crosscompiling for aarch64, override the default multibuild's repair_wheelhouse logic
+  # since "auditwheel repair" doesn't work for crosscompiled wheels
+  function repair_wheelhouse {
+      echo "Skipping repair_wheelhouse since auditwheel requires build architecture to match wheel architecture."
+  }
+fi
diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m
index b056a52..e3ff7c4 100644
--- a/objectivec/GPBExtensionRegistry.m
+++ b/objectivec/GPBExtensionRegistry.m
@@ -34,18 +34,20 @@
 #import "GPBDescriptor.h"
 
 @implementation GPBExtensionRegistry {
-  NSMutableDictionary *mutableClassMap_;
+  CFMutableDictionaryRef mutableClassMap_;
 }
 
 - (instancetype)init {
   if ((self = [super init])) {
-    mutableClassMap_ = [[NSMutableDictionary alloc] init];
+    // The keys are ObjC classes, so straight up ptr comparisons are fine.
+    mutableClassMap_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
+                                             &kCFTypeDictionaryValueCallBacks);
   }
   return self;
 }
 
 - (void)dealloc {
-  [mutableClassMap_ release];
+  CFRelease(mutableClassMap_);
   [super dealloc];
 }
 
@@ -68,14 +70,13 @@
 
   Class containingMessageClass = extension.containingMessageClass;
   CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      [mutableClassMap_ objectForKey:containingMessageClass];
+      CFDictionaryGetValue(mutableClassMap_, containingMessageClass);
   if (extensionMap == nil) {
     // Use a custom dictionary here because the keys are numbers and conversion
     // back and forth from NSNumber isn't worth the cost.
     extensionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
                                              &kCFTypeDictionaryValueCallBacks);
-    [mutableClassMap_ setObject:(id)extensionMap
-                         forKey:(id<NSCopying>)containingMessageClass];
+    CFDictionarySetValue(mutableClassMap_, containingMessageClass, extensionMap);
     CFRelease(extensionMap);
   }
 
@@ -87,7 +88,7 @@
                                        fieldNumber:(NSInteger)fieldNumber {
   Class messageClass = descriptor.messageClass;
   CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      [mutableClassMap_ objectForKey:messageClass];
+      CFDictionaryGetValue(mutableClassMap_, messageClass);
   ssize_t key = fieldNumber;
   GPBExtensionDescriptor *result =
       (extensionMap
@@ -101,28 +102,28 @@
   CFDictionarySetValue(extensionMap, key, value);
 }
 
+static void CopySubDictionary(const void *key, const void *value, void *context) {
+  CFMutableDictionaryRef mutableClassMap = (CFMutableDictionaryRef)context;
+  Class containingMessageClass = key;
+  CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
+
+  CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
+      CFDictionaryGetValue(mutableClassMap, containingMessageClass);
+  if (extensionMap == nil) {
+    extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
+    CFDictionarySetValue(mutableClassMap, containingMessageClass, extensionMap);
+    CFRelease(extensionMap);
+  } else {
+    CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap);
+  }
+}
+
 - (void)addExtensions:(GPBExtensionRegistry *)registry {
   if (registry == nil) {
     // In the case where there are no extensions just ignore.
     return;
   }
-  NSMutableDictionary *otherClassMap = registry->mutableClassMap_;
-  [otherClassMap enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL * stop) {
-#pragma unused(stop)
-    Class containingMessageClass = key;
-    CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
-
-    CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-        [mutableClassMap_ objectForKey:containingMessageClass];
-    if (extensionMap == nil) {
-      extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
-      [mutableClassMap_ setObject:(id)extensionMap
-                           forKey:(id<NSCopying>)containingMessageClass];
-      CFRelease(extensionMap);
-    } else {
-      CFDictionaryApplyFunction(otherExtensionMap, CopyKeyValue, extensionMap);
-    }
-  }];
+  CFDictionaryApplyFunction(registry->mutableClassMap_, CopySubDictionary, mutableClassMap_);
 }
 
 #pragma clang diagnostic pop
diff --git a/php/README.md b/php/README.md
index 16757be..c4292cf 100644
--- a/php/README.md
+++ b/php/README.md
@@ -16,8 +16,8 @@
 
 To use PHP runtime library requires:
 
-- C extension: PHP 5.5, 5.6, or 7.
-- [PHP package](http://php.net/downloads.php): PHP 5.5, 5.6 or 7.
+- C extension: PHP 7.x, 8.0
+- [PHP package](http://php.net/downloads.php): PHP 5.5, 5.6, 7.x, or 8.0.
 
 ## Installation
 
diff --git a/php/src/Google/Protobuf/Internal/FileOptions.php b/php/src/Google/Protobuf/Internal/FileOptions.php
index 6283b2a..3f2c3a4 100644
--- a/php/src/Google/Protobuf/Internal/FileOptions.php
+++ b/php/src/Google/Protobuf/Internal/FileOptions.php
@@ -25,20 +25,20 @@
      */
     protected $java_package = null;
     /**
-     * If set, all the classes from the .proto file are wrapped in a single
-     * outer class with the given name.  This applies to both Proto1
-     * (equivalent to the old "--one_java_file" option) and Proto2 (where
-     * a .proto always translates to a single class, but you may want to
-     * explicitly choose the class name).
+     * Controls the name of the wrapper Java class generated for the .proto file.
+     * That class will always contain the .proto file's getDescriptor() method as
+     * well as any top-level extensions defined in the .proto file.
+     * If java_multiple_files is disabled, then all the other classes from the
+     * .proto file will be nested inside the single wrapper outer class.
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      */
     protected $java_outer_classname = null;
     /**
-     * If set true, then the Java code generator will generate a separate .java
+     * If enabled, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
-     * file.  Thus, these types will *not* be nested inside the outer class
-     * named by java_outer_classname.  However, the outer class will still be
+     * file.  Thus, these types will *not* be nested inside the wrapper class
+     * named by java_outer_classname.  However, the wrapper class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
      *
@@ -192,16 +192,16 @@
      *           inappropriate because proto packages do not normally start with backwards
      *           domain names.
      *     @type string $java_outer_classname
-     *           If set, all the classes from the .proto file are wrapped in a single
-     *           outer class with the given name.  This applies to both Proto1
-     *           (equivalent to the old "--one_java_file" option) and Proto2 (where
-     *           a .proto always translates to a single class, but you may want to
-     *           explicitly choose the class name).
+     *           Controls the name of the wrapper Java class generated for the .proto file.
+     *           That class will always contain the .proto file's getDescriptor() method as
+     *           well as any top-level extensions defined in the .proto file.
+     *           If java_multiple_files is disabled, then all the other classes from the
+     *           .proto file will be nested inside the single wrapper outer class.
      *     @type bool $java_multiple_files
-     *           If set true, then the Java code generator will generate a separate .java
+     *           If enabled, then the Java code generator will generate a separate .java
      *           file for each top-level message, enum, and service defined in the .proto
-     *           file.  Thus, these types will *not* be nested inside the outer class
-     *           named by java_outer_classname.  However, the outer class will still be
+     *           file.  Thus, these types will *not* be nested inside the wrapper class
+     *           named by java_outer_classname.  However, the wrapper class will still be
      *           generated to contain the file's getDescriptor() method as well as any
      *           top-level extensions defined in the file.
      *     @type bool $java_generate_equals_and_hash
@@ -319,11 +319,11 @@
     }
 
     /**
-     * If set, all the classes from the .proto file are wrapped in a single
-     * outer class with the given name.  This applies to both Proto1
-     * (equivalent to the old "--one_java_file" option) and Proto2 (where
-     * a .proto always translates to a single class, but you may want to
-     * explicitly choose the class name).
+     * Controls the name of the wrapper Java class generated for the .proto file.
+     * That class will always contain the .proto file's getDescriptor() method as
+     * well as any top-level extensions defined in the .proto file.
+     * If java_multiple_files is disabled, then all the other classes from the
+     * .proto file will be nested inside the single wrapper outer class.
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      * @return string
@@ -344,11 +344,11 @@
     }
 
     /**
-     * If set, all the classes from the .proto file are wrapped in a single
-     * outer class with the given name.  This applies to both Proto1
-     * (equivalent to the old "--one_java_file" option) and Proto2 (where
-     * a .proto always translates to a single class, but you may want to
-     * explicitly choose the class name).
+     * Controls the name of the wrapper Java class generated for the .proto file.
+     * That class will always contain the .proto file's getDescriptor() method as
+     * well as any top-level extensions defined in the .proto file.
+     * If java_multiple_files is disabled, then all the other classes from the
+     * .proto file will be nested inside the single wrapper outer class.
      *
      * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
      * @param string $var
@@ -363,10 +363,10 @@
     }
 
     /**
-     * If set true, then the Java code generator will generate a separate .java
+     * If enabled, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
-     * file.  Thus, these types will *not* be nested inside the outer class
-     * named by java_outer_classname.  However, the outer class will still be
+     * file.  Thus, these types will *not* be nested inside the wrapper class
+     * named by java_outer_classname.  However, the wrapper class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
      *
@@ -389,10 +389,10 @@
     }
 
     /**
-     * If set true, then the Java code generator will generate a separate .java
+     * If enabled, then the Java code generator will generate a separate .java
      * file for each top-level message, enum, and service defined in the .proto
-     * file.  Thus, these types will *not* be nested inside the outer class
-     * named by java_outer_classname.  However, the outer class will still be
+     * file.  Thus, these types will *not* be nested inside the wrapper class
+     * named by java_outer_classname.  However, the wrapper class will still be
      * generated to contain the file's getDescriptor() method as well as any
      * top-level extensions defined in the file.
      *
diff --git a/php/src/Google/Protobuf/Internal/RepeatedField.php b/php/src/Google/Protobuf/Internal/RepeatedField.php
index ec7a3a6..350bbb5 100644
--- a/php/src/Google/Protobuf/Internal/RepeatedField.php
+++ b/php/src/Google/Protobuf/Internal/RepeatedField.php
@@ -67,7 +67,7 @@
     /**
      * Constructs an instance of RepeatedField.
      *
-     * @param long $type Type of the stored element.
+     * @param integer $type Type of the stored element.
      * @param string $klass Message/Enum class name (message/enum fields only).
      * @ignore
      */
@@ -116,7 +116,7 @@
      *
      * This will also be called for: $ele = $arr[0]
      *
-     * @param long $offset The index of the element to be fetched.
+     * @param integer $offset The index of the element to be fetched.
      * @return object The stored element at given index.
      * @throws \ErrorException Invalid type for index.
      * @throws \ErrorException Non-existing index.
@@ -131,7 +131,7 @@
      *
      * This will also be called for: $arr []= $ele and $arr[0] = ele
      *
-     * @param long $offset The index of the element to be assigned.
+     * @param integer $offset The index of the element to be assigned.
      * @param object $value The element to be assigned.
      * @return void
      * @throws \ErrorException Invalid type for index.
@@ -204,7 +204,7 @@
      *
      * This will also be called for: unset($arr)
      *
-     * @param long $offset The index of the element to be removed.
+     * @param integer $offset The index of the element to be removed.
      * @return void
      * @throws \ErrorException Invalid type for index.
      * @throws \ErrorException The element to be removed is not at the end of the
@@ -227,7 +227,7 @@
      *
      * This will also be called for: isset($arr)
      *
-     * @param long $offset The index of the element to be removed.
+     * @param integer $offset The index of the element to be removed.
      * @return bool True if the element at the given offset exists.
      * @throws \ErrorException Invalid type for index.
      */
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
index 2c45fef..8fc3669 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -20,7 +20,7 @@
 ## Maven Location
 The published protoc artifacts are available on Maven here:
 
-    http://central.maven.org/maven2/com/google/protobuf/protoc/
+    https://repo.maven.apache.org/maven2/com/google/protobuf/protoc/
 
 ## Versioning
 The version of the ``protoc`` artifact must be the same as the version of the
@@ -123,7 +123,7 @@
           protoc.exe
         + ppcle_64
           protoc.exe
-        + s390x
+        + s390_64
           protoc.exe
       + osx
         + x86_64
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index 7f65d37..4602842 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/build-protoc.sh
@@ -93,7 +93,7 @@
         assertEq $format "elf64-x86-64" $LINENO
       elif [[ "$ARCH" == aarch_64 ]]; then
         assertEq $format "elf64-little" $LINENO
-      elif [[ "$ARCH" == s390x ]]; then
+      elif [[ "$ARCH" == s390_64 ]]; then
 	if [[ $host_machine == s390x ]];then
 	  assertEq $format "elf64-s390" $LINENO
 	else
@@ -149,7 +149,7 @@
       white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
     elif [[ "$ARCH" == x86_64 ]]; then
       white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-x86-64\.so\.2"
-    elif [[ "$ARCH" == s390x ]]; then
+    elif [[ "$ARCH" == s390_64 ]]; then
       if [[ $host_machine != s390x ]];then
         dump_cmd='objdump -p '"$1"' | grep NEEDED'
       fi
@@ -226,7 +226,7 @@
     elif [[ "$ARCH" == ppcle_64 ]]; then
       CXXFLAGS="$CXXFLAGS -m64"
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=powerpc64le-linux-gnu"
-    elif [[ "$ARCH" == s390x ]]; then
+    elif [[ "$ARCH" == s390_64 ]]; then
       CXXFLAGS="$CXXFLAGS -m64"
       CONFIGURE_ARGS="$CONFIGURE_ARGS --host=s390x-linux-gnu"
     else
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
index 2a25d3c..7d1923e 100755
--- a/protoc-artifacts/build-zip.sh
+++ b/protoc-artifacts/build-zip.sh
@@ -21,7 +21,7 @@
   dist/<TARGET>-<VERSION_NUMBER>-linux-x86_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-aarch_64.zip
   dist/<TARGET>-<VERSION_NUMBER>-linux-ppcle_64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-linux-s390x.zip
+  dist/<TARGET>-<VERSION_NUMBER>-linux-s390_64.zip
 EOF
   exit 1
 fi
@@ -38,7 +38,7 @@
   linux-x86_64.zip linux-x86_64.exe \
   linux-aarch_64.zip linux-aarch_64.exe \
   linux-ppcle_64.zip linux-ppcle_64.exe \
-  linux-s390x.zip linux-s390x.exe \
+  linux-s390_64.zip linux-s390_64.exe \
 )
 
 # List of all well-known types to be included.
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
index 2e12c37..defc194 100644
--- a/protoc-artifacts/pom.xml
+++ b/protoc-artifacts/pom.xml
@@ -81,8 +81,8 @@
                   <type>exe</type>
 	  	</artifact>
                 <artifact>
-                  <file>${basedir}/target/linux/s390x/protoc.exe</file>
-                  <classifier>linux-s390x</classifier>
+                  <file>${basedir}/target/linux/s390_64/protoc.exe</file>
+                  <classifier>linux-s390_64</classifier>
                   <type>exe</type>
                 </artifact>
               </artifacts>
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/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 987116a..6f75251 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -1176,6 +1176,54 @@
         '  }\n'
         '}\n')
 
+  def testDuplicateMapKey(self):
+    message = map_unittest_pb2.TestMap()
+    text = (
+        'map_uint64_uint64 {\n'
+        '  key: 123\n'
+        '  value: 17179869184\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "first"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    c: 5\n'
+        '  }\n'
+        '}\n'
+        'map_uint64_uint64 {\n'
+        '  key: 123\n'
+        '  value: 321\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "second"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    d: 5\n'
+        '  }\n'
+        '}\n')
+    text_format.Parse(text, message)
+    self.CompareToGoldenText(
+        text_format.MessageToString(message), 'map_uint64_uint64 {\n'
+        '  key: 123\n'
+        '  value: 321\n'
+        '}\n'
+        'map_string_string {\n'
+        '  key: "abc"\n'
+        '  value: "second"\n'
+        '}\n'
+        'map_int32_foreign_message {\n'
+        '  key: 111\n'
+        '  value {\n'
+        '    d: 5\n'
+        '  }\n'
+        '}\n')
+
   # In cpp implementation, __str__ calls the cpp implementation of text format.
   def testPrintMapUsingCppImplementation(self):
     message = map_unittest_pb2.TestMap()
@@ -2348,6 +2396,13 @@
                 '}\n')
     self.assertEqual(expected, output)
 
+  def testPrintShortFormatRepeatedFields(self):
+    message = unittest_pb2.TestAllTypes()
+    message.repeated_int32.append(1)
+    output = text_format.MessageToString(
+        message, use_short_repeated_primitives=True, force_colon=True)
+    self.assertEqual('repeated_int32: [1]\n', output)
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 75f1760..eeb844c 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -30,15 +30,18 @@
 
 // Author: petar@google.com (Petar Petrov)
 
+#include <google/protobuf/pyext/descriptor.h>
+
 #include <Python.h>
 #include <frameobject.h>
+
+#include <cstdint>
 #include <string>
 #include <unordered_map>
 
 #include <google/protobuf/io/coded_stream.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/pyext/descriptor.h>
 #include <google/protobuf/pyext/descriptor_containers.h>
 #include <google/protobuf/pyext/descriptor_pool.h>
 #include <google/protobuf/pyext/message.h>
@@ -195,7 +198,7 @@
   std::string serialized;
   from.SerializeToString(&serialized);
   io::CodedInputStream input(
-      reinterpret_cast<const uint8*>(serialized.c_str()), serialized.size());
+      reinterpret_cast<const uint8_t*>(serialized.c_str()), serialized.size());
   input.SetExtensionRegistry(message_factory->pool->pool,
                              message_factory->message_factory);
   bool success = to->ParseFromCodedStream(&input);
@@ -247,8 +250,9 @@
                  message_type->full_name().c_str());
     return NULL;
   }
+  ScopedPyObjectPtr args(PyTuple_New(0));
   ScopedPyObjectPtr value(
-      PyEval_CallObject(message_class->AsPyObject(), NULL));
+      PyObject_Call(message_class->AsPyObject(), args.get(), NULL));
   Py_DECREF(message_class);
   if (value == NULL) {
     return NULL;
@@ -804,22 +808,22 @@
 
   switch (_GetDescriptor(self)->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      int32 value = _GetDescriptor(self)->default_value_int32();
+      int32_t value = _GetDescriptor(self)->default_value_int32();
       result = PyInt_FromLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      int64 value = _GetDescriptor(self)->default_value_int64();
+      int64_t value = _GetDescriptor(self)->default_value_int64();
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      uint32 value = _GetDescriptor(self)->default_value_uint32();
+      uint32_t value = _GetDescriptor(self)->default_value_uint32();
       result = PyInt_FromSize_t(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      uint64 value = _GetDescriptor(self)->default_value_uint64();
+      uint64_t value = _GetDescriptor(self)->default_value_uint64();
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
diff --git a/python/google/protobuf/pyext/descriptor_database.cc b/python/google/protobuf/pyext/descriptor_database.cc
index 26f1b5f..da1c84a 100644
--- a/python/google/protobuf/pyext/descriptor_database.cc
+++ b/python/google/protobuf/pyext/descriptor_database.cc
@@ -33,6 +33,8 @@
 
 #include <google/protobuf/pyext/descriptor_database.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -164,7 +166,7 @@
     return false;
   }
   Py_ssize_t size = PyList_Size(py_list.get());
-  int64 item_value;
+  int64_t item_value;
   for (Py_ssize_t i = 0 ; i < size; ++i) {
     ScopedPyObjectPtr item(PySequence_GetItem(py_list.get(), i));
     item_value = PyLong_AsLong(item.get());
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index 6f1464e..d330e0d 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -176,9 +176,10 @@
 // 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/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index e9ac714..37b414c 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -32,14 +32,16 @@
 // Author: tibell@google.com (Johan Tibell)
 
 #include <google/protobuf/pyext/extension_dict.h>
+
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/dynamic_message.h>
 #include <google/protobuf/message.h>
-#include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/pyext/descriptor.h>
 #include <google/protobuf/pyext/message.h>
 #include <google/protobuf/pyext/message_factory.h>
@@ -263,7 +265,7 @@
 }
 
 PyObject* _FindExtensionByNumber(ExtensionDict* self, PyObject* arg) {
-  int64 number = PyLong_AsLong(arg);
+  int64_t number = PyLong_AsLong(arg);
   if (number == -1 && PyErr_Occurred()) {
     return NULL;
   }
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index a0ee16f..1c2c526 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -32,15 +32,16 @@
 
 #include <google/protobuf/pyext/map_container.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
-#include <google/protobuf/map_field.h>
 #include <google/protobuf/map.h>
+#include <google/protobuf/map_field.h>
 #include <google/protobuf/message.h>
-#include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/pyext/message.h>
+#include <google/protobuf/pyext/message_factory.h>
 #include <google/protobuf/pyext/repeated_composite_container.h>
 #include <google/protobuf/pyext/scoped_pyobject_ptr.h>
 #include <google/protobuf/stubs/map_util.h>
@@ -99,7 +100,7 @@
   //
   // We store this so that if the map is modified during iteration we can throw
   // an error.
-  uint64 version;
+  uint64_t version;
 };
 
 Message* MapContainer::GetMutableMessage() {
@@ -462,10 +463,11 @@
 
 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;
   }
@@ -757,10 +759,11 @@
 }
 
 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/map_container.h b/python/google/protobuf/pyext/map_container.h
index a28945d..842602e 100644
--- a/python/google/protobuf/pyext/map_container.h
+++ b/python/google/protobuf/pyext/map_container.h
@@ -33,6 +33,7 @@
 
 #include <Python.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/descriptor.h>
@@ -56,7 +57,7 @@
 
   // We bump this whenever we perform a mutation, to invalidate existing
   // iterators.
-  uint64 version;
+  uint64_t version;
 };
 
 struct MessageMapContainer : public MapContainer {
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 4e74386..f30c6ba 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -35,6 +35,7 @@
 
 #include <structmember.h>  // A Python header file.
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <string>
@@ -196,15 +197,14 @@
 }
 
 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,
-                                   &name,
-                                   &PyTuple_Type, &bases,
-                                   &PyDict_Type, &dict)) {
+  if (!PyArg_ParseTupleAndKeywords(
+          args, kwargs, "sO!O!:type", const_cast<char**>(kwlist), &name,
+          &PyTuple_Type, &bases, &PyDict_Type, &dict)) {
     return NULL;
   }
 
@@ -546,7 +546,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();
@@ -1679,10 +1679,10 @@
     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,
-                                   &deterministic_obj)) {
+  if (!PyArg_ParseTupleAndKeywords(
+          args, kwargs, "|O", const_cast<char**>(kwlist), &deterministic_obj)) {
     return NULL;
   }
   // Preemptively convert to a bool first, so we don't need to back out of
@@ -1927,9 +1927,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;
   }
 
@@ -1942,7 +1941,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;
 
@@ -1968,9 +1968,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) {
@@ -2191,22 +2191,22 @@
   PyObject* result = NULL;
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      int32 value = reflection->GetInt32(*message, field_descriptor);
+      int32_t value = reflection->GetInt32(*message, field_descriptor);
       result = PyInt_FromLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      int64 value = reflection->GetInt64(*message, field_descriptor);
+      int64_t value = reflection->GetInt64(*message, field_descriptor);
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      uint32 value = reflection->GetUInt32(*message, field_descriptor);
+      uint32_t value = reflection->GetUInt32(*message, field_descriptor);
       result = PyInt_FromSize_t(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      uint64 value = reflection->GetUInt64(*message, field_descriptor);
+      uint64_t value = reflection->GetUInt64(*message, field_descriptor);
       result = PyLong_FromUnsignedLongLong(value);
       break;
     }
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index a1e8326..29af255 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -36,6 +36,7 @@
 
 #include <Python.h>
 
+#include <cstdint>
 #include <memory>
 #include <string>
 #include <unordered_map>
@@ -286,25 +287,25 @@
   ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED)
 
 #define GOOGLE_CHECK_GET_INT32(arg, value, err)  \
-  int32 value;                            \
+  int32_t value;                          \
   if (!CheckAndGetInteger(arg, &value)) { \
     return err;                           \
   }
 
 #define GOOGLE_CHECK_GET_INT64(arg, value, err)  \
-  int64 value;                            \
+  int64_t value;                          \
   if (!CheckAndGetInteger(arg, &value)) { \
     return err;                           \
   }
 
 #define GOOGLE_CHECK_GET_UINT32(arg, value, err) \
-  uint32 value;                           \
+  uint32_t value;                         \
   if (!CheckAndGetInteger(arg, &value)) { \
     return err;                           \
   }
 
 #define GOOGLE_CHECK_GET_UINT64(arg, value, err) \
-  uint64 value;                           \
+  uint64_t value;                         \
   if (!CheckAndGetInteger(arg, &value)) { \
     return err;                           \
   }
@@ -329,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..7905be0 100644
--- a/python/google/protobuf/pyext/message_factory.cc
+++ b/python/google/protobuf/pyext/message_factory.cc
@@ -77,9 +77,10 @@
 }
 
 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/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 5a5c4db..d76114b 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -33,6 +33,7 @@
 
 #include <google/protobuf/pyext/repeated_scalar_container.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/stubs/common.h>
@@ -207,25 +208,25 @@
   PyObject* result = nullptr;
   switch (field_descriptor->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32: {
-      int32 value =
+      int32_t value =
           reflection->GetRepeatedInt32(*message, field_descriptor, index);
       result = PyInt_FromLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_INT64: {
-      int64 value =
+      int64_t value =
           reflection->GetRepeatedInt64(*message, field_descriptor, index);
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT32: {
-      uint32 value =
+      uint32_t value =
           reflection->GetRepeatedUInt32(*message, field_descriptor, index);
       result = PyLong_FromLongLong(value);
       break;
     }
     case FieldDescriptor::CPPTYPE_UINT64: {
-      uint64 value =
+      uint64_t value =
           reflection->GetRepeatedUInt64(*message, field_descriptor, index);
       result = PyLong_FromUnsignedLongLong(value);
       break;
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index c376c7b..9c4ca90 100644
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -567,8 +567,6 @@
       self.out.write(', ')
     self.PrintFieldValue(field, value[-1])
     self.out.write(']')
-    if self.force_colon:
-      self.out.write(':')
     self.out.write(' ' if self.as_one_line else '\n')
 
   def _PrintMessageFieldValue(self, value):
@@ -1060,7 +1058,7 @@
       value_cpptype = field.message_type.fields_by_name['value'].cpp_type
       if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
         value = getattr(message, field.name)[sub_message.key]
-        value.MergeFrom(sub_message.value)
+        value.CopyFrom(sub_message.value)
       else:
         getattr(message, field.name)[sub_message.key] = sub_message.value
 
diff --git a/python/setup.py b/python/setup.py
index f97ce48..696bde2 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -18,6 +18,7 @@
 
 from distutils.command.build_py import build_py as _build_py
 from distutils.command.clean import clean as _clean
+from distutils.command.build_ext import build_ext as _build_ext
 from distutils.spawn import find_executable
 
 # Find the Protocol Compiler.
@@ -157,6 +158,22 @@
             if not any(fnmatch.fnmatchcase(fil, pat=pat) for pat in exclude)]
 
 
+class build_ext(_build_ext):
+  def get_ext_filename(self, ext_name):
+      # since python3.5, python extensions' shared libraries use a suffix that corresponds to the value
+      # of sysconfig.get_config_var('EXT_SUFFIX') and contains info about the architecture the library targets.
+      # E.g. on x64 linux the suffix is ".cpython-XYZ-x86_64-linux-gnu.so"
+      # When crosscompiling python wheels, we need to be able to override this suffix
+      # so that the resulting file name matches the target architecture and we end up with a well-formed
+      # wheel.
+      filename = _build_ext.get_ext_filename(self, ext_name)
+      orig_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
+      new_ext_suffix = os.getenv("PROTOCOL_BUFFERS_OVERRIDE_EXT_SUFFIX")
+      if new_ext_suffix and filename.endswith(orig_ext_suffix):
+        filename = filename[:-len(orig_ext_suffix)] + new_ext_suffix
+      return filename
+
+
 class test_conformance(_build_py):
   target = 'test_python'
   def run(self):
@@ -279,8 +296,6 @@
         "Programming Language :: Python :: 3.5",
         "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
-        "Programming Language :: Python :: 3.8",
-        "Programming Language :: Python :: 3.9",
         ],
       namespace_packages=['google'],
       packages=find_packages(
@@ -293,6 +308,7 @@
       cmdclass={
           'clean': clean,
           'build_py': build_py,
+          'build_ext': build_ext,
           'test_conformance': test_conformance,
       },
       install_requires=install_requires,
diff --git a/python/tox.ini b/python/tox.ini
index 9fabb6d..f9eee92 100644
--- a/python/tox.ini
+++ b/python/tox.ini
@@ -14,10 +14,9 @@
 commands =
     python setup.py -q build_py
     python: python setup.py -q build
-    # --warnings_as_errors disabled until we update the Python C extension. See:
-    # https://github.com/protocolbuffers/protobuf/issues/7930
-    # cpp: python setup.py -q build --cpp_implementation --warnings_as_errors --compile_static_extension
-    cpp: python setup.py -q build --cpp_implementation --compile_static_extension
+    # --warnings_as_errors disabled for Python 2.7 because _POSIX_C_SOURCE and _XOPEN_SOURCE are redefined
+    py27-cpp: python setup.py -q build --cpp_implementation --compile_static_extension
+    py{33,34,35,36,37,38,39}-cpp: python setup.py -q build --cpp_implementation --warnings_as_errors --compile_static_extension
     python: python setup.py -q test -q
     cpp: python setup.py -q test -q --cpp_implementation
     python: python setup.py -q test_conformance
diff --git a/ruby/ext/google/protobuf_c/protobuf.c b/ruby/ext/google/protobuf_c/protobuf.c
index 65263a4..63c7b9a 100644
--- a/ruby/ext/google/protobuf_c/protobuf.c
+++ b/ruby/ext/google/protobuf_c/protobuf.c
@@ -37,7 +37,7 @@
 #include "message.h"
 #include "repeated_field.h"
 
-VALUE cError;
+VALUE cParseError;
 VALUE cTypeError;
 
 const upb_fielddef* map_field_key(const upb_fielddef* field) {
@@ -441,8 +441,10 @@
   Map_register(protobuf);
   Message_register(protobuf);
 
-  cError = rb_const_get(protobuf, rb_intern("Error"));
+  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+  rb_gc_register_mark_object(cParseError);
   cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
+  rb_gc_register_mark_object(cTypeError);
 
   rb_define_singleton_method(protobuf, "discard_unknown",
                              Google_Protobuf_discard_unknown, 1);
diff --git a/src/Makefile.am b/src/Makefile.am
index bd5c586..648c267 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -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.cc b/src/google/protobuf/any.pb.cc
index aea98c0..5ecf63f 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -68,10 +68,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fany_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fany_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto, file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fany_2eproto);
-  return descriptor_table_google_2fprotobuf_2fany_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fany_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fany_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -165,7 +163,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string type_url = 1;
       case 1:
@@ -186,7 +183,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -323,10 +321,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fany_2eproto_getter, &descriptor_table_google_2fprotobuf_2fany_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fany_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index 91d8397..824934f 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Any;
 struct AnyDefaultTypeInternal;
@@ -70,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);
@@ -96,10 +95,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Any& default_instance() {
     return *internal_default_instance();
@@ -200,12 +199,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fany_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -218,10 +211,8 @@
   // string type_url = 1;
   void clear_type_url();
   const std::string& type_url() const;
-  void set_type_url(const std::string& value);
-  void set_type_url(std::string&& value);
-  void set_type_url(const char* value);
-  void set_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_type_url();
   std::string* release_type_url();
   void set_allocated_type_url(std::string* type_url);
@@ -234,10 +225,8 @@
   // bytes value = 2;
   void clear_value();
   const std::string& value() const;
-  void set_value(const std::string& value);
-  void set_value(std::string&& value);
-  void set_value(const char* value);
-  void set_value(const void* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_value();
   std::string* release_value();
   void set_allocated_value(std::string* value);
@@ -279,8 +268,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Any.type_url)
   return _internal_type_url();
 }
-inline void Any::set_type_url(const std::string& value) {
-  _internal_set_type_url(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Any::set_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Any.type_url)
 }
 inline std::string* Any::mutable_type_url() {
@@ -294,25 +286,6 @@
   
   type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Any::set_type_url(std::string&& value) {
-  
-  type_url_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.type_url)
-}
-inline void Any::set_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.type_url)
-}
-inline void Any::set_type_url(const char* value,
-    size_t size) {
-  
-  type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.type_url)
-}
 inline std::string* Any::_internal_mutable_type_url() {
   
   return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -340,8 +313,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Any.value)
   return _internal_value();
 }
-inline void Any::set_value(const std::string& value) {
-  _internal_set_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Any::set_value(ArgT0&& arg0, ArgT... args) {
+ 
+ value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Any.value)
 }
 inline std::string* Any::mutable_value() {
@@ -355,25 +331,6 @@
   
   value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Any::set_value(std::string&& value) {
-  
-  value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Any.value)
-}
-inline void Any::set_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Any.value)
-}
-inline void Any::set_value(const void* value,
-    size_t size) {
-  
-  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Any.value)
-}
 inline std::string* Any::_internal_mutable_value() {
   
   return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index c26b213..0f4facd 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -150,10 +150,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fapi_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fapi_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto, file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
-  return descriptor_table_google_2fprotobuf_2fapi_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fapi_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fapi_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -270,7 +268,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -343,7 +340,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -575,10 +573,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Api::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fapi_2eproto[0]);
 }
 
-
 // ===================================================================
 
 class Method::_Internal {
@@ -674,7 +673,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -739,7 +737,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -968,10 +967,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Method::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fapi_2eproto[1]);
 }
 
-
 // ===================================================================
 
 class Mixin::_Internal {
@@ -1043,7 +1043,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1065,7 +1064,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1206,10 +1206,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Mixin::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fapi_2eproto[2]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index a1ca11d..df54760 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -55,7 +55,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Api;
 struct ApiDefaultTypeInternal;
@@ -80,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);
@@ -106,10 +105,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Api& default_instance() {
     return *internal_default_instance();
@@ -177,12 +176,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -254,10 +247,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -270,10 +261,8 @@
   // string version = 4;
   void clear_version();
   const std::string& version() const;
-  void set_version(const std::string& value);
-  void set_version(std::string&& value);
-  void set_version(const char* value);
-  void set_version(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_version(ArgT0&& arg0, ArgT... args);
   std::string* mutable_version();
   std::string* release_version();
   void set_allocated_version(std::string* version);
@@ -333,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);
@@ -359,10 +348,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Method& default_instance() {
     return *internal_default_instance();
@@ -430,12 +419,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -471,10 +454,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -487,10 +468,8 @@
   // string request_type_url = 2;
   void clear_request_type_url();
   const std::string& request_type_url() const;
-  void set_request_type_url(const std::string& value);
-  void set_request_type_url(std::string&& value);
-  void set_request_type_url(const char* value);
-  void set_request_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_request_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_request_type_url();
   std::string* release_request_type_url();
   void set_allocated_request_type_url(std::string* request_type_url);
@@ -503,10 +482,8 @@
   // string response_type_url = 4;
   void clear_response_type_url();
   const std::string& response_type_url() const;
-  void set_response_type_url(const std::string& value);
-  void set_response_type_url(std::string&& value);
-  void set_response_type_url(const char* value);
-  void set_response_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_response_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_response_type_url();
   std::string* release_response_type_url();
   void set_allocated_response_type_url(std::string* response_type_url);
@@ -566,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);
@@ -592,10 +569,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Mixin& default_instance() {
     return *internal_default_instance();
@@ -663,12 +640,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fapi_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -681,10 +652,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -697,10 +666,8 @@
   // string root = 2;
   void clear_root();
   const std::string& root() const;
-  void set_root(const std::string& value);
-  void set_root(std::string&& value);
-  void set_root(const char* value);
-  void set_root(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_root(ArgT0&& arg0, ArgT... args);
   std::string* mutable_root();
   std::string* release_root();
   void set_allocated_root(std::string* root);
@@ -741,8 +708,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Api.name)
   return _internal_name();
 }
-inline void Api::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Api::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Api.name)
 }
 inline std::string* Api::mutable_name() {
@@ -756,25 +726,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Api::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.name)
-}
-inline void Api::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.name)
-}
-inline void Api::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.name)
-}
 inline std::string* Api::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -877,8 +828,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Api.version)
   return _internal_version();
 }
-inline void Api::set_version(const std::string& value) {
-  _internal_set_version(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Api::set_version(ArgT0&& arg0, ArgT... args) {
+ 
+ version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Api.version)
 }
 inline std::string* Api::mutable_version() {
@@ -892,25 +846,6 @@
   
   version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Api::set_version(std::string&& value) {
-  
-  version_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Api.version)
-}
-inline void Api::set_version(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Api.version)
-}
-inline void Api::set_version(const char* value,
-    size_t size) {
-  
-  version_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Api.version)
-}
 inline std::string* Api::_internal_mutable_version() {
   
   return version_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1078,8 +1013,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Method.name)
   return _internal_name();
 }
-inline void Method::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Method::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Method.name)
 }
 inline std::string* Method::mutable_name() {
@@ -1093,25 +1031,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Method::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.name)
-}
-inline void Method::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.name)
-}
-inline void Method::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.name)
-}
 inline std::string* Method::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1139,8 +1058,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Method.request_type_url)
   return _internal_request_type_url();
 }
-inline void Method::set_request_type_url(const std::string& value) {
-  _internal_set_request_type_url(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Method::set_request_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Method.request_type_url)
 }
 inline std::string* Method::mutable_request_type_url() {
@@ -1154,25 +1076,6 @@
   
   request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Method::set_request_type_url(std::string&& value) {
-  
-  request_type_url_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.request_type_url)
-}
-inline void Method::set_request_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.request_type_url)
-}
-inline void Method::set_request_type_url(const char* value,
-    size_t size) {
-  
-  request_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.request_type_url)
-}
 inline std::string* Method::_internal_mutable_request_type_url() {
   
   return request_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1220,8 +1123,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Method.response_type_url)
   return _internal_response_type_url();
 }
-inline void Method::set_response_type_url(const std::string& value) {
-  _internal_set_response_type_url(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Method::set_response_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Method.response_type_url)
 }
 inline std::string* Method::mutable_response_type_url() {
@@ -1235,25 +1141,6 @@
   
   response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Method::set_response_type_url(std::string&& value) {
-  
-  response_type_url_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Method.response_type_url)
-}
-inline void Method::set_response_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Method.response_type_url)
-}
-inline void Method::set_response_type_url(const char* value,
-    size_t size) {
-  
-  response_type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Method.response_type_url)
-}
 inline std::string* Method::_internal_mutable_response_type_url() {
   
   return response_type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1361,8 +1248,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Mixin.name)
   return _internal_name();
 }
-inline void Mixin::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Mixin::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Mixin.name)
 }
 inline std::string* Mixin::mutable_name() {
@@ -1376,25 +1266,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Mixin::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.name)
-}
-inline void Mixin::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.name)
-}
-inline void Mixin::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.name)
-}
 inline std::string* Mixin::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1422,8 +1293,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Mixin.root)
   return _internal_root();
 }
-inline void Mixin::set_root(const std::string& value) {
-  _internal_set_root(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Mixin::set_root(ArgT0&& arg0, ArgT... args) {
+ 
+ root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Mixin.root)
 }
 inline std::string* Mixin::mutable_root() {
@@ -1437,25 +1311,6 @@
   
   root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Mixin::set_root(std::string&& value) {
-  
-  root_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Mixin.root)
-}
-inline void Mixin::set_root(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Mixin.root)
-}
-inline void Mixin::set_root(const char* value,
-    size_t size) {
-  
-  root_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Mixin.root)
-}
 inline std::string* Mixin::_internal_mutable_root() {
   
   return root_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc
index 452d2bf..da49325 100644
--- a/src/google/protobuf/arenastring.cc
+++ b/src/google/protobuf/arenastring.cc
@@ -62,6 +62,14 @@
 }
 
 
+std::string* ArenaStringPtr::SetAndReturnNewString() {
+  std::string* new_string = new std::string();
+  tagged_ptr_.Set(new_string);
+  return new_string;
+}
+
+void ArenaStringPtr::DestroyNoArenaSlowPath() { delete UnsafeMutablePointer(); }
+
 void ArenaStringPtr::Set(const std::string* default_value,
                          ConstStringParam value, ::google::protobuf::Arena* arena) {
   if (IsDefault(default_value)) {
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index 927553c..a9eb5de 100644
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -193,6 +193,34 @@
   void Set(EmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
   void Set(NonEmptyDefault, ConstStringParam value, ::google::protobuf::Arena* arena);
   void Set(NonEmptyDefault, std::string&& value, ::google::protobuf::Arena* arena);
+  template <typename FirstParam>
+  void Set(FirstParam p1, const char* str, ::google::protobuf::Arena* arena) {
+    Set(p1, ConstStringParam(str), arena);
+  }
+  template <typename FirstParam>
+  void Set(FirstParam p1, const char* str, size_t size,
+           ::google::protobuf::Arena* arena) {
+    ConstStringParam sp{str, size};  // for string_view and `const string &`
+    Set(p1, sp, arena);
+  }
+  template <typename FirstParam, typename RefWrappedType>
+  void Set(FirstParam p1,
+           std::reference_wrapper<RefWrappedType> const_string_ref,
+           ::google::protobuf::Arena* arena) {
+    Set(p1, const_string_ref.get(), arena);
+  }
+
+  template <typename FirstParam, typename SecondParam>
+  void SetBytes(FirstParam p1, SecondParam&& p2, ::google::protobuf::Arena* arena) {
+    Set(p1, static_cast<SecondParam&&>(p2), arena);
+  }
+  template <typename FirstParam>
+  void SetBytes(FirstParam p1, const void* str, size_t size,
+                ::google::protobuf::Arena* arena) {
+    // must work whether ConstStringParam is string_view or `const string &`
+    ConstStringParam sp{static_cast<const char*>(str), size};
+    Set(p1, sp, arena);
+  }
 
   // Basic accessors.
   const std::string& Get() const PROTOBUF_NDEBUG_INLINE {
@@ -300,6 +328,12 @@
   template <typename... Lazy>
   std::string* MutableSlow(::google::protobuf::Arena* arena, const Lazy&... lazy_default);
 
+  // Sets value to a newly allocated string and returns it
+  std::string* SetAndReturnNewString();
+
+  // Destroys the non-default string value out-of-line
+  void DestroyNoArenaSlowPath();
+
 };
 
 inline void ArenaStringPtr::UnsafeSetDefault(const std::string* value) {
@@ -351,9 +385,7 @@
   // static global) and a branch to the slowpath (which calls operator new and
   // the ctor). DO NOT add any tagged-pointer operations here.
   if (IsDefault(default_value)) {
-    std::string* new_string = new std::string();
-    tagged_ptr_.Set(new_string);
-    return new_string;
+    return SetAndReturnNewString();
   } else {
     return UnsafeMutablePointer();
   }
@@ -361,7 +393,7 @@
 
 inline void ArenaStringPtr::DestroyNoArena(const std::string* default_value) {
   if (!IsDefault(default_value)) {
-    delete UnsafeMutablePointer();
+    DestroyNoArenaSlowPath();
   }
 }
 
diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc
index fb659f6..3c47aa4 100644
--- a/src/google/protobuf/compiler/annotation_test_util.cc
+++ b/src/google/protobuf/compiler/annotation_test_util.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/compiler/annotation_test_util.h>
 
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/testing/file.h>
@@ -141,8 +142,8 @@
            e = annotations.end();
        i != e; ++i) {
     const GeneratedCodeInfo::Annotation* annotation = *i;
-    uint32 begin = annotation->begin();
-    uint32 end = annotation->end();
+    uint32_t begin = annotation->begin();
+    uint32_t end = annotation->end();
     if (end < begin || end > file_content.size()) {
       return false;
     }
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 48594c4..57e81f8 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -34,6 +34,8 @@
 
 #include <google/protobuf/compiler/command_line_interface.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/platform_macros.h>
 
 #include <stdio.h>
@@ -288,7 +290,10 @@
       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 ------------------------------
@@ -300,6 +305,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);
   }
 
@@ -327,6 +333,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,
@@ -365,6 +373,7 @@
   const ErrorFormat format_;
   DiskSourceTree* tree_;
   bool found_errors_;
+  bool found_warnings_;
 };
 
 // -------------------------------------------------------------------
@@ -582,10 +591,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;
@@ -1036,16 +1047,6 @@
   }
 
 
-  for (auto fd : parsed_files) {
-    if (!AllowProto3Optional(*fd) && ContainsProto3Optional(fd)) {
-      std::cerr << fd->name()
-                << ": This file contains proto3 optional fields, but "
-                   "--experimental_allow_proto3_optional was not set."
-                << std::endl;
-      return 1;
-    }
-  }
-
   // We construct a separate GeneratorContext for each output location.  Note
   // that two code generators may output to the same location, in which case
   // they should share a single GeneratorContext so that OpenForInsert() works.
@@ -1127,7 +1128,8 @@
     }
   }
 
-  if (error_collector->FoundErrors()) {
+  if (error_collector->FoundErrors() ||
+      (fatal_warnings_ && error_collector->FoundWarnings())) {
     return 1;
   }
 
@@ -1214,13 +1216,6 @@
 
 }  // namespace
 
-bool CommandLineInterface::AllowProto3Optional(
-    const FileDescriptor& file) const {
-  // Proto3 optional is enabled by default now, the experimental flag is no
-  // longer required.
-  return true;
-}
-
 
 bool CommandLineInterface::VerifyInputFilesInDescriptors(
     DescriptorDatabase* database) {
@@ -1337,7 +1332,6 @@
   source_info_in_descriptor_set_ = false;
   disallow_services_ = false;
   direct_dependencies_explicitly_set_ = false;
-  allow_proto3_optional_ = false;
   deterministic_output_ = false;
 }
 
@@ -1648,7 +1642,7 @@
       *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.
@@ -1857,8 +1851,7 @@
 
 
   } else if (name == "--experimental_allow_proto3_optional") {
-    allow_proto3_optional_ = true;
-
+    // Flag is no longer observed, but we allow it for backward compat.
   } else if (name == "--encode" || name == "--decode" ||
              name == "--decode_raw") {
     if (mode_ != MODE_COMPILE) {
@@ -1902,6 +1895,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;
@@ -2061,6 +2060,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
@@ -2106,7 +2109,7 @@
 }
 
 bool CommandLineInterface::EnforceProto3OptionalSupport(
-    const std::string& codegen_name, uint64 supported_features,
+    const std::string& codegen_name, uint64_t supported_features,
     const std::vector<const FileDescriptor*>& parsed_files) const {
   bool supports_proto3_optional =
       supported_features & CodeGenerator::FEATURE_PROTO3_OPTIONAL;
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index 12ba653..27178b1 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -38,6 +38,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
 #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <set>
@@ -226,15 +227,10 @@
   bool MakeInputsBeProtoPathRelative(DiskSourceTree* source_tree,
                                      DescriptorDatabase* fallback_database);
 
-  // Is this .proto file whitelisted, or do we have a command-line flag allowing
-  // us to use proto3 optional? This is a temporary control to avoid people from
-  // using proto3 optional until code generators have implemented it.
-  bool AllowProto3Optional(const FileDescriptor& file) const;
-
   // Fails if these files use proto3 optional and the code generator doesn't
   // support it. This is a permanent check.
   bool EnforceProto3OptionalSupport(
-      const std::string& codegen_name, uint64 supported_features,
+      const std::string& codegen_name, uint64_t supported_features,
       const std::vector<const FileDescriptor*>& parsed_files) const;
 
 
@@ -397,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.
@@ -448,9 +447,6 @@
   // Was the --disallow_services flag used?
   bool disallow_services_ = false;
 
-  // Was the --experimental_allow_proto3_optional flag used?
-  bool allow_proto3_optional_ = false;
-
   // When using --encode, this will be passed to SetSerializationDeterministic.
   bool deterministic_output_ = false;
 
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 2bf0582..9cc8cf9 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -36,6 +36,8 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <cstdint>
+
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
@@ -157,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.
@@ -211,7 +218,7 @@
   // code generator that omits the given feature(s).
   void CreateGeneratorWithMissingFeatures(const std::string& name,
                                           const std::string& description,
-                                          uint64 features) {
+                                          uint64_t features) {
     MockCodeGenerator* generator = new MockCodeGenerator(name);
     generator->SuppressFeatures(features);
     mock_generators_to_delete_.push_back(generator);
@@ -426,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__)
@@ -515,6 +522,12 @@
                       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;
@@ -2303,7 +2316,7 @@
 }
 
 TEST_F(CommandLineInterfaceTest, InvalidErrorFormat) {
-  // Test --error_format=msvs
+  // Test invalid --error_format
 
   CreateTempFile("foo.proto",
                  "syntax = \"proto2\";\n"
@@ -2315,6 +2328,24 @@
   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
 
@@ -2378,7 +2409,6 @@
   ExpectErrorText("Missing value for flag: --test_out\n");
 }
 
-
 TEST_F(CommandLineInterfaceTest, Proto3OptionalDisallowedNoCodegenSupport) {
   CreateTempFile("google/foo.proto",
                  "syntax = \"proto3\";\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
index 7f9754f..c9b9c20 100644
--- a/src/google/protobuf/compiler/cpp/cpp_enum.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -32,10 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/cpp/cpp_enum.h>
+
+#include <cstdint>
+#include <limits>
 #include <map>
 
-#include <google/protobuf/compiler/cpp/cpp_enum.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -49,13 +53,13 @@
 // is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
 // generation of the GOOGLE_ARRAYSIZE constant.
 bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
-  int32 max_value = descriptor->value(0)->number();
+  int32_t max_value = descriptor->value(0)->number();
   for (int i = 0; i < descriptor->value_count(); i++) {
     if (descriptor->value(i)->number() > max_value) {
       max_value = descriptor->value(i)->number();
     }
   }
-  return max_value != kint32max;
+  return max_value != std::numeric_limits<int32_t>::max();
 }
 
 // Returns the number of unique numeric enum values. This is less than
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
index f95e14e..b28f6f2 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -33,6 +33,8 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/cpp/cpp_field.h>
+
+#include <cstdint>
 #include <memory>
 
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
@@ -89,7 +91,7 @@
   (*variables)["}"] = "";
 }
 
-void FieldGenerator::SetHasBitIndex(int32 has_bit_index) {
+void FieldGenerator::SetHasBitIndex(int32_t has_bit_index) {
   if (!HasHasbit(descriptor_)) {
     GOOGLE_CHECK_EQ(has_bit_index, -1);
     return;
diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
index 5a77639..b210ef9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_field.h
+++ b/src/google/protobuf/compiler/cpp/cpp_field.h
@@ -35,6 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <string>
@@ -180,7 +181,7 @@
   // are placed in the message's ByteSize() method.
   virtual void GenerateByteSize(io::Printer* printer) const = 0;
 
-  void SetHasBitIndex(int32 has_bit_index);
+  void SetHasBitIndex(int32_t has_bit_index);
 
  protected:
   const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
index 70941d8..9a0c7ab 100644
--- a/src/google/protobuf/compiler/cpp/cpp_file.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -694,10 +694,6 @@
   if (!message_generators_.empty()) {
     format("static ::$proto_ns$::Metadata $file_level_metadata$[$1$];\n",
            message_generators_.size());
-  } else {
-    format(
-        "static "
-        "constexpr ::$proto_ns$::Metadata* $file_level_metadata$ = nullptr;\n");
   }
   if (!enum_generators_.empty()) {
     format(
@@ -855,24 +851,30 @@
       "  false, $1$, $2$, $3$, \"$filename$\", \n"
       "  &$desc_table$_once, $4$, $5$, $6$,\n"
       "  schemas, file_default_instances, $tablename$::offsets,\n"
-      "  $file_level_metadata$, $file_level_enum_descriptors$, "
+      "  $7$, $file_level_enum_descriptors$, "
       "$file_level_service_descriptors$,\n"
       "};\n"
       // This function exists to be marked as weak.
-      // It can significantly speed up compilation by breaking up the SCC.
+      // It can significantly speed up compilation by breaking up LLVM's SCC in
+      // 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.
+      // the vtables and everything they use become part of the same SCC through
+      // a cycle like:
+      // GetMetadata -> descriptor table -> default instances ->
+      //   vtables -> GetMetadata
       // By adding a weak function here we break the connection from the
       // individual vtables back into the descriptor table.
-      "PROTOBUF_ATTRIBUTE_WEAK ::$proto_ns$::Metadata\n"
-      "$desc_table$_metadata_getter(int index) {\n"
-      "  ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
-      "  return $desc_table$.file_level_metadata[index];\n"
+      "PROTOBUF_ATTRIBUTE_WEAK const ::$proto_ns$::internal::DescriptorTable* "
+      "$desc_table$_getter() {\n"
+      "  return &$desc_table$;\n"
       "}\n"
       "\n",
       eager ? "true" : "false", file_data.size(), protodef_name,
       num_deps == 0 ? "nullptr" : variables_["desc_table"] + "_deps", num_deps,
-      message_generators_.size());
+      message_generators_.size(),
+      message_generators_.empty() ? "nullptr"
+                                  : variables_["file_level_metadata"]);
 
   // For descriptor.proto we want to avoid doing any dynamic initialization,
   // because in some situations that would otherwise pull in a lot of
@@ -1288,9 +1290,7 @@
   if (HasDescriptorMethods(file_, options_)) {
     format(
         "extern $dllexport_decl $const ::$proto_ns$::internal::DescriptorTable "
-        "$desc_table$;\n"
-        "$dllexport_decl $::$proto_ns$::Metadata "
-        "$desc_table$_metadata_getter(int index);\n");
+        "$desc_table$;\n");
   }
 }
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 5825af2..ceecb95 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -34,6 +34,7 @@
 
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 
+#include <cstdint>
 #include <functional>
 #include <limits>
 #include <map>
@@ -642,7 +643,7 @@
 }
 
 std::string Int32ToString(int number) {
-  if (number == kint32min) {
+  if (number == std::numeric_limits<int32_t>::min()) {
     // This needs to be special-cased, see explanation here:
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
     return StrCat(number + 1, " - 1");
@@ -651,8 +652,8 @@
   }
 }
 
-std::string Int64ToString(const std::string& macro_prefix, int64 number) {
-  if (number == kint64min) {
+std::string Int64ToString(const std::string& macro_prefix, int64_t number) {
+  if (number == std::numeric_limits<int64_t>::min()) {
     // This needs to be special-cased, see explanation here:
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52661
     return StrCat(macro_prefix, "_LONGLONG(", number + 1, ") - 1");
@@ -660,7 +661,7 @@
   return StrCat(macro_prefix, "_LONGLONG(", number, ")");
 }
 
-std::string UInt64ToString(const std::string& macro_prefix, uint64 number) {
+std::string UInt64ToString(const std::string& macro_prefix, uint64_t number) {
   return StrCat(macro_prefix, "_ULONGLONG(", number, ")");
 }
 
@@ -748,7 +749,8 @@
     } else {
       // Not alphanumeric.  To avoid any possibility of name conflicts we
       // use the hex code for the character.
-      StrAppend(&result, "_", strings::Hex(static_cast<uint8>(filename[i])));
+      StrAppend(&result, "_",
+                      strings::Hex(static_cast<uint8_t>(filename[i])));
     }
   }
   return result;
@@ -1612,7 +1614,7 @@
   }
 
   // Convert a 1 or 2 byte varint into the equivalent value upon a direct load.
-  static uint32 SmallVarintValue(uint32 x) {
+  static uint32_t SmallVarintValue(uint32_t x) {
     GOOGLE_DCHECK(x < 128 * 128);
     if (x >= 128) x += (x & 0xFF80) + 128;
     return x;
@@ -1629,7 +1631,7 @@
 
   void GenerateFieldBody(internal::WireFormatLite::WireType wiretype,
                          const FieldDescriptor* field) {
-    uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
+    uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
     switch (wiretype) {
       case WireFormatLite::WIRETYPE_VARINT: {
         std::string type = PrimitiveTypeName(options_, field->cpp_type());
@@ -1724,16 +1726,16 @@
 
   // Returns the tag for this field and in case of repeated packable fields,
   // sets a fallback tag in fallback_tag_ptr.
-  static uint32 ExpectedTag(const FieldDescriptor* field,
-                            uint32* fallback_tag_ptr) {
-    uint32 expected_tag;
+  static uint32_t ExpectedTag(const FieldDescriptor* field,
+                              uint32_t* fallback_tag_ptr) {
+    uint32_t expected_tag;
     if (field->is_packable()) {
       auto expected_wiretype = WireFormat::WireTypeForFieldType(field->type());
       expected_tag =
           WireFormatLite::MakeTag(field->number(), expected_wiretype);
       GOOGLE_CHECK(expected_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
       auto fallback_wiretype = WireFormatLite::WIRETYPE_LENGTH_DELIMITED;
-      uint32 fallback_tag =
+      uint32_t fallback_tag =
           WireFormatLite::MakeTag(field->number(), fallback_wiretype);
 
       if (field->is_packed()) std::swap(expected_tag, fallback_tag);
@@ -1752,8 +1754,7 @@
     format_(
         "while (!ctx->Done(&ptr)) {\n"
         "  $uint32$ tag;\n"
-        "  ptr = $pi_ns$::ReadTag(ptr, &tag);\n"
-        "  CHK_(ptr);\n");
+        "  ptr = $pi_ns$::ReadTag(ptr, &tag);\n");
     if (!ordered_fields.empty()) format_("  switch (tag >> 3) {\n");
 
     format_.Indent();
@@ -1763,14 +1764,14 @@
       PrintFieldComment(format_, field);
       format_("case $1$:\n", field->number());
       format_.Indent();
-      uint32 fallback_tag = 0;
-      uint32 expected_tag = ExpectedTag(field, &fallback_tag);
+      uint32_t fallback_tag = 0;
+      uint32_t expected_tag = ExpectedTag(field, &fallback_tag);
       format_(
           "if (PROTOBUF_PREDICT_TRUE(static_cast<$uint8$>(tag) == $1$)) {\n",
           expected_tag & 0xFF);
       format_.Indent();
       auto wiretype = WireFormatLite::GetTagWireType(expected_tag);
-      uint32 tag = WireFormatLite::MakeTag(field->number(), wiretype);
+      uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
       int tag_size = io::CodedOutputStream::VarintSize32(tag);
       bool is_repeat = ShouldRepeat(field, wiretype);
       if (is_repeat) {
@@ -1807,7 +1808,8 @@
     if (!ordered_fields.empty()) format_("default: {\n");
     if (!ordered_fields.empty()) format_("handle_unusual:\n");
     format_(
-        "  if ((tag & 7) == 4 || tag == 0) {\n"
+        "  if ((tag == 0) || ((tag & 7) == 4)) {\n"
+        "    CHK_(ptr);\n"
         "    ctx->SetLastTag(tag);\n"
         "    goto success;\n"
         "  }\n");
@@ -1821,9 +1823,9 @@
               descriptor->extension_range(i);
           if (i > 0) format_(" ||\n    ");
 
-          uint32 start_tag = WireFormatLite::MakeTag(
+          uint32_t start_tag = WireFormatLite::MakeTag(
               range->start, static_cast<WireFormatLite::WireType>(0));
-          uint32 end_tag = WireFormatLite::MakeTag(
+          uint32_t end_tag = WireFormatLite::MakeTag(
               range->end, static_cast<WireFormatLite::WireType>(0));
 
           if (range->end > FieldDescriptor::kMaxNumber) {
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 46d9477..43faf1c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -36,11 +36,13 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
 
 #include <algorithm>
+#include <cstdint>
 #include <iterator>
 #include <map>
 #include <string>
 
 #include <google/protobuf/compiler/cpp/cpp_options.h>
+#include <google/protobuf/compiler/cpp/cpp_names.h>
 #include <google/protobuf/compiler/scc.h>
 #include <google/protobuf/compiler/code_generator.h>
 #include <google/protobuf/descriptor.pb.h>
@@ -184,9 +186,6 @@
 // anyway, so normally this just returns field->name().
 std::string FieldName(const FieldDescriptor* field);
 
-// Get the sanitized name that should be used for the given enum in C++ code.
-std::string EnumValueName(const EnumValueDescriptor* enum_value);
-
 // Returns an estimate of the compiler's alignment for the field.  This
 // can't guarantee to be correct because the generated code could be compiled on
 // different systems with different alignment rules.  The estimates below assume
@@ -222,7 +221,7 @@
 std::string Int32ToString(int number);
 
 // Return the code that evaluates to the number when compiled.
-std::string Int64ToString(const Options& options, int64 number);
+std::string Int64ToString(const Options& options, int64_t number);
 
 // Get code that evaluates to the field's default value.
 std::string DefaultValue(const Options& options, const FieldDescriptor* field);
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 4878d18..e91a497 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/cpp/cpp_message.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <functional>
 #include <map>
 #include <memory>
@@ -76,7 +77,7 @@
 // masks is allowed to be shorter than _has_bits_, but at least one element of
 // masks must be non-zero.
 std::string ConditionalToCheckBitmasks(
-    const std::vector<uint32>& masks, bool return_success = true,
+    const std::vector<uint32_t>& masks, bool return_success = true,
     StringPiece has_bits_var = "_has_bits_") {
   std::vector<std::string> parts;
   for (int i = 0; i < masks.size(); i++) {
@@ -405,23 +406,23 @@
 // Returns a bit mask based on has_bit index of "fields" that are typically on
 // the same chunk. It is used in a group presence check where _has_bits_ is
 // masked to tell if any thing in "fields" is present.
-uint32 GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
-                    const std::vector<int>& has_bit_indices) {
+uint32_t GenChunkMask(const std::vector<const FieldDescriptor*>& fields,
+                      const std::vector<int>& has_bit_indices) {
   GOOGLE_CHECK(!fields.empty());
   int first_index_offset = has_bit_indices[fields.front()->index()] / 32;
-  uint32 chunk_mask = 0;
+  uint32_t chunk_mask = 0;
   for (auto field : fields) {
     // "index" defines where in the _has_bits_ the field appears.
     int index = has_bit_indices[field->index()];
     GOOGLE_CHECK_EQ(first_index_offset, index / 32);
-    chunk_mask |= static_cast<uint32>(1) << (index % 32);
+    chunk_mask |= static_cast<uint32_t>(1) << (index % 32);
   }
   GOOGLE_CHECK_NE(0, chunk_mask);
   return chunk_mask;
 }
 
 // Return the number of bits set in n, a non-negative integer.
-static int popcnt(uint32 n) {
+static int popcnt(uint32_t n) {
   int result = 0;
   while (n != 0) {
     result += (n & 1);
@@ -507,7 +508,7 @@
   format("if (PROTOBUF_PREDICT_FALSE(");
   int first_word = HasbitWord(chunk, 0);
   while (chunk < limit_chunk_) {
-    uint32 mask = 0;
+    uint32_t mask = 0;
     int this_word = HasbitWord(chunk, 0);
     // Generate mask for chunks on the same word.
     for (; chunk < limit_chunk_ && HasbitWord(chunk, 0) == this_word; chunk++) {
@@ -1076,19 +1077,9 @@
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
           "  void MergeFrom(const ::$proto_ns$::Message& other) final;\n"
-          "  ::$proto_ns$::Metadata GetMetadata() const final;\n"
-          "  private:\n"
-          "  static ::$proto_ns$::Metadata GetMetadataStatic() {\n"
-          "    ::$proto_ns$::internal::AssignDescriptors(&::$desc_table$);\n"
-          "    return ::$desc_table$.file_level_metadata[$1$];\n"
-          "  }\n"
-          "\n"
-          "  public:\n"
-          "};\n",
-          index_in_file_messages_);
-    } else {
-      format("};\n");
+          "  ::$proto_ns$::Metadata GetMetadata() const final;\n");
     }
+    format("};\n");
     return;
   }
 
@@ -1102,7 +1093,7 @@
 
   format(
       "inline $classname$() : $classname$(nullptr) {}\n"
-      "virtual ~$classname$();\n"
+      "~$classname$() override;\n"
       "explicit constexpr "
       "$classname$(::$proto_ns$::internal::ConstantInitialized);\n"
       "\n"
@@ -1168,10 +1159,10 @@
     // separately.
     format(
         "static const ::$proto_ns$::Descriptor* GetDescriptor() {\n"
-        "  return GetMetadataStatic().descriptor;\n"
+        "  return default_instance().GetMetadata().descriptor;\n"
         "}\n"
         "static const ::$proto_ns$::Reflection* GetReflection() {\n"
-        "  return GetMetadataStatic().reflection;\n"
+        "  return default_instance().GetMetadata().reflection;\n"
         "}\n");
   }
 
@@ -1380,12 +1371,6 @@
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
     format(
         "::$proto_ns$::Metadata GetMetadata() const final;\n"
-        "private:\n"
-        "static ::$proto_ns$::Metadata GetMetadataStatic() {\n"
-        "  return ::$desc_table$_metadata_getter(kIndexInFileMessages);\n"
-        "}\n"
-        "\n"
-        "public:\n"
         "\n");
   } else {
     format(
@@ -1670,8 +1655,8 @@
 
 // We need to calculate for each field what function the table driven code
 // should use to serialize it. This returns the index in a lookup table.
-uint32 CalcFieldNum(const FieldGenerator& generator,
-                    const FieldDescriptor* field, const Options& options) {
+uint32_t CalcFieldNum(const FieldGenerator& generator,
+                      const FieldDescriptor* field, const Options& options) {
   bool is_a_map = IsMapEntryMessage(field->containing_type());
   int type = field->type();
   if (type == FieldDescriptor::TYPE_STRING ||
@@ -1723,7 +1708,7 @@
       const FieldDescriptor* field = sorted[i];
       const FieldGenerator& generator = field_generators_.get(field);
 
-      uint32 tag = internal::WireFormatLite::MakeTag(
+      uint32_t tag = internal::WireFormatLite::MakeTag(
           field->number(), WireFormat::WireTypeForFieldType(field->type()));
 
       std::map<std::string, std::string> vars;
@@ -1780,7 +1765,7 @@
     if (i == sorted.size()) break;
     const FieldDescriptor* field = sorted[i];
 
-    uint32 tag = internal::WireFormatLite::MakeTag(
+    uint32_t tag = internal::WireFormatLite::MakeTag(
         field->number(), WireFormat::WireTypeForFieldType(field->type()));
     if (field->is_packed()) {
       tag = internal::WireFormatLite::MakeTag(
@@ -1843,7 +1828,7 @@
           tag);
     } else if (field->real_containing_oneof()) {
       format.Set("oneofoffset",
-                 sizeof(uint32) * field->containing_oneof()->index());
+                 sizeof(uint32_t) * field->containing_oneof()->index());
       format(
           "{PROTOBUF_FIELD_OFFSET($classtype$, $field_name$_), $1$,"
           " PROTOBUF_FIELD_OFFSET($classtype$, _oneof_case_) + "
@@ -1889,8 +1874,11 @@
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format(
           "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
-          "  return GetMetadataStatic();\n"
-          "}\n");
+          "  return ::$proto_ns$::internal::AssignDescriptors(\n"
+          "      &$desc_table$_getter, &$desc_table$_once,\n"
+          "      $file_level_metadata$[$1$]);\n"
+          "}\n",
+          index_in_file_messages_);
       format(
           "void $classname$::MergeFrom(\n"
           "    const ::$proto_ns$::Message& other) {\n"
@@ -1946,7 +1934,7 @@
     }
   }
   if (num_required_fields_ > 0) {
-    const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
+    const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
     format(
         "static bool MissingRequiredFields(const HasBits& has_bits) "
         "{\n"
@@ -2029,9 +2017,11 @@
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
     format(
         "::$proto_ns$::Metadata $classname$::GetMetadata() const {\n"
-        "  return GetMetadataStatic();\n"
-        "}\n"
-        "\n");
+        "  return ::$proto_ns$::internal::AssignDescriptors(\n"
+        "      &$desc_table$_getter, &$desc_table$_once,\n"
+        "      $file_level_metadata$[$1$]);\n"
+        "}\n",
+        index_in_file_messages_);
   } else {
     format(
         "std::string $classname$::GetTypeName() const {\n"
@@ -2762,7 +2752,7 @@
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
-      uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
           StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
 
@@ -3066,7 +3056,7 @@
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
-      uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
           StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
 
@@ -3456,6 +3446,12 @@
       }
     }
 
+    void EmitIfNotNull(const FieldDescriptor* field) {
+      if (field != nullptr) {
+        Emit(field);
+      }
+    }
+
     void Flush() {
       if (!v_.empty()) {
         mg_->GenerateSerializeOneofFields(format_.printer(), v_);
@@ -3482,6 +3478,61 @@
     int cached_has_bit_index_;
   };
 
+  class LazyExtensionRangeEmitter {
+   public:
+    LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* printer)
+        : mg_(mg), format_(printer) {}
+
+    void AddToRange(const Descriptor::ExtensionRange* range) {
+      if (!has_current_range_) {
+        current_combined_range_ = *range;
+        has_current_range_ = true;
+      } else {
+        current_combined_range_.start =
+            std::min(current_combined_range_.start, range->start);
+        current_combined_range_.end =
+            std::max(current_combined_range_.end, range->end);
+      }
+    }
+
+    void Flush() {
+      if (has_current_range_) {
+        mg_->GenerateSerializeOneExtensionRange(format_.printer(),
+                                                &current_combined_range_);
+      }
+      has_current_range_ = false;
+    }
+
+   private:
+    MessageGenerator* mg_;
+    Formatter format_;
+    bool has_current_range_ = false;
+    Descriptor::ExtensionRange current_combined_range_;
+  };
+
+  // We need to track the largest weak field, because weak fields are serialized
+  // differently than normal fields.  The WeakFieldMap::FieldWriter will
+  // serialize all weak fields that are ordinally between the last serialized
+  // weak field and the current field.  In order to guarantee that all weak
+  // fields are serialized, we need to make sure to emit the code to serialize
+  // the largest weak field present at some point.
+  class LargestWeakFieldHolder {
+   public:
+    const FieldDescriptor* Release() {
+      const FieldDescriptor* result = field_;
+      field_ = nullptr;
+      return result;
+    }
+    void ReplaceIfLarger(const FieldDescriptor* field) {
+      if (field_ == nullptr || field_->number() < field->number()) {
+        field_ = field;
+      }
+    }
+
+   private:
+    const FieldDescriptor* field_ = nullptr;
+  };
+
   std::vector<const FieldDescriptor*> ordered_fields =
       SortFieldsByNumber(descriptor_);
 
@@ -3505,7 +3556,8 @@
   // Merge the fields and the extension ranges, both sorted by field number.
   {
     LazySerializerEmitter e(this, printer);
-    const FieldDescriptor* last_weak_field = nullptr;
+    LazyExtensionRangeEmitter re(this, printer);
+    LargestWeakFieldHolder largest_weak_field;
     int i, j;
     for (i = 0, j = 0;
          i < ordered_fields.size() || j < sorted_extensions.size();) {
@@ -3516,31 +3568,22 @@
         if (IsFieldStripped(field, options_)) {
           continue;
         }
+        re.Flush();
         if (field->options().weak()) {
-          if (last_weak_field == nullptr ||
-              last_weak_field->number() < field->number()) {
-            last_weak_field = field;
-          }
+          largest_weak_field.ReplaceIfLarger(field);
           PrintFieldComment(format, field);
         } else {
-          if (last_weak_field != nullptr) {
-            e.Emit(last_weak_field);
-            last_weak_field = nullptr;
-          }
+          e.EmitIfNotNull(largest_weak_field.Release());
           e.Emit(field);
         }
       } else {
-        if (last_weak_field != nullptr) {
-          e.Emit(last_weak_field);
-          last_weak_field = nullptr;
-        }
+        e.EmitIfNotNull(largest_weak_field.Release());
         e.Flush();
-        GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
+        re.AddToRange(sorted_extensions[j++]);
       }
     }
-    if (last_weak_field != nullptr) {
-      e.Emit(last_weak_field);
-    }
+    re.Flush();
+    e.EmitIfNotNull(largest_weak_field.Release());
   }
 
   std::map<std::string, std::string> vars;
@@ -3655,9 +3698,9 @@
   format("}\n");
 }
 
-std::vector<uint32> MessageGenerator::RequiredFieldsBitMask() const {
+std::vector<uint32_t> MessageGenerator::RequiredFieldsBitMask() const {
   const int array_size = HasBitsSize();
-  std::vector<uint32> masks(array_size, 0);
+  std::vector<uint32_t> masks(array_size, 0);
 
   for (auto field : FieldRange(descriptor_)) {
     if (!field->is_required()) {
@@ -3665,7 +3708,8 @@
     }
 
     const int has_bit_index = has_bit_indices_[field->index()];
-    masks[has_bit_index / 32] |= static_cast<uint32>(1) << (has_bit_index % 32);
+    masks[has_bit_index / 32] |= static_cast<uint32_t>(1)
+                                 << (has_bit_index % 32);
   }
   return masks;
 }
@@ -3746,7 +3790,7 @@
   // present then the fast path executes; otherwise the slow path executes.
   if (num_required_fields_ > 1) {
     // The fast path works if all required fields are present.
-    const std::vector<uint32> masks_for_has_bits = RequiredFieldsBitMask();
+    const std::vector<uint32_t> masks_for_has_bits = RequiredFieldsBitMask();
     format("if ($1$) {  // All required fields are present.\n",
            ConditionalToCheckBitmasks(masks_for_has_bits));
     format.Indent();
@@ -3802,7 +3846,7 @@
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
-      uint32 chunk_mask = GenChunkMask(chunk, has_bit_indices_);
+      uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
           StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
index 4e3f4b9..cb1d77c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.h
+++ b/src/google/protobuf/compiler/cpp/cpp_message.h
@@ -35,9 +35,11 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 
+#include <cstdint>
 #include <memory>
 #include <set>
 #include <string>
+
 #include <google/protobuf/compiler/cpp/cpp_field.h>
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/compiler/cpp/cpp_message_layout_helper.h>
@@ -179,7 +181,7 @@
   int HasByteIndex(const FieldDescriptor* a) const;
   int HasWordIndex(const FieldDescriptor* a) const;
   bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
-  std::vector<uint32> RequiredFieldsBitMask() const;
+  std::vector<uint32_t> RequiredFieldsBitMask() const;
 
   const Descriptor* descriptor_;
   int index_in_file_messages_;
diff --git a/src/google/protobuf/compiler/cpp/cpp_names.h b/src/google/protobuf/compiler/cpp/cpp_names.h
index 9bede74..cbc69a7 100644
--- a/src/google/protobuf/compiler/cpp/cpp_names.h
+++ b/src/google/protobuf/compiler/cpp/cpp_names.h
@@ -40,6 +40,7 @@
 
 class Descriptor;
 class EnumDescriptor;
+class EnumValueDescriptor;
 class FieldDescriptor;
 
 namespace compiler {
@@ -72,6 +73,10 @@
 // anyway, so normally this just returns field->name().
 std::string FieldName(const FieldDescriptor* field);
 
+// Get the (unqualified) name that should be used for this enum value in C++
+// code.
+std::string EnumValueName(const EnumValueDescriptor* enum_value);
+
 // Strips ".proto" or ".protodevel" from the end of a filename.
 PROTOC_EXPORT std::string StripProto(const std::string& filename);
 
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
index 31f3f0c..373f38d 100644
--- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -80,13 +80,9 @@
     // Check field accessors for a required string:
     TryInsert("test.pb.h", "field_get:foo.Bar.requiredString", context);
     TryInsert("test.pb.h", "field_set:foo.Bar.requiredString", context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
     TryInsert("test.pb.h", "field_mutable:foo.Bar.requiredString", context);
     TryInsert("test.pb.h", "field_set_allocated:foo.Bar.requiredString",
               context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.requiredString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.requiredString", context);
 
     // Check field accessors for a repeated string:
     TryInsert("test.pb.h", "field_get:foo.Bar.repeatedString", context);
@@ -104,12 +100,8 @@
     // Check field accessors for a string inside oneof{}:
     TryInsert("test.pb.h", "field_get:foo.Bar.oneOfString", context);
     TryInsert("test.pb.h", "field_set:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
     TryInsert("test.pb.h", "field_mutable:foo.Bar.oneOfString", context);
     TryInsert("test.pb.h", "field_set_allocated:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_char:foo.Bar.oneOfString", context);
-    TryInsert("test.pb.h", "field_set_pointer:foo.Bar.oneOfString", context);
 
     // Check field accessors for an optional message:
     TryInsert("test.pb.h", "field_get:foo.Bar.optMessage", context);
diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
index d840492..9f7f61e 100644
--- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
@@ -33,6 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
 #include <google/protobuf/compiler/cpp/cpp_primitive_field.h>
+
 #include <google/protobuf/compiler/cpp/cpp_helpers.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -301,7 +302,7 @@
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
-  if (descriptor_->is_packed() &&
+  if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
       HasGeneratedMethods(descriptor_->file(), options_)) {
     format("mutable std::atomic<int> _$name$_cached_byte_size_;\n");
   }
@@ -409,13 +410,7 @@
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   if (descriptor_->is_packed()) {
-    if (FixedSize(descriptor_->type()) > 0) {
-      format(
-          "if (this->_internal_$name$_size() > 0) {\n"
-          "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
-          "target);\n"
-          "}\n");
-    } else {
+    if (FixedSize(descriptor_->type()) == -1) {
       format(
           "{\n"
           "  int byte_size = "
@@ -425,6 +420,12 @@
           "        $number$, _internal_$name$(), byte_size, target);\n"
           "  }\n"
           "}\n");
+    } else {
+      format(
+          "if (this->_internal_$name$_size() > 0) {\n"
+          "  target = stream->WriteFixedPacked($number$, _internal_$name$(), "
+          "target);\n"
+          "}\n");
     }
   } else {
     format(
@@ -460,11 +461,14 @@
         "  total_size += $tag_size$ +\n"
         "    ::$proto_ns$::internal::WireFormatLite::Int32Size(\n"
         "        static_cast<$int32$>(data_size));\n"
-        "}\n"
-        "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
-        "_$name$_cached_byte_size_.store(cached_size,\n"
-        "                                std::memory_order_relaxed);\n"
-        "total_size += data_size;\n");
+        "}\n");
+    if (FixedSize(descriptor_->type()) == -1) {
+      format(
+          "int cached_size = ::$proto_ns$::internal::ToCachedSize(data_size);\n"
+          "_$name$_cached_byte_size_.store(cached_size,\n"
+          "                                std::memory_order_relaxed);\n");
+    }
+    format("total_size += data_size;\n");
   } else {
     format(
         "total_size += $tag_size$ *\n"
@@ -480,7 +484,7 @@
     io::Printer* printer) const {
   Formatter format(printer, variables_);
   format("$name$_()");
-  if (descriptor_->is_packed() &&
+  if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
       HasGeneratedMethods(descriptor_->file(), options_)) {
     format("\n, _$name$_cached_byte_size_()");
   }
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index 3769437..dc9d9b8 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -82,6 +82,8 @@
                        : "lazy_variable"];
   (*variables)["pointer_type"] =
       descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char";
+  (*variables)["setter"] =
+      descriptor->type() == FieldDescriptor::TYPE_BYTES ? "SetBytes" : "Set";
   (*variables)["null_check"] = (*variables)["DCHK"] + "(value != nullptr);\n";
   // NOTE: Escaped here to unblock proto1->proto2 migration.
   // TODO(liujisi): Extend this to apply for other conflicting methods.
@@ -155,19 +157,10 @@
 
   format(
       "$deprecated_attr$const std::string& ${1$$name$$}$() const;\n"
-      "$deprecated_attr$void ${1$set_$name$$}$(const std::string& value);\n"
-      "$deprecated_attr$void ${1$set_$name$$}$(std::string&& value);\n"
-      "$deprecated_attr$void ${1$set_$name$$}$(const char* value);\n",
+      "template <typename ArgT0 = const std::string&, typename... ArgT>\n"
+      "$deprecated_attr$void ${1$set_$name$$}$(ArgT0&& arg0, ArgT... args);\n",
       descriptor_);
-  if (!options_.opensource_runtime) {
-    format(
-        "$deprecated_attr$void ${1$set_$name$$}$(::StringPiece value);\n",
-        descriptor_);
-  }
   format(
-      "$deprecated_attr$void ${1$set_$name$$}$(const $pointer_type$* "
-      "value, size_t size)"
-      ";\n"
       "$deprecated_attr$std::string* ${1$mutable_$name$$}$();\n"
       "$deprecated_attr$std::string* ${1$$release_name$$}$();\n"
       "$deprecated_attr$void ${1$set_allocated_$name$$}$(std::string* "
@@ -202,9 +195,13 @@
   format(
       "  return _internal_$name$();\n"
       "}\n"
-      "inline void $classname$::set_$name$(const std::string& value) {\n"
+      "template <typename ArgT0, typename... ArgT>\n"
+      "PROTOBUF_ALWAYS_INLINE\n"
+      "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
       "$annotate_accessor$"
-      "  _internal_set_$name$(value);\n"
+      " $set_hasbit$\n"
+      " $name$_.$setter$($default_value_tag$, static_cast<ArgT0 &&>(arg0),"
+      " args..., GetArena());\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline std::string* $classname$::mutable_$name$() {\n"
@@ -219,40 +216,8 @@
       "value) {\n"
       "  $set_hasbit$\n"
       "  $name$_.Set($default_value_tag$, value, GetArena());\n"
-      "}\n"
-      "inline void $classname$::set_$name$(std::string&& value) {\n"
-      "$annotate_accessor$"
-      "  $set_hasbit$\n"
-      "  $name$_.Set(\n"
-      "    $default_value_tag$, ::std::move(value), GetArena());\n"
-      "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
-      "}\n"
-      "inline void $classname$::set_$name$(const char* value) {\n"
-      "$annotate_accessor$"
-      "  $null_check$"
-      "  $set_hasbit$\n"
-      "  $name$_.Set($default_value_tag$, $string_piece$(value), GetArena());\n"
-      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n");
-  if (!options_.opensource_runtime) {
-    format(
-        "inline void $classname$::set_$name$(::StringPiece value) {\n"
-        "$annotate_accessor$"
-        "  $set_hasbit$\n"
-        "  $name$_.Set($default_value_tag$, value,GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
-        "}\n");
-  }
   format(
-      "inline "
-      "void $classname$::set_$name$(const $pointer_type$* value,\n"
-      "    size_t size) {\n"
-      "$annotate_accessor$"
-      "  $set_hasbit$\n"
-      "  $name$_.Set($default_value_tag$, $string_piece$(\n"
-      "      reinterpret_cast<const char*>(value), size), GetArena());\n"
-      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-      "}\n"
       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
       "  $set_hasbit$\n"
       "  return $name$_.Mutable($default_variable_or_tag$, GetArena());\n"
@@ -431,9 +396,16 @@
       "  // @@protoc_insertion_point(field_get:$full_name$)\n"
       "  return _internal_$name$();\n"
       "}\n"
-      "inline void $classname$::set_$name$(const std::string& value) {\n"
+      "template <typename ArgT0, typename... ArgT>\n"
+      "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
       "$annotate_accessor$"
-      "  _internal_set_$name$(value);\n"
+      "  if (!_internal_has_$name$()) {\n"
+      "    clear_$oneof_name$();\n"
+      "    set_has_$name$();\n"
+      "    $field_member$.UnsafeSetDefault($init_value$);\n"
+      "  }\n"
+      "  $field_member$.$setter$($default_value_tag$,"
+      " static_cast<ArgT0 &&>(arg0), args..., GetArena());\n"
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline std::string* $classname$::mutable_$name$() {\n"
@@ -455,60 +427,8 @@
       "    $field_member$.UnsafeSetDefault($init_value$);\n"
       "  }\n"
       "  $field_member$.Set($default_value_tag$, value, GetArena());\n"
-      "}\n"
-      "inline void $classname$::set_$name$(std::string&& value) {\n"
-      "$annotate_accessor$"
-      "  // @@protoc_insertion_point(field_set:$full_name$)\n"
-      "  if (!_internal_has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $field_member$.UnsafeSetDefault($init_value$);\n"
-      "  }\n"
-      "  $field_member$.Set(\n"
-      "    $default_value_tag$, ::std::move(value), GetArena());\n"
-      "  // @@protoc_insertion_point(field_set_rvalue:$full_name$)\n"
-      "}\n"
-      "inline void $classname$::set_$name$(const char* value) {\n"
-      "$annotate_accessor$"
-      "  $null_check$"
-      "  if (!_internal_has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $field_member$.UnsafeSetDefault($init_value$);\n"
-      "  }\n"
-      "  $field_member$.Set($default_value_tag$,\n"
-      "      $string_piece$(value), GetArena());\n"
-      "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
       "}\n");
-  if (!options_.opensource_runtime) {
-    format(
-        "inline void $classname$::set_$name$(::StringPiece value) {\n"
-        "$annotate_accessor$"
-        "  if (!_internal_has_$name$()) {\n"
-        "    clear_$oneof_name$();\n"
-        "    set_has_$name$();\n"
-        "    $field_member$.UnsafeSetDefault($init_value$);\n"
-        "  }\n"
-        "  $field_member$.Set($default_value_tag$, value, GetArena());\n"
-        "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
-        "}\n");
-  }
   format(
-      "inline "
-      "void $classname$::set_$name$(const $pointer_type$* value,\n"
-      "                             size_t size) {\n"
-      "$annotate_accessor$"
-      "  if (!_internal_has_$name$()) {\n"
-      "    clear_$oneof_name$();\n"
-      "    set_has_$name$();\n"
-      "    $field_member$.UnsafeSetDefault($init_value$);\n"
-      "  }\n"
-      "  $field_member$.Set(\n"
-      "      $default_value_tag$, $string_piece$(\n"
-      "      reinterpret_cast<const char*>(value), size),\n"
-      "      GetArena());\n"
-      "  // @@protoc_insertion_point(field_set_pointer:$full_name$)\n"
-      "}\n"
       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
       "  if (!_internal_has_$name$()) {\n"
       "    clear_$oneof_name$();\n"
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.inc b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
index c8238ab..a717f99 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.inc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.inc
@@ -44,6 +44,8 @@
 // correctly and produces the interfaces we expect, which is why this test
 // is written this way.
 
+#include <cstdint>
+#include <limits>
 #include <memory>
 #include <vector>
 
@@ -203,10 +205,13 @@
 TEST(GENERATED_MESSAGE_TEST_NAME, ExtremeSmallIntegerDefault) {
   const UNITTEST::TestExtremeDefaultValues& extreme_default =
       UNITTEST::TestExtremeDefaultValues::default_instance();
-  EXPECT_EQ(~0x7fffffff, kint32min);
-  EXPECT_EQ(PROTOBUF_LONGLONG(~0x7fffffffffffffff), kint64min);
-  EXPECT_EQ(kint32min, extreme_default.really_small_int32());
-  EXPECT_EQ(kint64min, extreme_default.really_small_int64());
+  EXPECT_EQ(~0x7fffffff, std::numeric_limits<int32_t>::min());
+  EXPECT_EQ(PROTOBUF_LONGLONG(~0x7fffffffffffffff),
+            std::numeric_limits<int64_t>::min());
+  EXPECT_EQ(std::numeric_limits<int32_t>::min(),
+            extreme_default.really_small_int32());
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(),
+            extreme_default.really_small_int64());
 }
 
 TEST(GENERATED_MESSAGE_TEST_NAME, Accessors) {
@@ -369,7 +374,7 @@
   UNITTEST::TestAllTypes message;
 
   TestUtil::SetAllFields(&message);
-  int64 original_value = message.optional_int64();
+  int64_t original_value = message.optional_int64();
 
   // Clear the field and make sure it shows up as cleared.
   message.clear_optional_int64();
@@ -498,7 +503,7 @@
 
   // Note the address of one of the repeated fields, to verify it was swapped
   // rather than copied.
-  const int32* addr = &message1.repeated_int32().Get(0);
+  const int32_t* addr = &message1.repeated_int32().Get(0);
 
   using std::swap;
   swap(message1, message2);
@@ -648,7 +653,7 @@
 
   // This tests concatenating.
   message2.add_repeated_int32(message1.repeated_int32(1));
-  int32 i = message1.repeated_int32(0);
+  int32_t i = message1.repeated_int32(0);
   message1.clear_repeated_int32();
   message1.add_repeated_int32(i);
 
@@ -665,8 +670,8 @@
   TestUtil::SetAllFields(&message1);
   int size = message1.ByteSizeLong();
   data.resize(size);
-  uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-  uint8* end = message1.SerializeWithCachedSizesToArray(start);
+  uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+  uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(size, end - start);
   EXPECT_TRUE(message2.ParseFromString(data));
   TestUtil::ExpectAllFieldsSet(message2);
@@ -679,8 +684,9 @@
   TestUtil::SetPackedFields(&packed_message1);
   int packed_size = packed_message1.ByteSizeLong();
   packed_data.resize(packed_size);
-  uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&packed_data));
-  uint8* end = packed_message1.SerializeWithCachedSizesToArray(start);
+  uint8_t* start =
+      reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&packed_data));
+  uint8_t* end = packed_message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(packed_size, end - start);
   EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
   TestUtil::ExpectPackedFieldsSet(packed_message2);
@@ -1846,8 +1852,8 @@
 message1.set_foo_int(123);
 int size = message1.ByteSizeLong();
 data.resize(size);
-uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-uint8* end = message1.SerializeWithCachedSizesToArray(start);
+uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
 EXPECT_EQ(size, end - start);
 EXPECT_TRUE(message2.ParseFromString(data));
 EXPECT_EQ(message2.foo_int(), 123);
@@ -1860,8 +1866,8 @@
     message1.set_foo_string("foo");
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_string(), "foo");
@@ -1875,8 +1881,8 @@
     message1.set_foo_bytes("qux");
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_bytes(), "qux");
@@ -1889,8 +1895,8 @@
     message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_enum(), UNITTEST::TestOneof2::FOO);
@@ -1903,8 +1909,8 @@
     message1.mutable_foo_message()->set_qux_int(234);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foo_message().qux_int(), 234);
@@ -1917,8 +1923,8 @@
     message1.mutable_foogroup()->set_a(345);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8* start = reinterpret_cast<uint8*>(::google::protobuf::string_as_array(&data));
-    uint8* end = message1.SerializeWithCachedSizesToArray(start);
+    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
     EXPECT_EQ(message2.foogroup().a(), 345);
diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
index d74a7ed..fea870f 100644
--- a/src/google/protobuf/compiler/java/java_context.cc
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -108,6 +108,7 @@
     InitializeFieldGeneratorInfoForMessage(message->nested_type(i));
   }
   std::vector<const FieldDescriptor*> fields;
+  fields.reserve(message->field_count());
   for (int i = 0; i < message->field_count(); ++i) {
     fields.push_back(message->field(i));
   }
diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
index 9706c6d..9a0799e 100644
--- a/src/google/protobuf/compiler/java/java_enum_field.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_enum_field.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -39,7 +42,6 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
-#include <google/protobuf/compiler/java/java_enum_field.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/io/printer.h>
@@ -67,7 +69,7 @@
   (*variables)["default_number"] =
       StrCat(descriptor->default_value_enum()->number());
   (*variables)["tag"] = StrCat(
-      static_cast<int32>(internal::WireFormat::MakeTag(descriptor)));
+      static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
index dfa051c..8403f95 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_enum_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -39,7 +42,6 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
-#include <google/protobuf/compiler/java/java_enum_field_lite.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/io/printer.h>
@@ -74,7 +76,7 @@
   (*variables)["default_number"] =
       StrCat(descriptor->default_value_enum()->number());
   (*variables)["tag"] = StrCat(
-      static_cast<int32>(internal::WireFormat::MakeTag(descriptor)));
+      static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
@@ -281,7 +283,7 @@
 }
 
 void ImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -377,7 +379,7 @@
 }
 
 void ImmutableEnumOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -632,7 +634,7 @@
 }
 
 void RepeatedImmutableEnumFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
index b5e9807..fbc1127 100644
--- a/src/google/protobuf/compiler/java/java_enum_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h
@@ -35,8 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -70,7 +72,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
@@ -95,7 +97,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
@@ -115,7 +117,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
index 9d04dc8..df6c38d 100644
--- a/src/google/protobuf/compiler/java/java_field.h
+++ b/src/google/protobuf/compiler/java/java_field.h
@@ -35,6 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
 
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <string>
@@ -104,7 +105,7 @@
   virtual void GenerateBuilderMembers(io::Printer* printer) const = 0;
   virtual void GenerateInitializationCode(io::Printer* printer) const = 0;
   virtual void GenerateFieldInfo(io::Printer* printer,
-                                 std::vector<uint16>* output) const = 0;
+                                 std::vector<uint16_t>* output) const = 0;
 
   virtual std::string GetBoxedType() const = 0;
 
diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
index 3aebf72..e32b6e3 100644
--- a/src/google/protobuf/compiler/java/java_helpers.cc
+++ b/src/google/protobuf/compiler/java/java_helpers.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_helpers.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <limits>
 #include <unordered_set>
 #include <vector>
@@ -500,11 +501,11 @@
       return StrCat(field->default_value_int32());
     case FieldDescriptor::CPPTYPE_UINT32:
       // Need to print as a signed int since Java has no unsigned.
-      return StrCat(static_cast<int32>(field->default_value_uint32()));
+      return StrCat(static_cast<int32_t>(field->default_value_uint32()));
     case FieldDescriptor::CPPTYPE_INT64:
       return StrCat(field->default_value_int64()) + "L";
     case FieldDescriptor::CPPTYPE_UINT64:
-      return StrCat(static_cast<int64>(field->default_value_uint64())) +
+      return StrCat(static_cast<int64_t>(field->default_value_uint64())) +
              "L";
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field->default_value_double();
@@ -896,11 +897,11 @@
 //
 // Note that we only use code points in [0x0000, 0xD7FF] and [0xE000, 0xFFFF].
 // There will be no surrogate pairs in the encoded character sequence.
-void WriteUInt32ToUtf16CharSequence(uint32 number,
-                                    std::vector<uint16>* output) {
+void WriteUInt32ToUtf16CharSequence(uint32_t number,
+                                    std::vector<uint16_t>* output) {
   // For values in [0x0000, 0xD7FF], only use one char to encode it.
   if (number < 0xD800) {
-    output->push_back(static_cast<uint16>(number));
+    output->push_back(static_cast<uint16_t>(number));
     return;
   }
   // Encode into multiple chars. All except the last char will be in the range
@@ -910,10 +911,10 @@
   // them.
   while (number >= 0xD800) {
     // [0xE000, 0xFFFF] can represent 13 bits of info.
-    output->push_back(static_cast<uint16>(0xE000 | (number & 0x1FFF)));
+    output->push_back(static_cast<uint16_t>(0xE000 | (number & 0x1FFF)));
     number >>= 13;
   }
-  output->push_back(static_cast<uint16>(number));
+  output->push_back(static_cast<uint16_t>(number));
 }
 
 int GetExperimentalJavaFieldTypeForSingular(const FieldDescriptor* field) {
@@ -994,7 +995,7 @@
 }
 
 // Escape a UTF-16 character to be embedded in a Java string.
-void EscapeUtf16ToString(uint16 code, std::string* output) {
+void EscapeUtf16ToString(uint16_t code, std::string* output) {
   if (code == '\t') {
     output->append("\\t");
   } else if (code == '\b') {
diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
index 8cc2f5a..5ede13c 100644
--- a/src/google/protobuf/compiler/java/java_helpers.h
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -35,7 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
 
+#include <cstdint>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
@@ -412,15 +414,16 @@
   return "V3";
 }
 
-void WriteUInt32ToUtf16CharSequence(uint32 number, std::vector<uint16>* output);
+void WriteUInt32ToUtf16CharSequence(uint32_t number,
+                                    std::vector<uint16_t>* output);
 
 inline void WriteIntToUtf16CharSequence(int value,
-                                        std::vector<uint16>* output) {
-  WriteUInt32ToUtf16CharSequence(static_cast<uint32>(value), output);
+                                        std::vector<uint16_t>* output) {
+  WriteUInt32ToUtf16CharSequence(static_cast<uint32_t>(value), output);
 }
 
 // Escape a UTF-16 character so it can be embedded in a Java string literal.
-void EscapeUtf16ToString(uint16 code, std::string* output);
+void EscapeUtf16ToString(uint16_t code, std::string* output);
 
 // Only the lowest two bytes of the return value are used. The lowest byte
 // is the integer value of a j/c/g/protobuf/FieldType enum. For the other
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
index 4fa939f..8db281d 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/compiler/java/java_map_field_lite.h>
 
+#include <cstdint>
+
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
@@ -95,9 +97,13 @@
   // We use `x.getClass()` as a null check because it generates less bytecode
   // than an `if (x == null) { throw ... }` statement.
   (*variables)["key_null_check"] =
-      IsReferenceType(keyJavaType) ? "key.getClass();" : "";
+      IsReferenceType(keyJavaType)
+          ? "java.lang.Class<?> keyClass = key.getClass();"
+          : "";
   (*variables)["value_null_check"] =
-      IsReferenceType(valueJavaType) ? "value.getClass();" : "";
+      IsReferenceType(valueJavaType)
+          ? "java.lang.Class<?> valueClass = value.getClass();"
+          : "";
 
   if (GetJavaType(value) == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
@@ -501,7 +507,7 @@
 }
 
 void ImmutableMapFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
index 49cbf6c..37aec06 100644
--- a/src/google/protobuf/compiler/java/java_map_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__
 
+#include <cstdint>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -52,7 +54,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index f9d4e43..f2df25f 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_message.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <vector>
@@ -571,6 +572,7 @@
       SortFieldsByNumber(descriptor_));
 
   std::vector<const Descriptor::ExtensionRange*> sorted_extensions;
+  sorted_extensions.reserve(descriptor_->extension_range_count());
   for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
     sorted_extensions.push_back(descriptor_->extension_range(i));
   }
@@ -1212,11 +1214,11 @@
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = sorted_fields[i];
-    uint32 tag = WireFormatLite::MakeTag(
+    uint32_t tag = WireFormatLite::MakeTag(
         field->number(), WireFormat::WireTypeForFieldType(field->type()));
 
     printer->Print("case $tag$: {\n", "tag",
-                   StrCat(static_cast<int32>(tag)));
+                   StrCat(static_cast<int32_t>(tag)));
     printer->Indent();
 
     field_generators_.get(field).GenerateParsingCode(printer);
@@ -1229,10 +1231,10 @@
     if (field->is_packable()) {
       // To make packed = true wire compatible, we generate parsing code from a
       // packed version of this field regardless of field->options().packed().
-      uint32 packed_tag = WireFormatLite::MakeTag(
+      uint32_t packed_tag = WireFormatLite::MakeTag(
           field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
       printer->Print("case $tag$: {\n", "tag",
-                     StrCat(static_cast<int32>(packed_tag)));
+                     StrCat(static_cast<int32_t>(packed_tag)));
       printer->Indent();
 
       field_generators_.get(field).GenerateParsingCodeFromPacked(printer);
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
index b17859d..73f1bcf 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -32,13 +32,15 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_message_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
 #include <google/protobuf/compiler/java/java_context.h>
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
-#include <google/protobuf/compiler/java/java_message_field_lite.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
@@ -276,7 +278,7 @@
 }
 
 void ImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -366,7 +368,7 @@
 }
 
 void ImmutableMessageOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -731,7 +733,7 @@
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
index c0a9b37..8b935e6 100644
--- a/src/google/protobuf/compiler/java/java_message_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.h
@@ -35,8 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -70,7 +72,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
@@ -95,7 +97,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
@@ -115,7 +117,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
index 4afffdc..cae9963 100644
--- a/src/google/protobuf/compiler/java/java_message_lite.cc
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -35,6 +35,7 @@
 #include <google/protobuf/compiler/java/java_message_lite.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <map>
 #include <memory>
 #include <vector>
@@ -471,7 +472,7 @@
 
   // Collect field info into a sequence of UTF-16 chars. It will be embedded
   // as a Java string in the generated code.
-  std::vector<uint16> chars;
+  std::vector<uint16_t> chars;
 
   int flags = 0;
   if (IsProto2(descriptor_->file())) {
@@ -553,7 +554,7 @@
   printer->Print("java.lang.String info =\n");
   std::string line;
   for (size_t i = 0; i < chars.size(); i++) {
-    uint16 code = chars[i];
+    uint16_t code = chars[i];
     EscapeUtf16ToString(code, &line);
     if (line.size() >= 80) {
       printer->Print("    \"$string$\" +\n", "string", line);
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
index 8bc68b7..65cc05a 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -32,6 +32,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_primitive_field.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -41,7 +44,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_primitive_field.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -112,7 +114,7 @@
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   if (IsReferenceType(GetJavaType(descriptor))) {
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
index e807066..1932e99 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -34,6 +34,7 @@
 
 #include <google/protobuf/compiler/java/java_primitive_field_lite.h>
 
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -78,7 +79,7 @@
   (*variables)["capitalized_type"] =
       GetCapitalizedType(descriptor, /* immutable = */ true);
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
@@ -127,7 +128,8 @@
   if (IsReferenceType(javaType)) {
     // We use `x.getClass()` as a null check because it generates less bytecode
     // than an `if (x == null) { throw ... }` statement.
-    (*variables)["null_check"] = "  value.getClass();\n";
+    (*variables)["null_check"] =
+        "  java.lang.Class<?> valueClass = value.getClass();\n";
   } else {
     (*variables)["null_check"] = "";
   }
@@ -303,7 +305,7 @@
 
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -384,7 +386,7 @@
 }
 
 void ImmutablePrimitiveOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -614,7 +616,7 @@
 }
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
index 5867cee..22a2557 100644
--- a/src/google/protobuf/compiler/java/java_primitive_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
@@ -35,8 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -70,7 +72,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
@@ -96,7 +98,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
 
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
@@ -116,7 +118,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
index 485fcf8..2e9a9e7 100644
--- a/src/google/protobuf/compiler/java/java_string_field.cc
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -33,6 +33,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_string_field.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -42,7 +45,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_string_field.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -71,7 +73,7 @@
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["capitalized_type"] = "String";
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["null_check"] =
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
index 25bfedc..63702c1 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc
@@ -33,6 +33,9 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include <google/protobuf/compiler/java/java_string_field_lite.h>
+
+#include <cstdint>
 #include <map>
 #include <string>
 
@@ -42,7 +45,6 @@
 #include <google/protobuf/compiler/java/java_doc_comment.h>
 #include <google/protobuf/compiler/java/java_helpers.h>
 #include <google/protobuf/compiler/java/java_name_resolver.h>
-#include <google/protobuf/compiler/java/java_string_field_lite.h>
 #include <google/protobuf/io/printer.h>
 #include <google/protobuf/wire_format.h>
 #include <google/protobuf/stubs/strutil.h>
@@ -72,12 +74,13 @@
       "= " + ImmutableDefaultValue(descriptor, name_resolver);
   (*variables)["capitalized_type"] = "java.lang.String";
   (*variables)["tag"] =
-      StrCat(static_cast<int32>(WireFormat::MakeTag(descriptor)));
+      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
   (*variables)["tag_size"] = StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // We use `x.getClass()` as a null check because it generates less bytecode
   // than an `if (x == null) { throw ... }` statement.
-  (*variables)["null_check"] = "  value.getClass();\n";
+  (*variables)["null_check"] =
+      "  java.lang.Class<?> valueClass = value.getClass();\n";
 
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
@@ -302,7 +305,7 @@
 }
 
 void ImmutableStringFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -406,7 +409,7 @@
 }
 
 void ImmutableStringOneofFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
@@ -702,7 +705,7 @@
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::GenerateFieldInfo(
-    io::Printer* printer, std::vector<uint16>* output) const {
+    io::Printer* printer, std::vector<uint16_t>* output) const {
   WriteIntToUtf16CharSequence(descriptor_->number(), output);
   WriteIntToUtf16CharSequence(GetExperimentalJavaFieldType(descriptor_),
                               output);
diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
index b67135c..194a19d 100644
--- a/src/google/protobuf/compiler/java/java_string_field_lite.h
+++ b/src/google/protobuf/compiler/java/java_string_field_lite.h
@@ -36,8 +36,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
+
 #include <google/protobuf/compiler/java/java_field.h>
 
 namespace google {
@@ -71,7 +73,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
@@ -96,7 +98,7 @@
   void GenerateMembers(io::Printer* printer) const;
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
 };
@@ -115,7 +117,7 @@
   void GenerateBuilderMembers(io::Printer* printer) const;
   void GenerateInitializationCode(io::Printer* printer) const;
   void GenerateFieldInfo(io::Printer* printer,
-                         std::vector<uint16>* output) const;
+                         std::vector<uint16_t>* output) const;
 
   std::string GetBoxedType() const;
 
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 3abb5c0..1fce106 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -34,6 +34,7 @@
 
 #include <stdlib.h>
 
+#include <cstdint>
 #include <iostream>
 #include <memory>
 #include <vector>
@@ -88,11 +89,11 @@
 MockCodeGenerator::~MockCodeGenerator() {}
 
 uint64_t MockCodeGenerator::GetSupportedFeatures() const {
-  uint64 all_features = CodeGenerator::FEATURE_PROTO3_OPTIONAL;
+  uint64_t all_features = CodeGenerator::FEATURE_PROTO3_OPTIONAL;
   return all_features & ~suppressed_features_;
 }
 
-void MockCodeGenerator::SuppressFeatures(uint64 features) {
+void MockCodeGenerator::SuppressFeatures(uint64_t features) {
   suppressed_features_ = features;
 }
 
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 9677d19..6e10105 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -33,6 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
 
+#include <cstdint>
 #include <string>
 
 #include <google/protobuf/compiler/code_generator.h>
@@ -112,11 +113,11 @@
                 GeneratorContext* context, std::string* error) const override;
 
   uint64_t GetSupportedFeatures() const override;
-  void SuppressFeatures(uint64 features);
+  void SuppressFeatures(uint64_t features);
 
  private:
   std::string name_;
-  uint64 suppressed_features_ = 0;
+  uint64_t suppressed_features_ = 0;
 
   static std::string GetOutputFileContent(const std::string& generator_name,
                                           const std::string& parameter,
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index d92cd55..b1bf288 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -38,6 +38,7 @@
 
 #include <float.h>
 
+#include <cstdint>
 #include <limits>
 #include <unordered_map>
 #include <unordered_set>
@@ -243,8 +244,9 @@
 
 bool Parser::ConsumeInteger(int* output, const char* error) {
   if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
-    uint64 value = 0;
-    if (!io::Tokenizer::ParseInteger(input_->current().text, kint32max,
+    uint64_t value = 0;
+    if (!io::Tokenizer::ParseInteger(input_->current().text,
+                                     std::numeric_limits<int32_t>::max(),
                                      &value)) {
       AddError("Integer out of range.");
       // We still return true because we did, in fact, parse an integer.
@@ -260,19 +262,19 @@
 
 bool Parser::ConsumeSignedInteger(int* output, const char* error) {
   bool is_negative = false;
-  uint64 max_value = kint32max;
+  uint64_t max_value = std::numeric_limits<int32_t>::max();
   if (TryConsume("-")) {
     is_negative = true;
     max_value += 1;
   }
-  uint64 value = 0;
+  uint64_t value = 0;
   DO(ConsumeInteger64(max_value, &value, error));
   if (is_negative) value *= -1;
   *output = value;
   return true;
 }
 
-bool Parser::ConsumeInteger64(uint64 max_value, uint64* output,
+bool Parser::ConsumeInteger64(uint64_t max_value, uint64_t* output,
                               const char* error) {
   if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
     if (!io::Tokenizer::ParseInteger(input_->current().text, max_value,
@@ -296,8 +298,9 @@
     return true;
   } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
     // Also accept integers.
-    uint64 value = 0;
-    if (!io::Tokenizer::ParseInteger(input_->current().text, kuint64max,
+    uint64_t value = 0;
+    if (!io::Tokenizer::ParseInteger(input_->current().text,
+                                     std::numeric_limits<uint64_t>::max(),
                                      &value)) {
       AddError("Integer out of range.");
       // We still return true because we did, in fact, parse a number.
@@ -829,8 +832,9 @@
 // tag number can only be determined after all options have been parsed.
 void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) {
   const bool is_message_set = IsMessageSetWireFormatMessage(*message);
-  const int max_extension_number =
-      is_message_set ? kint32max : FieldDescriptor::kMaxNumber + 1;
+  const int max_extension_number = is_message_set
+                                       ? std::numeric_limits<int32_t>::max()
+                                       : FieldDescriptor::kMaxNumber + 1;
   for (int i = 0; i < message->extension_range_size(); ++i) {
     if (message->extension_range(i).end() == kMaxRangeSentinel) {
       message->mutable_extension_range(i)->set_end(max_extension_number);
@@ -843,8 +847,9 @@
 // tag number can only be determined after all options have been parsed.
 void AdjustReservedRangesWithMaxEndNumber(DescriptorProto* message) {
   const bool is_message_set = IsMessageSetWireFormatMessage(*message);
-  const int max_field_number =
-      is_message_set ? kint32max : FieldDescriptor::kMaxNumber + 1;
+  const int max_field_number = is_message_set
+                                   ? std::numeric_limits<int32_t>::max()
+                                   : FieldDescriptor::kMaxNumber + 1;
   for (int i = 0; i < message->reserved_range_size(); ++i) {
     if (message->reserved_range(i).end() == kMaxRangeSentinel) {
       message->mutable_reserved_range(i)->set_end(max_field_number);
@@ -1260,11 +1265,11 @@
     case FieldDescriptorProto::TYPE_SINT64:
     case FieldDescriptorProto::TYPE_SFIXED32:
     case FieldDescriptorProto::TYPE_SFIXED64: {
-      uint64 max_value = kint64max;
+      uint64_t max_value = std::numeric_limits<int64_t>::max();
       if (field->type() == FieldDescriptorProto::TYPE_INT32 ||
           field->type() == FieldDescriptorProto::TYPE_SINT32 ||
           field->type() == FieldDescriptorProto::TYPE_SFIXED32) {
-        max_value = kint32max;
+        max_value = std::numeric_limits<int32_t>::max();
       }
 
       // These types can be negative.
@@ -1274,7 +1279,7 @@
         ++max_value;
       }
       // Parse the integer to verify that it is not out-of-range.
-      uint64 value;
+      uint64_t value;
       DO(ConsumeInteger64(max_value, &value,
                           "Expected integer for field default value."));
       // And stringify it again.
@@ -1286,10 +1291,10 @@
     case FieldDescriptorProto::TYPE_UINT64:
     case FieldDescriptorProto::TYPE_FIXED32:
     case FieldDescriptorProto::TYPE_FIXED64: {
-      uint64 max_value = kuint64max;
+      uint64_t max_value = std::numeric_limits<uint64_t>::max();
       if (field->type() == FieldDescriptorProto::TYPE_UINT32 ||
           field->type() == FieldDescriptorProto::TYPE_FIXED32) {
-        max_value = kuint32max;
+        max_value = std::numeric_limits<uint32_t>::max();
       }
 
       // Numeric, not negative.
@@ -1297,7 +1302,7 @@
         AddError("Unsigned field can't have negative default value.");
       }
       // Parse the integer to verify that it is not out-of-range.
-      uint64 value;
+      uint64_t value;
       DO(ConsumeInteger64(max_value, &value,
                           "Expected integer for field default value."));
       // And stringify it again.
@@ -1529,15 +1534,17 @@
       }
 
       case io::Tokenizer::TYPE_INTEGER: {
-        uint64 value;
-        uint64 max_value =
-            is_negative ? static_cast<uint64>(kint64max) + 1 : kuint64max;
+        uint64_t value;
+        uint64_t max_value =
+            is_negative
+                ? static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1
+                : std::numeric_limits<uint64_t>::max();
         DO(ConsumeInteger64(max_value, &value, "Expected integer."));
         if (is_negative) {
           value_location.AddPath(
               UninterpretedOption::kNegativeIntValueFieldNumber);
           uninterpreted_option->set_negative_int_value(
-              static_cast<int64>(-value));
+              static_cast<int64_t>(-value));
         } else {
           value_location.AddPath(
               UninterpretedOption::kPositiveIntValueFieldNumber);
@@ -2338,8 +2345,8 @@
 }
 
 bool Parser::ParseImport(RepeatedPtrField<std::string>* dependency,
-                         RepeatedField<int32>* public_dependency,
-                         RepeatedField<int32>* weak_dependency,
+                         RepeatedField<int32_t>* public_dependency,
+                         RepeatedField<int32_t>* weak_dependency,
                          const LocationRecorder& root_location,
                          const FileDescriptorProto* containing_file) {
   LocationRecorder location(root_location,
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index e8afdbc..e0ba90f 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -37,14 +37,17 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
 #define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
 #include <utility>
+
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/descriptor.h>
 #include <google/protobuf/repeated_field.h>
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -172,7 +175,8 @@
   bool ConsumeSignedInteger(int* output, const char* error);
   // Consume a 64-bit integer and store its value in "output".  If the value
   // is greater than max_value, an error will be reported.
-  bool ConsumeInteger64(uint64 max_value, uint64* output, const char* error);
+  bool ConsumeInteger64(uint64_t max_value, uint64_t* output,
+                        const char* error);
   // Consume a number and store its value in "output".  This will accept
   // tokens of either INTEGER or FLOAT type.
   bool ConsumeNumber(double* output, const char* error);
@@ -323,8 +327,8 @@
                     const LocationRecorder& root_location,
                     const FileDescriptorProto* containing_file);
   bool ParseImport(RepeatedPtrField<std::string>* dependency,
-                   RepeatedField<int32>* public_dependency,
-                   RepeatedField<int32>* weak_dependency,
+                   RepeatedField<int32_t>* public_dependency,
+                   RepeatedField<int32_t>* weak_dependency,
                    const LocationRecorder& root_location,
                    const FileDescriptorProto* containing_file);
 
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index f59504d..374a444 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -181,10 +181,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto, file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
-  return descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -307,7 +305,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 major = 1;
       case 1:
@@ -346,7 +343,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -530,10 +528,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Version::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[0]);
 }
 
-
 // ===================================================================
 
 class CodeGeneratorRequest::_Internal {
@@ -637,7 +636,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated string file_to_generate = 1;
       case 1:
@@ -687,7 +685,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -873,10 +872,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorRequest::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1]);
 }
 
-
 // ===================================================================
 
 class CodeGeneratorResponse_File::_Internal {
@@ -1001,7 +1001,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -1045,7 +1044,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1235,10 +1235,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse_File::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[2]);
 }
 
-
 // ===================================================================
 
 class CodeGeneratorResponse::_Internal {
@@ -1321,7 +1322,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string error = 1;
       case 1:
@@ -1356,7 +1356,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1520,10 +1521,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter, &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[3]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 40b2936..e2bfb2c 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -61,7 +61,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
 class CodeGeneratorRequest;
@@ -116,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);
@@ -149,10 +148,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Version& default_instance() {
     return *internal_default_instance();
@@ -220,12 +219,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -244,10 +237,8 @@
   public:
   void clear_suffix();
   const std::string& suffix() const;
-  void set_suffix(const std::string& value);
-  void set_suffix(std::string&& value);
-  void set_suffix(const char* value);
-  void set_suffix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_suffix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_suffix();
   std::string* release_suffix();
   void set_allocated_suffix(std::string* suffix);
@@ -317,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);
@@ -350,10 +341,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const CodeGeneratorRequest& default_instance() {
     return *internal_default_instance();
@@ -421,12 +412,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -487,10 +472,8 @@
   public:
   void clear_parameter();
   const std::string& parameter() const;
-  void set_parameter(const std::string& value);
-  void set_parameter(std::string&& value);
-  void set_parameter(const char* value);
-  void set_parameter(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_parameter(ArgT0&& arg0, ArgT... args);
   std::string* mutable_parameter();
   std::string* release_parameter();
   void set_allocated_parameter(std::string* parameter);
@@ -539,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);
@@ -572,10 +555,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const CodeGeneratorResponse_File& default_instance() {
     return *internal_default_instance();
@@ -643,12 +626,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -667,10 +644,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -687,10 +662,8 @@
   public:
   void clear_insertion_point();
   const std::string& insertion_point() const;
-  void set_insertion_point(const std::string& value);
-  void set_insertion_point(std::string&& value);
-  void set_insertion_point(const char* value);
-  void set_insertion_point(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_insertion_point(ArgT0&& arg0, ArgT... args);
   std::string* mutable_insertion_point();
   std::string* release_insertion_point();
   void set_allocated_insertion_point(std::string* insertion_point);
@@ -707,10 +680,8 @@
   public:
   void clear_content();
   const std::string& content() const;
-  void set_content(const std::string& value);
-  void set_content(std::string&& value);
-  void set_content(const char* value);
-  void set_content(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_content(ArgT0&& arg0, ArgT... args);
   std::string* mutable_content();
   std::string* release_content();
   void set_allocated_content(std::string* content);
@@ -759,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);
@@ -792,10 +763,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const CodeGeneratorResponse& default_instance() {
     return *internal_default_instance();
@@ -863,12 +834,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -936,10 +901,8 @@
   public:
   void clear_error();
   const std::string& error() const;
-  void set_error(const std::string& value);
-  void set_error(std::string&& value);
-  void set_error(const char* value);
-  void set_error(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_error(ArgT0&& arg0, ArgT... args);
   std::string* mutable_error();
   std::string* release_error();
   void set_allocated_error(std::string* error);
@@ -1087,8 +1050,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.suffix)
   return _internal_suffix();
 }
-inline void Version::set_suffix(const std::string& value) {
-  _internal_set_suffix(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Version::set_suffix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.suffix)
 }
 inline std::string* Version::mutable_suffix() {
@@ -1102,25 +1068,6 @@
   _has_bits_[0] |= 0x00000001u;
   suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Version::set_suffix(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.Version.suffix)
-}
-inline void Version::set_suffix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.Version.suffix)
-}
-inline void Version::set_suffix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  suffix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.Version.suffix)
-}
 inline std::string* Version::_internal_mutable_suffix() {
   _has_bits_[0] |= 0x00000001u;
   return suffix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1238,8 +1185,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter)
   return _internal_parameter();
 }
-inline void CodeGeneratorRequest::set_parameter(const std::string& value) {
-  _internal_set_parameter(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void CodeGeneratorRequest::set_parameter(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter)
 }
 inline std::string* CodeGeneratorRequest::mutable_parameter() {
@@ -1253,25 +1203,6 @@
   _has_bits_[0] |= 0x00000001u;
   parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void CodeGeneratorRequest::set_parameter(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-inline void CodeGeneratorRequest::set_parameter(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
-inline void CodeGeneratorRequest::set_parameter(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  parameter_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-}
 inline std::string* CodeGeneratorRequest::_internal_mutable_parameter() {
   _has_bits_[0] |= 0x00000001u;
   return parameter_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1434,8 +1365,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name)
   return _internal_name();
 }
-inline void CodeGeneratorResponse_File::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void CodeGeneratorResponse_File::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name)
 }
 inline std::string* CodeGeneratorResponse_File::mutable_name() {
@@ -1449,25 +1383,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void CodeGeneratorResponse_File::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-inline void CodeGeneratorResponse_File::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
-inline void CodeGeneratorResponse_File::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-}
 inline std::string* CodeGeneratorResponse_File::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1507,8 +1422,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
   return _internal_insertion_point();
 }
-inline void CodeGeneratorResponse_File::set_insertion_point(const std::string& value) {
-  _internal_set_insertion_point(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void CodeGeneratorResponse_File::set_insertion_point(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
 }
 inline std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
@@ -1522,25 +1440,6 @@
   _has_bits_[0] |= 0x00000002u;
   insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void CodeGeneratorResponse_File::set_insertion_point(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
-inline void CodeGeneratorResponse_File::set_insertion_point(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  insertion_point_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-}
 inline std::string* CodeGeneratorResponse_File::_internal_mutable_insertion_point() {
   _has_bits_[0] |= 0x00000002u;
   return insertion_point_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1580,8 +1479,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content)
   return _internal_content();
 }
-inline void CodeGeneratorResponse_File::set_content(const std::string& value) {
-  _internal_set_content(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void CodeGeneratorResponse_File::set_content(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content)
 }
 inline std::string* CodeGeneratorResponse_File::mutable_content() {
@@ -1595,25 +1497,6 @@
   _has_bits_[0] |= 0x00000004u;
   content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void CodeGeneratorResponse_File::set_content(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  content_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-inline void CodeGeneratorResponse_File::set_content(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
-inline void CodeGeneratorResponse_File::set_content(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  content_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-}
 inline std::string* CodeGeneratorResponse_File::_internal_mutable_content() {
   _has_bits_[0] |= 0x00000004u;
   return content_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1736,8 +1619,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error)
   return _internal_error();
 }
-inline void CodeGeneratorResponse::set_error(const std::string& value) {
-  _internal_set_error(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void CodeGeneratorResponse::set_error(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error)
 }
 inline std::string* CodeGeneratorResponse::mutable_error() {
@@ -1751,25 +1637,6 @@
   _has_bits_[0] |= 0x00000001u;
   error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void CodeGeneratorResponse::set_error(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  error_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-inline void CodeGeneratorResponse::set_error(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
-inline void CodeGeneratorResponse::set_error(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  error_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error)
-}
 inline std::string* CodeGeneratorResponse::_internal_mutable_error() {
   _has_bits_[0] |= 0x00000001u;
   return error_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 5ae0261..72e1d71 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -34,6 +34,9 @@
 // Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 
 #include <google/protobuf/compiler/zip_writer.h>
+
+#include <cstdint>
+
 #include <google/protobuf/io/coded_stream.h>
 
 namespace google {
@@ -42,9 +45,9 @@
 
 // January 1, 1980 as a DOS date.
 // see https://msdn.microsoft.com/en-us/library/9kkf9tah.aspx
-static const uint16 kDosEpoch = 1 << 5 | 1;
+static const uint16_t kDosEpoch = 1 << 5 | 1;
 
-static const uint32 kCRC32Table[256] = {
+static const uint32_t kCRC32Table[256] = {
     0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
     0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
     0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
@@ -89,8 +92,8 @@
     0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
     0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
 
-static uint32 ComputeCRC32(const std::string& buf) {
-  uint32 x = ~0U;
+static uint32_t ComputeCRC32(const std::string& buf) {
+  uint32_t x = ~0U;
   for (int i = 0; i < buf.size(); ++i) {
     unsigned char c = buf[i];
     x = kCRC32Table[(x ^ c) & 0xff] ^ (x >> 8);
@@ -98,10 +101,10 @@
   return ~x;
 }
 
-static void WriteShort(io::CodedOutputStream* out, uint16 val) {
-  uint8 p[2];
-  p[0] = static_cast<uint8>(val);
-  p[1] = static_cast<uint8>(val >> 8);
+static void WriteShort(io::CodedOutputStream* out, uint16_t val) {
+  uint8_t p[2];
+  p[0] = static_cast<uint8_t>(val);
+  p[1] = static_cast<uint8_t>(val >> 8);
   out->WriteRaw(p, 2);
 }
 
@@ -114,7 +117,7 @@
   FileInfo info;
 
   info.name = filename;
-  uint16 filename_size = filename.size();
+  uint16_t filename_size = filename.size();
   info.offset = raw_output_->ByteCount();
   info.size = contents.size();
   info.crc32 = ComputeCRC32(contents);
@@ -141,17 +144,17 @@
 }
 
 bool ZipWriter::WriteDirectory() {
-  uint16 num_entries = files_.size();
-  uint32 dir_ofs = raw_output_->ByteCount();
+  uint16_t num_entries = files_.size();
+  uint32_t dir_ofs = raw_output_->ByteCount();
 
   // write central directory
   io::CodedOutputStream output(raw_output_);
   for (int i = 0; i < num_entries; ++i) {
     const std::string& filename = files_[i].name;
-    uint16 filename_size = filename.size();
-    uint32 crc32 = files_[i].crc32;
-    uint32 size = files_[i].size;
-    uint32 offset = files_[i].offset;
+    uint16_t filename_size = filename.size();
+    uint32_t crc32 = files_[i].crc32;
+    uint32_t size = files_[i].size;
+    uint32_t offset = files_[i].offset;
 
     output.WriteLittleEndian32(0x02014b50);  // magic
     WriteShort(&output, 10);                 // version made by
@@ -172,7 +175,7 @@
     output.WriteLittleEndian32(offset);      // local header offset
     output.WriteString(filename);            // file name
   }
-  uint32 dir_len = output.ByteCount();
+  uint32_t dir_len = output.ByteCount();
 
   // write end of central directory marker
   output.WriteLittleEndian32(0x06054b50);  // magic
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 3a8903a..0a8a773 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -30,7 +30,9 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
+#include <cstdint>
 #include <vector>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/io/zero_copy_stream.h>
 
@@ -49,9 +51,9 @@
  private:
   struct FileInfo {
     std::string name;
-    uint32 offset;
-    uint32 size;
-    uint32 crc32;
+    uint32_t offset;
+    uint32_t size;
+    uint32_t crc32;
   };
 
   io::ZeroCopyOutputStream* raw_output_;
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index 8ceaa19..c22ae43 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -990,75 +990,74 @@
   "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
   "tion\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_"
   "SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002J\004\010&\020"
-  "\'\"\362\001\n\016MessageOptions\022&\n\027message_set_wire"
+  "\'\"\204\002\n\016MessageOptions\022&\n\027message_set_wire"
   "_format\030\001 \001(\010:\005false\022.\n\037no_standard_desc"
   "riptor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecat"
   "ed\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024un"
   "interpreted_option\030\347\007 \003(\0132$.google.proto"
-  "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\010\020\t"
-  "J\004\010\t\020\n\"\236\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#"
-  ".google.protobuf.FieldOptions.CType:\006STR"
-  "ING\022\016\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.go"
-  "ogle.protobuf.FieldOptions.JSType:\tJS_NO"
-  "RMAL\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030"
-  "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni"
-  "nterpreted_option\030\347\007 \003(\0132$.google.protob"
-  "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN"
-  "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JSTyp"
-  "e\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS_STRING\020\001\022\r\n\tJS_NU"
-  "MBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005\"^\n\014OneofOptions\022"
-  "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google."
-  "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\""
-  "\223\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\n"
-  "deprecated\030\003 \001(\010:\005false\022C\n\024uninterpreted"
-  "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
-  "pretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"}\n\020EnumVal"
-  "ueOptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024"
-  "uninterpreted_option\030\347\007 \003(\0132$.google.pro"
-  "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016"
-  "ServiceOptions\022\031\n\ndeprecated\030! \001(\010:\005fals"
+  "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005"
+  "J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020\n\"\236\003\n\014FieldOption"
+  "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field"
+  "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n"
+  "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt"
+  "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa"
+  "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n"
+  " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
+  "(\0132$.google.protobuf.UninterpretedOption"
+  "\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRIN"
+  "G_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS"
+  "_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020"
+  "\005\"^\n\014OneofOptions\022C\n\024uninterpreted_optio"
+  "n\030\347\007 \003(\0132$.google.protobuf.Uninterpreted"
+  "Option*\t\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptions\022\023\n\013all"
+  "ow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fals"
   "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
   "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200"
-  "\002\"\255\002\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:"
-  "\005false\022_\n\021idempotency_level\030\" \001(\0162/.goog"
-  "le.protobuf.MethodOptions.IdempotencyLev"
-  "el:\023IDEMPOTENCY_UNKNOWN\022C\n\024uninterpreted"
-  "_option\030\347\007 \003(\0132$.google.protobuf.Uninter"
-  "pretedOption\"P\n\020IdempotencyLevel\022\027\n\023IDEM"
-  "POTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_EFFECTS\020\001\022\016"
-  "\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterpre"
-  "tedOption\022;\n\004name\030\002 \003(\0132-.google.protobu"
-  "f.UninterpretedOption.NamePart\022\030\n\020identi"
-  "fier_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004"
-  " \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014doub"
-  "le_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017"
-  "aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tnam"
-  "e_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016S"
-  "ourceCodeInfo\022:\n\010location\030\001 \003(\0132(.google"
-  ".protobuf.SourceCodeInfo.Location\032\206\001\n\010Lo"
-  "cation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002"
-  "\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trailing"
-  "_comments\030\004 \001(\t\022!\n\031leading_detached_comm"
-  "ents\030\006 \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nanno"
-  "tation\030\001 \003(\0132-.google.protobuf.Generated"
-  "CodeInfo.Annotation\032O\n\nAnnotation\022\020\n\004pat"
-  "h\030\001 \003(\005B\002\020\001\022\023\n\013source_file\030\002 \001(\t\022\r\n\005begi"
-  "n\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~\n\023com.google.proto"
-  "bufB\020DescriptorProtosH\001Z-google.golang.o"
-  "rg/protobuf/types/descriptorpb\370\001\001\242\002\003GPB\252"
-  "\002\032Google.Protobuf.Reflection"
+  "\002J\004\010\005\020\006\"}\n\020EnumValueOptions\022\031\n\ndeprecate"
+  "d\030\001 \001(\010:\005false\022C\n\024uninterpreted_option\030\347"
+  "\007 \003(\0132$.google.protobuf.UninterpretedOpt"
+  "ion*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndepr"
+  "ecated\030! \001(\010:\005false\022C\n\024uninterpreted_opt"
+  "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+  "edOption*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n"
+  "\ndeprecated\030! \001(\010:\005false\022_\n\021idempotency_"
+  "level\030\" \001(\0162/.google.protobuf.MethodOpti"
+  "ons.IdempotencyLevel:\023IDEMPOTENCY_UNKNOW"
+  "N\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl"
+  "e.protobuf.UninterpretedOption\"P\n\020Idempo"
+  "tencyLevel\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017N"
+  "O_SIDE_EFFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200"
+  "\200\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003("
+  "\0132-.google.protobuf.UninterpretedOption."
+  "NamePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022po"
+  "sitive_int_value\030\004 \001(\004\022\032\n\022negative_int_v"
+  "alue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014stri"
+  "ng_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\032"
+  "3\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_ext"
+  "ension\030\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010locat"
+  "ion\030\001 \003(\0132(.google.protobuf.SourceCodeIn"
+  "fo.Location\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002"
+  "\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments"
+  "\030\003 \001(\t\022\031\n\021trailing_comments\030\004 \001(\t\022!\n\031lea"
+  "ding_detached_comments\030\006 \003(\t\"\247\001\n\021Generat"
+  "edCodeInfo\022A\n\nannotation\030\001 \003(\0132-.google."
+  "protobuf.GeneratedCodeInfo.Annotation\032O\n"
+  "\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source_"
+  "file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B~"
+  "\n\023com.google.protobufB\020DescriptorProtosH"
+  "\001Z-google.golang.org/protobuf/types/desc"
+  "riptorpb\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Refl"
+  "ection"
   ;
 static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once;
 const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = {
-  false, false, 6028, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", 
+  false, false, 6046, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto, "google/protobuf/descriptor.proto", 
   &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once, nullptr, 0, 27,
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto, file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
-  return descriptor_table_google_2fprotobuf_2fdescriptor_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -1291,7 +1290,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       case 1:
@@ -1307,7 +1305,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1424,10 +1423,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorSet::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[0]);
 }
 
-
 // ===================================================================
 
 class FileDescriptorProto::_Internal {
@@ -1590,7 +1590,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -1735,7 +1734,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2077,10 +2077,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[1]);
 }
 
-
 // ===================================================================
 
 class DescriptorProto_ExtensionRange::_Internal {
@@ -2177,7 +2178,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
@@ -2204,7 +2204,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2372,10 +2373,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[2]);
 }
 
-
 // ===================================================================
 
 class DescriptorProto_ReservedRange::_Internal {
@@ -2454,7 +2456,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
@@ -2474,7 +2475,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2621,10 +2623,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ReservedRange::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[3]);
 }
 
-
 // ===================================================================
 
 class DescriptorProto::_Internal {
@@ -2743,7 +2746,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -2865,7 +2867,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -3161,10 +3164,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[4]);
 }
 
-
 // ===================================================================
 
 class ExtensionRangeOptions::_Internal {
@@ -3226,7 +3230,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
@@ -3242,7 +3245,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -3377,10 +3381,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ExtensionRangeOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[5]);
 }
 
-
 // ===================================================================
 
 class FieldDescriptorProto::_Internal {
@@ -3560,7 +3565,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -3674,7 +3678,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4000,10 +4005,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[6]);
 }
 
-
 // ===================================================================
 
 class OneofDescriptorProto::_Internal {
@@ -4098,7 +4104,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -4120,7 +4125,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4271,10 +4277,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata OneofDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[7]);
 }
 
-
 // ===================================================================
 
 class EnumDescriptorProto_EnumReservedRange::_Internal {
@@ -4353,7 +4360,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
@@ -4373,7 +4379,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4520,10 +4527,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto_EnumReservedRange::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[8]);
 }
 
-
 // ===================================================================
 
 class EnumDescriptorProto::_Internal {
@@ -4627,7 +4635,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -4689,7 +4696,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -4895,10 +4903,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[9]);
 }
 
-
 // ===================================================================
 
 class EnumValueDescriptorProto::_Internal {
@@ -5001,7 +5010,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -5031,7 +5039,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -5204,10 +5213,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValueDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[10]);
 }
 
-
 // ===================================================================
 
 class ServiceDescriptorProto::_Internal {
@@ -5305,7 +5315,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -5339,7 +5348,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -5508,10 +5518,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ServiceDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[11]);
 }
 
-
 // ===================================================================
 
 class MethodDescriptorProto::_Internal {
@@ -5647,7 +5658,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
@@ -5707,7 +5717,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -5934,10 +5945,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MethodDescriptorProto::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[12]);
 }
 
-
 // ===================================================================
 
 class FileOptions::_Internal {
@@ -6189,7 +6201,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional string java_package = 1;
       case 1:
@@ -6399,7 +6410,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -6913,10 +6925,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[13]);
 }
 
-
 // ===================================================================
 
 class MessageOptions::_Internal {
@@ -7004,7 +7017,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool message_set_wire_format = 1 [default = false];
       case 1:
@@ -7052,7 +7064,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -7259,10 +7272,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MessageOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[14]);
 }
 
-
 // ===================================================================
 
 class FieldOptions::_Internal {
@@ -7359,7 +7373,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
       case 1:
@@ -7431,7 +7444,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -7670,10 +7684,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[15]);
 }
 
-
 // ===================================================================
 
 class OneofOptions::_Internal {
@@ -7735,7 +7750,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
@@ -7751,7 +7765,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -7886,10 +7901,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata OneofOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[16]);
 }
 
-
 // ===================================================================
 
 class EnumOptions::_Internal {
@@ -7971,7 +7987,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool allow_alias = 2;
       case 2:
@@ -8003,7 +8018,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8182,10 +8198,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[17]);
 }
 
-
 // ===================================================================
 
 class EnumValueOptions::_Internal {
@@ -8257,7 +8274,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 1 [default = false];
       case 1:
@@ -8281,7 +8297,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8435,10 +8452,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValueOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[18]);
 }
 
-
 // ===================================================================
 
 class ServiceOptions::_Internal {
@@ -8510,7 +8528,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33:
@@ -8534,7 +8551,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8688,10 +8706,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ServiceOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[19]);
 }
 
-
 // ===================================================================
 
 class MethodOptions::_Internal {
@@ -8776,7 +8795,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33:
@@ -8812,7 +8830,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -8993,10 +9012,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MethodOptions::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[20]);
 }
 
-
 // ===================================================================
 
 class UninterpretedOption_NamePart::_Internal {
@@ -9079,7 +9099,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // required string name_part = 1;
       case 1:
@@ -9102,7 +9121,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -9263,10 +9283,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption_NamePart::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[21]);
 }
 
-
 // ===================================================================
 
 class UninterpretedOption::_Internal {
@@ -9392,7 +9413,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
       case 2:
@@ -9462,7 +9482,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -9700,10 +9721,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[22]);
 }
 
-
 // ===================================================================
 
 class SourceCodeInfo_Location::_Internal {
@@ -9801,7 +9823,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1:
@@ -9863,7 +9884,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10085,10 +10107,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo_Location::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[23]);
 }
 
-
 // ===================================================================
 
 class SourceCodeInfo::_Internal {
@@ -10147,7 +10170,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
       case 1:
@@ -10163,7 +10185,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10279,10 +10302,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[24]);
 }
 
-
 // ===================================================================
 
 class GeneratedCodeInfo_Annotation::_Internal {
@@ -10377,7 +10401,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1:
@@ -10418,7 +10441,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10612,10 +10636,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[25]);
 }
 
-
 // ===================================================================
 
 class GeneratedCodeInfo::_Internal {
@@ -10674,7 +10699,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
       case 1:
@@ -10690,7 +10714,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -10806,10 +10831,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[26]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 587941b..27be491 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -54,7 +54,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class DescriptorProto;
 struct DescriptorProtoDefaultTypeInternal;
@@ -334,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);
@@ -367,10 +366,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FileDescriptorSet& default_instance() {
     return *internal_default_instance();
@@ -438,12 +437,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -487,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);
@@ -520,10 +513,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FileDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -591,12 +584,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -763,10 +750,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -783,10 +768,8 @@
   public:
   void clear_package();
   const std::string& package() const;
-  void set_package(const std::string& value);
-  void set_package(std::string&& value);
-  void set_package(const char* value);
-  void set_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_package();
   std::string* release_package();
   void set_allocated_package(std::string* package);
@@ -803,10 +786,8 @@
   public:
   void clear_syntax();
   const std::string& syntax() const;
-  void set_syntax(const std::string& value);
-  void set_syntax(std::string&& value);
-  void set_syntax(const char* value);
-  void set_syntax(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_syntax(ArgT0&& arg0, ArgT... args);
   std::string* mutable_syntax();
   std::string* release_syntax();
   void set_allocated_syntax(std::string* syntax);
@@ -881,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);
@@ -914,10 +895,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const DescriptorProto_ExtensionRange& default_instance() {
     return *internal_default_instance();
@@ -985,12 +966,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1065,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);
@@ -1098,10 +1073,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const DescriptorProto_ReservedRange& default_instance() {
     return *internal_default_instance();
@@ -1169,12 +1144,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1229,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);
@@ -1262,10 +1231,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const DescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -1333,12 +1302,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1516,10 +1479,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -1574,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);
@@ -1607,10 +1568,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const ExtensionRangeOptions& default_instance() {
     return *internal_default_instance();
@@ -1678,12 +1639,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1730,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);
@@ -1763,10 +1718,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FieldDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -1834,12 +1789,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1959,10 +1908,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -1979,10 +1926,8 @@
   public:
   void clear_extendee();
   const std::string& extendee() const;
-  void set_extendee(const std::string& value);
-  void set_extendee(std::string&& value);
-  void set_extendee(const char* value);
-  void set_extendee(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_extendee(ArgT0&& arg0, ArgT... args);
   std::string* mutable_extendee();
   std::string* release_extendee();
   void set_allocated_extendee(std::string* extendee);
@@ -1999,10 +1944,8 @@
   public:
   void clear_type_name();
   const std::string& type_name() const;
-  void set_type_name(const std::string& value);
-  void set_type_name(std::string&& value);
-  void set_type_name(const char* value);
-  void set_type_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_type_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_type_name();
   std::string* release_type_name();
   void set_allocated_type_name(std::string* type_name);
@@ -2019,10 +1962,8 @@
   public:
   void clear_default_value();
   const std::string& default_value() const;
-  void set_default_value(const std::string& value);
-  void set_default_value(std::string&& value);
-  void set_default_value(const char* value);
-  void set_default_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_default_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_default_value();
   std::string* release_default_value();
   void set_allocated_default_value(std::string* default_value);
@@ -2039,10 +1980,8 @@
   public:
   void clear_json_name();
   const std::string& json_name() const;
-  void set_json_name(const std::string& value);
-  void set_json_name(std::string&& value);
-  void set_json_name(const char* value);
-  void set_json_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_json_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_json_name();
   std::string* release_json_name();
   void set_allocated_json_name(std::string* json_name);
@@ -2163,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);
@@ -2196,10 +2135,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const OneofDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -2267,12 +2206,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -2289,10 +2222,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -2339,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);
@@ -2372,10 +2303,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const EnumDescriptorProto_EnumReservedRange& default_instance() {
     return *internal_default_instance();
@@ -2443,12 +2374,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -2503,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);
@@ -2536,10 +2461,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const EnumDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -2607,12 +2532,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -2694,10 +2613,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -2747,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);
@@ -2780,10 +2697,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const EnumValueDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -2851,12 +2768,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -2874,10 +2785,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -2938,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);
@@ -2971,10 +2880,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const ServiceDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -3042,12 +2951,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -3083,10 +2986,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -3134,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);
@@ -3167,10 +3068,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const MethodDescriptorProto& default_instance() {
     return *internal_default_instance();
@@ -3238,12 +3139,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -3264,10 +3159,8 @@
   public:
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -3284,10 +3177,8 @@
   public:
   void clear_input_type();
   const std::string& input_type() const;
-  void set_input_type(const std::string& value);
-  void set_input_type(std::string&& value);
-  void set_input_type(const char* value);
-  void set_input_type(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_input_type(ArgT0&& arg0, ArgT... args);
   std::string* mutable_input_type();
   std::string* release_input_type();
   void set_allocated_input_type(std::string* input_type);
@@ -3304,10 +3195,8 @@
   public:
   void clear_output_type();
   const std::string& output_type() const;
-  void set_output_type(const std::string& value);
-  void set_output_type(std::string&& value);
-  void set_output_type(const char* value);
-  void set_output_type(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_output_type(ArgT0&& arg0, ArgT... args);
   std::string* mutable_output_type();
   std::string* release_output_type();
   void set_allocated_output_type(std::string* output_type);
@@ -3384,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);
@@ -3417,10 +3306,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FileOptions& default_instance() {
     return *internal_default_instance();
@@ -3488,12 +3377,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -3579,10 +3462,8 @@
   public:
   void clear_java_package();
   const std::string& java_package() const;
-  void set_java_package(const std::string& value);
-  void set_java_package(std::string&& value);
-  void set_java_package(const char* value);
-  void set_java_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_java_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_java_package();
   std::string* release_java_package();
   void set_allocated_java_package(std::string* java_package);
@@ -3599,10 +3480,8 @@
   public:
   void clear_java_outer_classname();
   const std::string& java_outer_classname() const;
-  void set_java_outer_classname(const std::string& value);
-  void set_java_outer_classname(std::string&& value);
-  void set_java_outer_classname(const char* value);
-  void set_java_outer_classname(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_java_outer_classname(ArgT0&& arg0, ArgT... args);
   std::string* mutable_java_outer_classname();
   std::string* release_java_outer_classname();
   void set_allocated_java_outer_classname(std::string* java_outer_classname);
@@ -3619,10 +3498,8 @@
   public:
   void clear_go_package();
   const std::string& go_package() const;
-  void set_go_package(const std::string& value);
-  void set_go_package(std::string&& value);
-  void set_go_package(const char* value);
-  void set_go_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_go_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_go_package();
   std::string* release_go_package();
   void set_allocated_go_package(std::string* go_package);
@@ -3639,10 +3516,8 @@
   public:
   void clear_objc_class_prefix();
   const std::string& objc_class_prefix() const;
-  void set_objc_class_prefix(const std::string& value);
-  void set_objc_class_prefix(std::string&& value);
-  void set_objc_class_prefix(const char* value);
-  void set_objc_class_prefix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_objc_class_prefix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_objc_class_prefix();
   std::string* release_objc_class_prefix();
   void set_allocated_objc_class_prefix(std::string* objc_class_prefix);
@@ -3659,10 +3534,8 @@
   public:
   void clear_csharp_namespace();
   const std::string& csharp_namespace() const;
-  void set_csharp_namespace(const std::string& value);
-  void set_csharp_namespace(std::string&& value);
-  void set_csharp_namespace(const char* value);
-  void set_csharp_namespace(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_csharp_namespace(ArgT0&& arg0, ArgT... args);
   std::string* mutable_csharp_namespace();
   std::string* release_csharp_namespace();
   void set_allocated_csharp_namespace(std::string* csharp_namespace);
@@ -3679,10 +3552,8 @@
   public:
   void clear_swift_prefix();
   const std::string& swift_prefix() const;
-  void set_swift_prefix(const std::string& value);
-  void set_swift_prefix(std::string&& value);
-  void set_swift_prefix(const char* value);
-  void set_swift_prefix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_swift_prefix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_swift_prefix();
   std::string* release_swift_prefix();
   void set_allocated_swift_prefix(std::string* swift_prefix);
@@ -3699,10 +3570,8 @@
   public:
   void clear_php_class_prefix();
   const std::string& php_class_prefix() const;
-  void set_php_class_prefix(const std::string& value);
-  void set_php_class_prefix(std::string&& value);
-  void set_php_class_prefix(const char* value);
-  void set_php_class_prefix(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_php_class_prefix(ArgT0&& arg0, ArgT... args);
   std::string* mutable_php_class_prefix();
   std::string* release_php_class_prefix();
   void set_allocated_php_class_prefix(std::string* php_class_prefix);
@@ -3719,10 +3588,8 @@
   public:
   void clear_php_namespace();
   const std::string& php_namespace() const;
-  void set_php_namespace(const std::string& value);
-  void set_php_namespace(std::string&& value);
-  void set_php_namespace(const char* value);
-  void set_php_namespace(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_php_namespace(ArgT0&& arg0, ArgT... args);
   std::string* mutable_php_namespace();
   std::string* release_php_namespace();
   void set_allocated_php_namespace(std::string* php_namespace);
@@ -3739,10 +3606,8 @@
   public:
   void clear_php_metadata_namespace();
   const std::string& php_metadata_namespace() const;
-  void set_php_metadata_namespace(const std::string& value);
-  void set_php_metadata_namespace(std::string&& value);
-  void set_php_metadata_namespace(const char* value);
-  void set_php_metadata_namespace(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_php_metadata_namespace(ArgT0&& arg0, ArgT... args);
   std::string* mutable_php_metadata_namespace();
   std::string* release_php_metadata_namespace();
   void set_allocated_php_metadata_namespace(std::string* php_metadata_namespace);
@@ -3759,10 +3624,8 @@
   public:
   void clear_ruby_package();
   const std::string& ruby_package() const;
-  void set_ruby_package(const std::string& value);
-  void set_ruby_package(std::string&& value);
-  void set_ruby_package(const char* value);
-  void set_ruby_package(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_ruby_package(ArgT0&& arg0, ArgT... args);
   std::string* mutable_ruby_package();
   std::string* release_ruby_package();
   void set_allocated_ruby_package(std::string* ruby_package);
@@ -3943,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);
@@ -3976,10 +3839,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const MessageOptions& default_instance() {
     return *internal_default_instance();
@@ -4047,12 +3910,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -4160,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);
@@ -4193,10 +4050,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FieldOptions& default_instance() {
     return *internal_default_instance();
@@ -4264,12 +4121,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -4471,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);
@@ -4504,10 +4355,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const OneofOptions& default_instance() {
     return *internal_default_instance();
@@ -4575,12 +4426,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -4627,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);
@@ -4660,10 +4505,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const EnumOptions& default_instance() {
     return *internal_default_instance();
@@ -4731,12 +4576,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -4814,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);
@@ -4847,10 +4686,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const EnumValueOptions& default_instance() {
     return *internal_default_instance();
@@ -4918,12 +4757,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -4986,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);
@@ -5019,10 +4852,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const ServiceOptions& default_instance() {
     return *internal_default_instance();
@@ -5090,12 +4923,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -5158,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);
@@ -5191,10 +5018,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const MethodOptions& default_instance() {
     return *internal_default_instance();
@@ -5262,12 +5089,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -5377,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);
@@ -5410,10 +5231,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const UninterpretedOption_NamePart& default_instance() {
     return *internal_default_instance();
@@ -5481,12 +5302,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -5503,10 +5318,8 @@
   public:
   void clear_name_part();
   const std::string& name_part() const;
-  void set_name_part(const std::string& value);
-  void set_name_part(std::string&& value);
-  void set_name_part(const char* value);
-  void set_name_part(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name_part(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name_part();
   std::string* release_name_part();
   void set_allocated_name_part(std::string* name_part);
@@ -5551,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);
@@ -5584,10 +5397,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const UninterpretedOption& default_instance() {
     return *internal_default_instance();
@@ -5655,12 +5468,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -5702,10 +5509,8 @@
   public:
   void clear_identifier_value();
   const std::string& identifier_value() const;
-  void set_identifier_value(const std::string& value);
-  void set_identifier_value(std::string&& value);
-  void set_identifier_value(const char* value);
-  void set_identifier_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_identifier_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_identifier_value();
   std::string* release_identifier_value();
   void set_allocated_identifier_value(std::string* identifier_value);
@@ -5722,10 +5527,8 @@
   public:
   void clear_string_value();
   const std::string& string_value() const;
-  void set_string_value(const std::string& value);
-  void set_string_value(std::string&& value);
-  void set_string_value(const char* value);
-  void set_string_value(const void* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_string_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_string_value();
   std::string* release_string_value();
   void set_allocated_string_value(std::string* string_value);
@@ -5742,10 +5545,8 @@
   public:
   void clear_aggregate_value();
   const std::string& aggregate_value() const;
-  void set_aggregate_value(const std::string& value);
-  void set_aggregate_value(std::string&& value);
-  void set_aggregate_value(const char* value);
-  void set_aggregate_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_aggregate_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_aggregate_value();
   std::string* release_aggregate_value();
   void set_allocated_aggregate_value(std::string* aggregate_value);
@@ -5818,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);
@@ -5851,10 +5652,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const SourceCodeInfo_Location& default_instance() {
     return *internal_default_instance();
@@ -5922,12 +5723,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -6015,10 +5810,8 @@
   public:
   void clear_leading_comments();
   const std::string& leading_comments() const;
-  void set_leading_comments(const std::string& value);
-  void set_leading_comments(std::string&& value);
-  void set_leading_comments(const char* value);
-  void set_leading_comments(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_leading_comments(ArgT0&& arg0, ArgT... args);
   std::string* mutable_leading_comments();
   std::string* release_leading_comments();
   void set_allocated_leading_comments(std::string* leading_comments);
@@ -6035,10 +5828,8 @@
   public:
   void clear_trailing_comments();
   const std::string& trailing_comments() const;
-  void set_trailing_comments(const std::string& value);
-  void set_trailing_comments(std::string&& value);
-  void set_trailing_comments(const char* value);
-  void set_trailing_comments(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_trailing_comments(ArgT0&& arg0, ArgT... args);
   std::string* mutable_trailing_comments();
   std::string* release_trailing_comments();
   void set_allocated_trailing_comments(std::string* trailing_comments);
@@ -6072,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);
@@ -6105,10 +5896,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const SourceCodeInfo& default_instance() {
     return *internal_default_instance();
@@ -6176,12 +5967,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -6227,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);
@@ -6260,10 +6045,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const GeneratedCodeInfo_Annotation& default_instance() {
     return *internal_default_instance();
@@ -6331,12 +6116,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -6377,10 +6156,8 @@
   public:
   void clear_source_file();
   const std::string& source_file() const;
-  void set_source_file(const std::string& value);
-  void set_source_file(std::string&& value);
-  void set_source_file(const char* value);
-  void set_source_file(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_source_file(ArgT0&& arg0, ArgT... args);
   std::string* mutable_source_file();
   std::string* release_source_file();
   void set_allocated_source_file(std::string* source_file);
@@ -6438,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);
@@ -6471,10 +6248,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const GeneratedCodeInfo& default_instance() {
     return *internal_default_instance();
@@ -6542,12 +6319,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -6657,8 +6428,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name)
   return _internal_name();
 }
-inline void FileDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name)
 }
 inline std::string* FileDescriptorProto::mutable_name() {
@@ -6672,25 +6446,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.name)
-}
-inline void FileDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name)
-}
-inline void FileDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name)
-}
 inline std::string* FileDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -6730,8 +6485,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package)
   return _internal_package();
 }
-inline void FileDescriptorProto::set_package(const std::string& value) {
-  _internal_set_package(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileDescriptorProto::set_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package)
 }
 inline std::string* FileDescriptorProto::mutable_package() {
@@ -6745,25 +6503,6 @@
   _has_bits_[0] |= 0x00000002u;
   package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileDescriptorProto::set_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  package_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.package)
-}
-inline void FileDescriptorProto::set_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package)
-}
-inline void FileDescriptorProto::set_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package)
-}
 inline std::string* FileDescriptorProto::_internal_mutable_package() {
   _has_bits_[0] |= 0x00000002u;
   return package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -7293,8 +7032,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax)
   return _internal_syntax();
 }
-inline void FileDescriptorProto::set_syntax(const std::string& value) {
-  _internal_set_syntax(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileDescriptorProto::set_syntax(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax)
 }
 inline std::string* FileDescriptorProto::mutable_syntax() {
@@ -7308,25 +7050,6 @@
   _has_bits_[0] |= 0x00000004u;
   syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileDescriptorProto::set_syntax(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileDescriptorProto.syntax)
-}
-inline void FileDescriptorProto::set_syntax(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax)
-}
-inline void FileDescriptorProto::set_syntax(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  syntax_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax)
-}
 inline std::string* FileDescriptorProto::_internal_mutable_syntax() {
   _has_bits_[0] |= 0x00000004u;
   return syntax_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -7573,8 +7296,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name)
   return _internal_name();
 }
-inline void DescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void DescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name)
 }
 inline std::string* DescriptorProto::mutable_name() {
@@ -7588,25 +7314,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void DescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.DescriptorProto.name)
-}
-inline void DescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name)
-}
-inline void DescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name)
-}
 inline std::string* DescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8123,8 +7830,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name)
   return _internal_name();
 }
-inline void FieldDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FieldDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name)
 }
 inline std::string* FieldDescriptorProto::mutable_name() {
@@ -8138,25 +7848,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FieldDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.name)
-}
-inline void FieldDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name)
-}
-inline void FieldDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name)
-}
 inline std::string* FieldDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8282,8 +7973,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name)
   return _internal_type_name();
 }
-inline void FieldDescriptorProto::set_type_name(const std::string& value) {
-  _internal_set_type_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FieldDescriptorProto::set_type_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name)
 }
 inline std::string* FieldDescriptorProto::mutable_type_name() {
@@ -8297,25 +7991,6 @@
   _has_bits_[0] |= 0x00000004u;
   type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FieldDescriptorProto::set_type_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.type_name)
-}
-inline void FieldDescriptorProto::set_type_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name)
-}
-inline void FieldDescriptorProto::set_type_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  type_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name)
-}
 inline std::string* FieldDescriptorProto::_internal_mutable_type_name() {
   _has_bits_[0] |= 0x00000004u;
   return type_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8355,8 +8030,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee)
   return _internal_extendee();
 }
-inline void FieldDescriptorProto::set_extendee(const std::string& value) {
-  _internal_set_extendee(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FieldDescriptorProto::set_extendee(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee)
 }
 inline std::string* FieldDescriptorProto::mutable_extendee() {
@@ -8370,25 +8048,6 @@
   _has_bits_[0] |= 0x00000002u;
   extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FieldDescriptorProto::set_extendee(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.extendee)
-}
-inline void FieldDescriptorProto::set_extendee(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee)
-}
-inline void FieldDescriptorProto::set_extendee(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  extendee_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee)
-}
 inline std::string* FieldDescriptorProto::_internal_mutable_extendee() {
   _has_bits_[0] |= 0x00000002u;
   return extendee_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8428,8 +8087,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value)
   return _internal_default_value();
 }
-inline void FieldDescriptorProto::set_default_value(const std::string& value) {
-  _internal_set_default_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FieldDescriptorProto::set_default_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000008u;
+ default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value)
 }
 inline std::string* FieldDescriptorProto::mutable_default_value() {
@@ -8443,25 +8105,6 @@
   _has_bits_[0] |= 0x00000008u;
   default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FieldDescriptorProto::set_default_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.default_value)
-}
-inline void FieldDescriptorProto::set_default_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value)
-}
-inline void FieldDescriptorProto::set_default_value(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000008u;
-  default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value)
-}
 inline std::string* FieldDescriptorProto::_internal_mutable_default_value() {
   _has_bits_[0] |= 0x00000008u;
   return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8529,8 +8172,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.json_name)
   return _internal_json_name();
 }
-inline void FieldDescriptorProto::set_json_name(const std::string& value) {
-  _internal_set_json_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FieldDescriptorProto::set_json_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000010u;
+ json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.json_name)
 }
 inline std::string* FieldDescriptorProto::mutable_json_name() {
@@ -8544,25 +8190,6 @@
   _has_bits_[0] |= 0x00000010u;
   json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FieldDescriptorProto::set_json_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FieldDescriptorProto.json_name)
-}
-inline void FieldDescriptorProto::set_json_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.json_name)
-}
-inline void FieldDescriptorProto::set_json_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000010u;
-  json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.json_name)
-}
 inline std::string* FieldDescriptorProto::_internal_mutable_json_name() {
   _has_bits_[0] |= 0x00000010u;
   return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8717,8 +8344,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name)
   return _internal_name();
 }
-inline void OneofDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void OneofDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name)
 }
 inline std::string* OneofDescriptorProto::mutable_name() {
@@ -8732,25 +8362,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void OneofDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.OneofDescriptorProto.name)
-}
-inline void OneofDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name)
-}
-inline void OneofDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name)
-}
 inline std::string* OneofDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -8937,8 +8548,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name)
   return _internal_name();
 }
-inline void EnumDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void EnumDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name)
 }
 inline std::string* EnumDescriptorProto::mutable_name() {
@@ -8952,25 +8566,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void EnumDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumDescriptorProto.name)
-}
-inline void EnumDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name)
-}
-inline void EnumDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name)
-}
 inline std::string* EnumDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -9249,8 +8844,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name)
   return _internal_name();
 }
-inline void EnumValueDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void EnumValueDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name)
 }
 inline std::string* EnumValueDescriptorProto::mutable_name() {
@@ -9264,25 +8862,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void EnumValueDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValueDescriptorProto.name)
-}
-inline void EnumValueDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name)
-}
-inline void EnumValueDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name)
-}
 inline std::string* EnumValueDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -9437,8 +9016,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name)
   return _internal_name();
 }
-inline void ServiceDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void ServiceDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name)
 }
 inline std::string* ServiceDescriptorProto::mutable_name() {
@@ -9452,25 +9034,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void ServiceDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.ServiceDescriptorProto.name)
-}
-inline void ServiceDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name)
-}
-inline void ServiceDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name)
-}
 inline std::string* ServiceDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -9636,8 +9199,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name)
   return _internal_name();
 }
-inline void MethodDescriptorProto::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void MethodDescriptorProto::set_name(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name)
 }
 inline std::string* MethodDescriptorProto::mutable_name() {
@@ -9651,25 +9217,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void MethodDescriptorProto::set_name(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.name)
-}
-inline void MethodDescriptorProto::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name)
-}
-inline void MethodDescriptorProto::set_name(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name)
-}
 inline std::string* MethodDescriptorProto::_internal_mutable_name() {
   _has_bits_[0] |= 0x00000001u;
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -9709,8 +9256,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type)
   return _internal_input_type();
 }
-inline void MethodDescriptorProto::set_input_type(const std::string& value) {
-  _internal_set_input_type(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void MethodDescriptorProto::set_input_type(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type)
 }
 inline std::string* MethodDescriptorProto::mutable_input_type() {
@@ -9724,25 +9274,6 @@
   _has_bits_[0] |= 0x00000002u;
   input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void MethodDescriptorProto::set_input_type(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.input_type)
-}
-inline void MethodDescriptorProto::set_input_type(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type)
-}
-inline void MethodDescriptorProto::set_input_type(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  input_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type)
-}
 inline std::string* MethodDescriptorProto::_internal_mutable_input_type() {
   _has_bits_[0] |= 0x00000002u;
   return input_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -9782,8 +9313,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type)
   return _internal_output_type();
 }
-inline void MethodDescriptorProto::set_output_type(const std::string& value) {
-  _internal_set_output_type(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void MethodDescriptorProto::set_output_type(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type)
 }
 inline std::string* MethodDescriptorProto::mutable_output_type() {
@@ -9797,25 +9331,6 @@
   _has_bits_[0] |= 0x00000004u;
   output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void MethodDescriptorProto::set_output_type(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.MethodDescriptorProto.output_type)
-}
-inline void MethodDescriptorProto::set_output_type(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type)
-}
-inline void MethodDescriptorProto::set_output_type(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  output_type_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type)
-}
 inline std::string* MethodDescriptorProto::_internal_mutable_output_type() {
   _has_bits_[0] |= 0x00000004u;
   return output_type_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -9998,8 +9513,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package)
   return _internal_java_package();
 }
-inline void FileOptions::set_java_package(const std::string& value) {
-  _internal_set_java_package(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_java_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package)
 }
 inline std::string* FileOptions::mutable_java_package() {
@@ -10013,25 +9531,6 @@
   _has_bits_[0] |= 0x00000001u;
   java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_java_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_package)
-}
-inline void FileOptions::set_java_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package)
-}
-inline void FileOptions::set_java_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  java_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package)
-}
 inline std::string* FileOptions::_internal_mutable_java_package() {
   _has_bits_[0] |= 0x00000001u;
   return java_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10071,8 +9570,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname)
   return _internal_java_outer_classname();
 }
-inline void FileOptions::set_java_outer_classname(const std::string& value) {
-  _internal_set_java_outer_classname(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_java_outer_classname(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname)
 }
 inline std::string* FileOptions::mutable_java_outer_classname() {
@@ -10086,25 +9588,6 @@
   _has_bits_[0] |= 0x00000002u;
   java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_java_outer_classname(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.java_outer_classname)
-}
-inline void FileOptions::set_java_outer_classname(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname)
-}
-inline void FileOptions::set_java_outer_classname(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  java_outer_classname_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname)
-}
 inline std::string* FileOptions::_internal_mutable_java_outer_classname() {
   _has_bits_[0] |= 0x00000002u;
   return java_outer_classname_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10257,8 +9740,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package)
   return _internal_go_package();
 }
-inline void FileOptions::set_go_package(const std::string& value) {
-  _internal_set_go_package(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_go_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package)
 }
 inline std::string* FileOptions::mutable_go_package() {
@@ -10272,25 +9758,6 @@
   _has_bits_[0] |= 0x00000004u;
   go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_go_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.go_package)
-}
-inline void FileOptions::set_go_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package)
-}
-inline void FileOptions::set_go_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  go_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package)
-}
 inline std::string* FileOptions::_internal_mutable_go_package() {
   _has_bits_[0] |= 0x00000004u;
   return go_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10498,8 +9965,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix)
   return _internal_objc_class_prefix();
 }
-inline void FileOptions::set_objc_class_prefix(const std::string& value) {
-  _internal_set_objc_class_prefix(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_objc_class_prefix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000008u;
+ objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix)
 }
 inline std::string* FileOptions::mutable_objc_class_prefix() {
@@ -10513,25 +9983,6 @@
   _has_bits_[0] |= 0x00000008u;
   objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_objc_class_prefix(std::string&& value) {
-  _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.objc_class_prefix)
-}
-inline void FileOptions::set_objc_class_prefix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix)
-}
-inline void FileOptions::set_objc_class_prefix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000008u;
-  objc_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix)
-}
 inline std::string* FileOptions::_internal_mutable_objc_class_prefix() {
   _has_bits_[0] |= 0x00000008u;
   return objc_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10571,8 +10022,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace)
   return _internal_csharp_namespace();
 }
-inline void FileOptions::set_csharp_namespace(const std::string& value) {
-  _internal_set_csharp_namespace(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_csharp_namespace(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000010u;
+ csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace)
 }
 inline std::string* FileOptions::mutable_csharp_namespace() {
@@ -10586,25 +10040,6 @@
   _has_bits_[0] |= 0x00000010u;
   csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_csharp_namespace(std::string&& value) {
-  _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.csharp_namespace)
-}
-inline void FileOptions::set_csharp_namespace(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace)
-}
-inline void FileOptions::set_csharp_namespace(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000010u;
-  csharp_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace)
-}
 inline std::string* FileOptions::_internal_mutable_csharp_namespace() {
   _has_bits_[0] |= 0x00000010u;
   return csharp_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10644,8 +10079,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.swift_prefix)
   return _internal_swift_prefix();
 }
-inline void FileOptions::set_swift_prefix(const std::string& value) {
-  _internal_set_swift_prefix(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_swift_prefix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000020u;
+ swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.swift_prefix)
 }
 inline std::string* FileOptions::mutable_swift_prefix() {
@@ -10659,25 +10097,6 @@
   _has_bits_[0] |= 0x00000020u;
   swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_swift_prefix(std::string&& value) {
-  _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.swift_prefix)
-}
-inline void FileOptions::set_swift_prefix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.swift_prefix)
-}
-inline void FileOptions::set_swift_prefix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000020u;
-  swift_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.swift_prefix)
-}
 inline std::string* FileOptions::_internal_mutable_swift_prefix() {
   _has_bits_[0] |= 0x00000020u;
   return swift_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10717,8 +10136,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_class_prefix)
   return _internal_php_class_prefix();
 }
-inline void FileOptions::set_php_class_prefix(const std::string& value) {
-  _internal_set_php_class_prefix(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_php_class_prefix(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000040u;
+ php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_class_prefix)
 }
 inline std::string* FileOptions::mutable_php_class_prefix() {
@@ -10732,25 +10154,6 @@
   _has_bits_[0] |= 0x00000040u;
   php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_php_class_prefix(std::string&& value) {
-  _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_class_prefix)
-}
-inline void FileOptions::set_php_class_prefix(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_class_prefix)
-}
-inline void FileOptions::set_php_class_prefix(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000040u;
-  php_class_prefix_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_class_prefix)
-}
 inline std::string* FileOptions::_internal_mutable_php_class_prefix() {
   _has_bits_[0] |= 0x00000040u;
   return php_class_prefix_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10790,8 +10193,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_namespace)
   return _internal_php_namespace();
 }
-inline void FileOptions::set_php_namespace(const std::string& value) {
-  _internal_set_php_namespace(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_php_namespace(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000080u;
+ php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_namespace)
 }
 inline std::string* FileOptions::mutable_php_namespace() {
@@ -10805,25 +10211,6 @@
   _has_bits_[0] |= 0x00000080u;
   php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_php_namespace(std::string&& value) {
-  _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_namespace)
-}
-inline void FileOptions::set_php_namespace(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_namespace)
-}
-inline void FileOptions::set_php_namespace(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000080u;
-  php_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_namespace)
-}
 inline std::string* FileOptions::_internal_mutable_php_namespace() {
   _has_bits_[0] |= 0x00000080u;
   return php_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10863,8 +10250,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.php_metadata_namespace)
   return _internal_php_metadata_namespace();
 }
-inline void FileOptions::set_php_metadata_namespace(const std::string& value) {
-  _internal_set_php_metadata_namespace(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_php_metadata_namespace(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000100u;
+ php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.php_metadata_namespace)
 }
 inline std::string* FileOptions::mutable_php_metadata_namespace() {
@@ -10878,25 +10268,6 @@
   _has_bits_[0] |= 0x00000100u;
   php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_php_metadata_namespace(std::string&& value) {
-  _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.php_metadata_namespace)
-}
-inline void FileOptions::set_php_metadata_namespace(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.php_metadata_namespace)
-}
-inline void FileOptions::set_php_metadata_namespace(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000100u;
-  php_metadata_namespace_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.php_metadata_namespace)
-}
 inline std::string* FileOptions::_internal_mutable_php_metadata_namespace() {
   _has_bits_[0] |= 0x00000100u;
   return php_metadata_namespace_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -10936,8 +10307,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.ruby_package)
   return _internal_ruby_package();
 }
-inline void FileOptions::set_ruby_package(const std::string& value) {
-  _internal_set_ruby_package(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void FileOptions::set_ruby_package(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000200u;
+ ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.ruby_package)
 }
 inline std::string* FileOptions::mutable_ruby_package() {
@@ -10951,25 +10325,6 @@
   _has_bits_[0] |= 0x00000200u;
   ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void FileOptions::set_ruby_package(std::string&& value) {
-  _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.FileOptions.ruby_package)
-}
-inline void FileOptions::set_ruby_package(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.ruby_package)
-}
-inline void FileOptions::set_ruby_package(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000200u;
-  ruby_package_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.ruby_package)
-}
 inline std::string* FileOptions::_internal_mutable_ruby_package() {
   _has_bits_[0] |= 0x00000200u;
   return ruby_package_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -11804,8 +11159,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part)
   return _internal_name_part();
 }
-inline void UninterpretedOption_NamePart::set_name_part(const std::string& value) {
-  _internal_set_name_part(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void UninterpretedOption_NamePart::set_name_part(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part)
 }
 inline std::string* UninterpretedOption_NamePart::mutable_name_part() {
@@ -11819,25 +11177,6 @@
   _has_bits_[0] |= 0x00000001u;
   name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void UninterpretedOption_NamePart::set_name_part(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.NamePart.name_part)
-}
-inline void UninterpretedOption_NamePart::set_name_part(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part)
-}
-inline void UninterpretedOption_NamePart::set_name_part(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  name_part_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part)
-}
 inline std::string* UninterpretedOption_NamePart::_internal_mutable_name_part() {
   _has_bits_[0] |= 0x00000001u;
   return name_part_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -11948,8 +11287,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value)
   return _internal_identifier_value();
 }
-inline void UninterpretedOption::set_identifier_value(const std::string& value) {
-  _internal_set_identifier_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void UninterpretedOption::set_identifier_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value)
 }
 inline std::string* UninterpretedOption::mutable_identifier_value() {
@@ -11963,25 +11305,6 @@
   _has_bits_[0] |= 0x00000001u;
   identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void UninterpretedOption::set_identifier_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.identifier_value)
-}
-inline void UninterpretedOption::set_identifier_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value)
-}
-inline void UninterpretedOption::set_identifier_value(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  identifier_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value)
-}
 inline std::string* UninterpretedOption::_internal_mutable_identifier_value() {
   _has_bits_[0] |= 0x00000001u;
   return identifier_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -12105,8 +11428,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value)
   return _internal_string_value();
 }
-inline void UninterpretedOption::set_string_value(const std::string& value) {
-  _internal_set_string_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void UninterpretedOption::set_string_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ string_value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value)
 }
 inline std::string* UninterpretedOption::mutable_string_value() {
@@ -12120,25 +11446,6 @@
   _has_bits_[0] |= 0x00000002u;
   string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void UninterpretedOption::set_string_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.string_value)
-}
-inline void UninterpretedOption::set_string_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value)
-}
-inline void UninterpretedOption::set_string_value(const void* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value)
-}
 inline std::string* UninterpretedOption::_internal_mutable_string_value() {
   _has_bits_[0] |= 0x00000002u;
   return string_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -12178,8 +11485,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value)
   return _internal_aggregate_value();
 }
-inline void UninterpretedOption::set_aggregate_value(const std::string& value) {
-  _internal_set_aggregate_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void UninterpretedOption::set_aggregate_value(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000004u;
+ aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value)
 }
 inline std::string* UninterpretedOption::mutable_aggregate_value() {
@@ -12193,25 +11503,6 @@
   _has_bits_[0] |= 0x00000004u;
   aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void UninterpretedOption::set_aggregate_value(std::string&& value) {
-  _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.UninterpretedOption.aggregate_value)
-}
-inline void UninterpretedOption::set_aggregate_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value)
-}
-inline void UninterpretedOption::set_aggregate_value(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000004u;
-  aggregate_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value)
-}
 inline std::string* UninterpretedOption::_internal_mutable_aggregate_value() {
   _has_bits_[0] |= 0x00000004u;
   return aggregate_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -12349,8 +11640,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments)
   return _internal_leading_comments();
 }
-inline void SourceCodeInfo_Location::set_leading_comments(const std::string& value) {
-  _internal_set_leading_comments(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void SourceCodeInfo_Location::set_leading_comments(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments)
 }
 inline std::string* SourceCodeInfo_Location::mutable_leading_comments() {
@@ -12364,25 +11658,6 @@
   _has_bits_[0] |= 0x00000001u;
   leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void SourceCodeInfo_Location::set_leading_comments(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.leading_comments)
-}
-inline void SourceCodeInfo_Location::set_leading_comments(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments)
-}
-inline void SourceCodeInfo_Location::set_leading_comments(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  leading_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments)
-}
 inline std::string* SourceCodeInfo_Location::_internal_mutable_leading_comments() {
   _has_bits_[0] |= 0x00000001u;
   return leading_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -12422,8 +11697,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments)
   return _internal_trailing_comments();
 }
-inline void SourceCodeInfo_Location::set_trailing_comments(const std::string& value) {
-  _internal_set_trailing_comments(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void SourceCodeInfo_Location::set_trailing_comments(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000002u;
+ trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments)
 }
 inline std::string* SourceCodeInfo_Location::mutable_trailing_comments() {
@@ -12437,25 +11715,6 @@
   _has_bits_[0] |= 0x00000002u;
   trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void SourceCodeInfo_Location::set_trailing_comments(std::string&& value) {
-  _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-}
-inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-}
-inline void SourceCodeInfo_Location::set_trailing_comments(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000002u;
-  trailing_comments_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-}
 inline std::string* SourceCodeInfo_Location::_internal_mutable_trailing_comments() {
   _has_bits_[0] |= 0x00000002u;
   return trailing_comments_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -12663,8 +11922,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
   return _internal_source_file();
 }
-inline void GeneratedCodeInfo_Annotation::set_source_file(const std::string& value) {
-  _internal_set_source_file(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void GeneratedCodeInfo_Annotation::set_source_file(ArgT0&& arg0, ArgT... args) {
+ _has_bits_[0] |= 0x00000001u;
+ source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
 }
 inline std::string* GeneratedCodeInfo_Annotation::mutable_source_file() {
@@ -12678,25 +11940,6 @@
   _has_bits_[0] |= 0x00000001u;
   source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void GeneratedCodeInfo_Annotation::set_source_file(std::string&& value) {
-  _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-}
-inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-}
-inline void GeneratedCodeInfo_Annotation::set_source_file(const char* value,
-    size_t size) {
-  _has_bits_[0] |= 0x00000001u;
-  source_file_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-}
 inline std::string* GeneratedCodeInfo_Annotation::_internal_mutable_source_file() {
   _has_bits_[0] |= 0x00000001u;
   return source_file_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 9f0ce6c..156e410 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -348,17 +348,17 @@
   optional string java_package = 1;
 
 
-  // If set, all the classes from the .proto file are wrapped in a single
-  // outer class with the given name.  This applies to both Proto1
-  // (equivalent to the old "--one_java_file" option) and Proto2 (where
-  // a .proto always translates to a single class, but you may want to
-  // explicitly choose the class name).
+  // Controls the name of the wrapper Java class generated for the .proto file.
+  // That class will always contain the .proto file's getDescriptor() method as
+  // well as any top-level extensions defined in the .proto file.
+  // If java_multiple_files is disabled, then all the other classes from the
+  // .proto file will be nested inside the single wrapper outer class.
   optional string java_outer_classname = 8;
 
-  // If set true, then the Java code generator will generate a separate .java
+  // If enabled, then the Java code generator will generate a separate .java
   // file for each top-level message, enum, and service defined in the .proto
-  // file.  Thus, these types will *not* be nested inside the outer class
-  // named by java_outer_classname.  However, the outer class will still be
+  // file.  Thus, these types will *not* be nested inside the wrapper class
+  // named by java_outer_classname.  However, the wrapper class will still be
   // generated to contain the file's getDescriptor() method as well as any
   // top-level extensions defined in the file.
   optional bool java_multiple_files = 10 [default = false];
@@ -496,6 +496,8 @@
   // this is a formalization for deprecating messages.
   optional bool deprecated = 3 [default = false];
 
+  reserved 4, 5, 6;
+
   // Whether the message is an automatically generated map entry type for the
   // maps field.
   //
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index d04e32b..01cd8d7 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -67,10 +67,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fduration_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fduration_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto, file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
-  return descriptor_table_google_2fprotobuf_2fduration_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fduration_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fduration_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -142,7 +140,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1:
@@ -160,7 +157,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -297,10 +295,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Duration::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fduration_2eproto_getter, &descriptor_table_google_2fprotobuf_2fduration_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fduration_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index 36a3015..0aedba4 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Duration;
 struct DurationDefaultTypeInternal;
@@ -70,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);
@@ -96,10 +95,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Duration& default_instance() {
     return *internal_default_instance();
@@ -167,12 +166,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fduration_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 42d7f3b..b2149ab 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -62,10 +62,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fempty_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fempty_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto, file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
-  return descriptor_table_google_2fprotobuf_2fempty_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fempty_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fempty_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -127,8 +125,8 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -225,10 +223,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Empty::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fempty_2eproto_getter, &descriptor_table_google_2fprotobuf_2fempty_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fempty_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index 7dcab19..289e557 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Empty;
 struct EmptyDefaultTypeInternal;
@@ -70,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);
@@ -96,10 +95,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Empty& default_instance() {
     return *internal_default_instance();
@@ -167,12 +166,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fempty_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 5a23fc7..5890bb2 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -65,10 +65,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto, file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
-  return descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -133,7 +131,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated string paths = 1;
       case 1:
@@ -151,7 +148,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -270,10 +268,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldMask::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter, &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index 153d9dd..355dff4 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class FieldMask;
 struct FieldMaskDefaultTypeInternal;
@@ -70,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);
@@ -96,10 +95,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FieldMask& default_instance() {
     return *internal_default_instance();
@@ -167,12 +166,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index b2ffe1f..3260e30 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -2520,6 +2520,17 @@
 
 namespace internal {
 
+Metadata AssignDescriptors(const DescriptorTable* (*table)(),
+                           internal::once_flag* once,
+                           const Metadata& metadata) {
+  call_once(*once, [=] {
+    auto* t = table();
+    AssignDescriptorsImpl(t, t->is_eager);
+  });
+
+  return metadata;
+}
+
 void AssignDescriptors(const DescriptorTable* table, bool eager) {
   if (!eager) eager = table->is_eager;
   call_once(*table->once, AssignDescriptorsImpl, table, eager);
diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
index 5916cb7..b34f722 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -290,6 +290,14 @@
 void PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* table,
                                        bool eager = false);
 
+// Overload used to implement GetMetadataStatic in the generated code.
+// See comments in compiler/cpp/internal/file.cc as to why.
+// It takes a `Metadata` and returns it to allow for tail calls and reduce
+// binary size.
+Metadata PROTOBUF_EXPORT AssignDescriptors(const DescriptorTable* (*table)(),
+                                           internal::once_flag* once,
+                                           const Metadata& metadata);
+
 // These cannot be in lite so we put them in the reflection.
 PROTOBUF_EXPORT void UnknownFieldSetSerializer(const uint8* base, uint32 offset,
                                                uint32 tag, uint32 has_offset,
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 2b20e0a..a318da4 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -951,6 +951,26 @@
   return WriteStringToArray(str, target);
 }
 
+uint8* CodedOutputStream::WriteVarint32ToArrayOutOfLineHelper(uint32 value,
+                                                              uint8* target) {
+  GOOGLE_DCHECK_GE(value, 0x80);
+  target[0] |= static_cast<uint8>(0x80);
+  value >>= 7;
+  target[1] = static_cast<uint8>(value);
+  if (value < 0x80) {
+    return target + 2;
+  }
+  target += 2;
+  do {
+    // Turn on continuation bit in the byte we just wrote.
+    target[-1] |= static_cast<uint8>(0x80);
+    value >>= 7;
+    *target = static_cast<uint8>(value);
+    ++target;
+  } while (value >= 0x80);
+  return target;
+}
+
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
index df8c449..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
@@ -851,11 +853,11 @@
   }
 
   static constexpr int TagSize(uint32 tag) {
-    return (tag < (1 << 7))
-               ? 1
-               : (tag < (1 << 14))
-                     ? 2
-                     : (tag < (1 << 21)) ? 3 : (tag < (1 << 28)) ? 4 : 5;
+    return (tag < (1 << 7))    ? 1
+           : (tag < (1 << 14)) ? 2
+           : (tag < (1 << 21)) ? 3
+           : (tag < (1 << 28)) ? 4
+                               : 5;
   }
 
   PROTOBUF_ALWAYS_INLINE uint8* WriteTag(uint32 num, uint32 wt, uint8* ptr) {
@@ -904,23 +906,25 @@
   PROTOBUF_ALWAYS_INLINE static uint8* UnsafeVarint(T value, uint8* ptr) {
     static_assert(std::is_unsigned<T>::value,
                   "Varint serialization must be unsigned");
+    ptr[0] = static_cast<uint8>(value);
     if (value < 0x80) {
-      ptr[0] = static_cast<uint8>(value);
       return ptr + 1;
     }
-    ptr[0] = static_cast<uint8>(value | 0x80);
+    // Turn on continuation bit in the byte we just wrote.
+    ptr[0] |= static_cast<uint8>(0x80);
     value >>= 7;
+    ptr[1] = static_cast<uint8>(value);
     if (value < 0x80) {
-      ptr[1] = static_cast<uint8>(value);
       return ptr + 2;
     }
-    ptr++;
+    ptr += 2;
     do {
-      *ptr = static_cast<uint8>(value | 0x80);
+      // Turn on continuation bit in the byte we just wrote.
+      ptr[-1] |= static_cast<uint8>(0x80);
       value >>= 7;
+      *ptr = static_cast<uint8>(value);
       ++ptr;
-    } while (PROTOBUF_PREDICT_FALSE(value >= 0x80));
-    *ptr++ = static_cast<uint8>(value);
+    } while (value >= 0x80);
     return ptr;
   }
 
@@ -1149,6 +1153,9 @@
   void WriteVarint32(uint32 value);
   // Like WriteVarint32()  but writing directly to the target array.
   static uint8* WriteVarint32ToArray(uint32 value, uint8* target);
+  // Like WriteVarint32()  but writing directly to the target array, and with the
+  // less common-case paths being out of line rather than inlined.
+  static uint8* WriteVarint32ToArrayOutOfLine(uint32 value, uint8* target);
   // Write an unsigned integer with Varint encoding.
   void WriteVarint64(uint64 value);
   // Like WriteVarint64()  but writing directly to the target array.
@@ -1181,12 +1188,11 @@
   // Compile-time equivalent of VarintSize32().
   template <uint32 Value>
   struct StaticVarintSize32 {
-    static const size_t value =
-        (Value < (1 << 7))
-            ? 1
-            : (Value < (1 << 14))
-                  ? 2
-                  : (Value < (1 << 21)) ? 3 : (Value < (1 << 28)) ? 4 : 5;
+    static const size_t value = (Value < (1 << 7))    ? 1
+                                : (Value < (1 << 14)) ? 2
+                                : (Value < (1 << 21)) ? 3
+                                : (Value < (1 << 28)) ? 4
+                                                      : 5;
   };
 
   // Returns the total number of bytes written since this object was created.
@@ -1264,6 +1270,8 @@
   static void SetDefaultSerializationDeterministic() {
     default_serialization_deterministic_.store(true, std::memory_order_relaxed);
   }
+  // REQUIRES: value >= 0x80, and that (value & 7f) has been written to *target.
+  static uint8* WriteVarint32ToArrayOutOfLineHelper(uint32 value, uint8* target);
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
 };
 
@@ -1594,6 +1602,16 @@
   return EpsCopyOutputStream::UnsafeVarint(value, target);
 }
 
+inline uint8* CodedOutputStream::WriteVarint32ToArrayOutOfLine(uint32 value,
+                                                               uint8* target) {
+  target[0] = static_cast<uint8>(value);
+  if (value < 0x80) {
+    return target + 1;
+  } else {
+    return WriteVarint32ToArrayOutOfLineHelper(value, target);
+  }
+}
+
 inline uint8* CodedOutputStream::WriteVarint64ToArray(uint64 value,
                                                       uint8* target) {
   return EpsCopyOutputStream::UnsafeVarint(value, target);
diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc
index 003f1fe..0d97d40 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -661,5 +661,37 @@
 }
 
 
+TEST(MESSAGE_TEST_NAME, CheckSerializationWhenInterleavedExtensions) {
+  UNITTEST::TestExtensionRangeSerialize in_message;
+
+  in_message.set_foo_one(1);
+  in_message.set_foo_two(2);
+  in_message.set_foo_three(3);
+  in_message.set_foo_four(4);
+
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_one, 1);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_two, 2);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_three, 3);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_four, 4);
+  in_message.SetExtension(UNITTEST::TestExtensionRangeSerialize::bar_five, 5);
+
+  std::string buffer;
+  in_message.SerializeToString(&buffer);
+
+  UNITTEST::TestExtensionRangeSerialize out_message;
+  out_message.ParseFromString(buffer);
+
+  EXPECT_EQ(1, out_message.foo_one());
+  EXPECT_EQ(2, out_message.foo_two());
+  EXPECT_EQ(3, out_message.foo_three());
+  EXPECT_EQ(4, out_message.foo_four());
+
+  EXPECT_EQ(1, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_one));
+  EXPECT_EQ(2, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_two));
+  EXPECT_EQ(3, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_three));
+  EXPECT_EQ(4, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_four));
+  EXPECT_EQ(5, out_message.GetExtension(UNITTEST::TestExtensionRangeSerialize::bar_five));
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index 8e1d24e..1f8d8fc 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -67,7 +67,7 @@
   template <typename T>
   void Delete() {
     // Note that Delete<> should be called not more than once.
-    if (have_unknown_fields() && arena() == NULL) {
+    if (have_unknown_fields()) {
       DeleteOutOfLineHelper<T>();
     }
   }
@@ -204,7 +204,9 @@
 
   template <typename T>
   PROTOBUF_NOINLINE void DeleteOutOfLineHelper() {
-    delete PtrValue<Container<T>>();
+    if (arena() == NULL) {
+      delete PtrValue<Container<T>>();
+    }
   }
 
   template <typename T>
diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc
index 8143af8..e141c43 100644
--- a/src/google/protobuf/parse_context.cc
+++ b/src/google/protobuf/parse_context.cc
@@ -326,6 +326,18 @@
   return buffer_;
 }
 
+const char* ParseContext::ReadSizeAndPushLimitAndDepth(const char* ptr,
+                                                       int* old_limit) {
+  int size = ReadSize(&ptr);
+  if (PROTOBUF_PREDICT_FALSE(!ptr)) {
+    *old_limit = 0;  // Make sure this isn't uninitialized even on error return
+    return nullptr;
+  }
+  *old_limit = PushLimit(ptr, size);
+  if (--depth_ < 0) return nullptr;
+  return ptr;
+}
+
 const char* ParseContext::ParseMessage(MessageLite* msg, const char* ptr) {
   return ParseMessage<MessageLite>(msg, ptr);
 }
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
index 7966d99..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_;
@@ -413,6 +412,17 @@
   }
 
  private:
+  // Out-of-line routine to save space in ParseContext::ParseMessage<T>
+  //   int old;
+  //   ptr = ReadSizeAndPushLimitAndDepth(ptr, &old)
+  // is equivalent to:
+  //   int size = ReadSize(&ptr);
+  //   if (!ptr) return nullptr;
+  //   int old = PushLimit(ptr, size);
+  //   if (--depth_ < 0) return nullptr;
+  PROTOBUF_MUST_USE_RESULT const char* ReadSizeAndPushLimitAndDepth(
+      const char* ptr, int* old_limit);
+
   // The context keeps an internal stack to keep track of the recursive
   // part of the parse state.
   // Current depth of the active parser, depth counts down.
@@ -640,12 +650,9 @@
 template <typename T>
 PROTOBUF_MUST_USE_RESULT const char* ParseContext::ParseMessage(
     T* msg, const char* ptr) {
-  int size = ReadSize(&ptr);
-  if (!ptr) return nullptr;
-  auto old = PushLimit(ptr, size);
-  if (--depth_ < 0) return nullptr;
-  ptr = msg->_InternalParse(ptr, this);
-  if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr;
+  int old;
+  ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
+  ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr;
   depth_++;
   if (!PopLimit(old)) return nullptr;
   return ptr;
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index c11c1d9..73cd630 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -198,22 +198,24 @@
 //   You can #define these annotations yourself if the default implementation
 //   is not right for you.
 
+#ifndef PROTOBUF_NO_INLINE
 #ifdef GOOGLE_ATTRIBUTE_ALWAYS_INLINE
 #define PROTOBUF_ALWAYS_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE
 #define PROTOBUF_NDEBUG_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE
-#else
-#if defined(__GNUC__) && \
+#elif defined(__GNUC__) && \
     (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
 // For functions we want to force inline.
 // Introduced in gcc 3.1.
 #define PROTOBUF_ALWAYS_INLINE __attribute__((always_inline))
 #define PROTOBUF_NDEBUG_INLINE __attribute__((always_inline))
-#else
+#endif
+#endif
+
+#ifndef PROTOBUF_ALWAYS_INLINE
 // Other compilers will have to figure it out for themselves.
 #define PROTOBUF_ALWAYS_INLINE
 #define PROTOBUF_NDEBUG_INLINE
 #endif
-#endif
 
 #ifdef GOOGLE_ATTRIBUTE_NOINLINE
 #define PROTOBUF_NOINLINE GOOGLE_ATTRIBUTE_NOINLINE
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index daef09b..8591762 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -79,6 +79,10 @@
 #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
 #undef PROTOBUF_PRAGMA_INIT_SEG
 
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+#undef PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif
+
 // Restore macro that may have been #undef'd in port_def.inc.
 #ifdef _MSC_VER
 #pragma pop_macro("CREATE_NEW")
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index 7731b28..83be3d8 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -317,6 +317,35 @@
   }
 }
 
+TEST(Proto3OptionalTest, Extensions) {
+  const DescriptorPool* p = DescriptorPool::generated_pool();
+  const FieldDescriptor* no_optional = p->FindExtensionByName(
+      "protobuf_unittest.Proto3OptionalExtensions.ext_no_optional");
+  const FieldDescriptor* with_optional = p->FindExtensionByName(
+      "protobuf_unittest.Proto3OptionalExtensions.ext_with_optional");
+  GOOGLE_CHECK(no_optional);
+  GOOGLE_CHECK(with_optional);
+  EXPECT_FALSE(no_optional->has_optional_keyword());
+  EXPECT_TRUE(with_optional->has_optional_keyword());
+
+  const Descriptor* d = protobuf_unittest::Proto3OptionalExtensions::descriptor();
+  EXPECT_TRUE(d->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_no_optional));
+  EXPECT_TRUE(d->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_with_optional));
+  EXPECT_EQ(8, d->options().GetExtension(
+                   protobuf_unittest::Proto3OptionalExtensions::ext_no_optional));
+  EXPECT_EQ(16,
+            d->options().GetExtension(
+                protobuf_unittest::Proto3OptionalExtensions::ext_with_optional));
+
+  const Descriptor* d2 = protobuf_unittest::TestProto3Optional::descriptor();
+  EXPECT_FALSE(d2->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_no_optional));
+  EXPECT_FALSE(d2->options().HasExtension(
+      protobuf_unittest::Proto3OptionalExtensions::ext_with_optional));
+}
+
 TEST(Proto3OptionalTest, OptionalField) {
   protobuf_unittest::TestProto3Optional msg;
   EXPECT_FALSE(msg.has_optional_int32());
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index f5e83ff..addd26ce 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -98,6 +98,15 @@
   }
 }
 
+void* RepeatedPtrFieldBase::AddOutOfLineHelper(void* obj) {
+  if (!rep_ || rep_->allocated_size == total_size_) {
+    InternalExtend(1);  // Equivalent to "Reserve(total_size_ + 1)"
+  }
+  ++rep_->allocated_size;
+  rep_->elements[current_size_++] = obj;
+  return obj;
+}
+
 void RepeatedPtrFieldBase::CloseGap(int start, int num) {
   if (rep_ == NULL) return;
   // Close up a gap of "num" elements starting at offset "start".
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 9ba9e93..58190e3 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -171,9 +171,14 @@
  public:
   constexpr RepeatedField();
   explicit RepeatedField(Arena* arena);
+
   RepeatedField(const RepeatedField& other);
-  template <typename Iter>
-  RepeatedField(Iter begin, const Iter& end);
+
+  template <typename Iter,
+            typename = typename std::enable_if<std::is_constructible<
+                Element, decltype(*std::declval<Iter>())>::value>::type>
+  RepeatedField(Iter begin, Iter end);
+
   ~RepeatedField();
 
   RepeatedField& operator=(const RepeatedField& other);
@@ -216,6 +221,10 @@
   void MergeFrom(const RepeatedField& other);
   void CopyFrom(const RepeatedField& other);
 
+  // Replaces the contents with RepeatedField(begin, end).
+  template <typename Iter>
+  void Assign(Iter begin, Iter end);
+
   // Reserve space to expand the field to at least the given size.  If the
   // array is grown, it will always be at least doubled in size.
   void Reserve(int new_size);
@@ -760,8 +769,9 @@
                                                                   int));
 
   template <typename TypeHandler>
-  void MergeFromInnerLoop(void** our_elems, void** other_elems, int length,
-                          int already_allocated);
+  PROTOBUF_NOINLINE void MergeFromInnerLoop(void** our_elems,
+                                            void** other_elems, int length,
+                                            int already_allocated);
 
   // Internal helper: extend array space if necessary to contain |extend_amount|
   // more elements, and return a pointer to the element immediately following
@@ -769,6 +779,11 @@
   // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0.
   void** InternalExtend(int extend_amount);
 
+  // Internal helper for Add: add "obj" as the next element in the
+  // array, including potentially resizing the array with Reserve if
+  // needed
+  void* AddOutOfLineHelper(void* obj);
+
   // The reflection implementation needs to call protected methods directly,
   // reinterpreting pointers as being to Message instead of a specific Message
   // subclass.
@@ -923,8 +938,12 @@
   explicit RepeatedPtrField(Arena* arena);
 
   RepeatedPtrField(const RepeatedPtrField& other);
-  template <typename Iter>
-  RepeatedPtrField(Iter begin, const Iter& end);
+
+  template <typename Iter,
+            typename = typename std::enable_if<std::is_constructible<
+                Element, decltype(*std::declval<Iter>())>::value>::type>
+  RepeatedPtrField(Iter begin, Iter end);
+
   ~RepeatedPtrField();
 
   RepeatedPtrField& operator=(const RepeatedPtrField& other);
@@ -939,6 +958,10 @@
   Element* Mutable(int index);
   Element* Add();
   void Add(Element&& value);
+  // Append elements in the range [begin, end) after reserving
+  // the appropriate number of elements.
+  template <typename Iter>
+  void Add(Iter begin, Iter end);
 
   const Element& operator[](int index) const { return Get(index); }
   Element& operator[](int index) { return *Mutable(index); }
@@ -959,6 +982,10 @@
   void MergeFrom(const RepeatedPtrField& other);
   void CopyFrom(const RepeatedPtrField& other);
 
+  // Replaces the contents with RepeatedPtrField(begin, end).
+  template <typename Iter>
+  void Assign(Iter begin, Iter end);
+
   // Reserve space to expand the field to at least the given size.  This only
   // resizes the pointer array; it doesn't allocate any objects.  If the
   // array is grown, it will always be at least doubled in size.
@@ -1197,8 +1224,8 @@
 }
 
 template <typename Element>
-template <typename Iter>
-RepeatedField<Element>::RepeatedField(Iter begin, const Iter& end)
+template <typename Iter, typename>
+RepeatedField<Element>::RepeatedField(Iter begin, Iter end)
     : current_size_(0), total_size_(0), arena_or_elements_(nullptr) {
   Add(begin, end);
 }
@@ -1434,6 +1461,13 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedField<Element>::Assign(Iter begin, Iter end) {
+  Clear();
+  Add(begin, end);
+}
+
+template <typename Element>
 inline typename RepeatedField<Element>::iterator RepeatedField<Element>::erase(
     const_iterator position) {
   return erase(position, position + 1);
@@ -1747,14 +1781,10 @@
   if (rep_ != NULL && current_size_ < rep_->allocated_size) {
     return cast<TypeHandler>(rep_->elements[current_size_++]);
   }
-  if (!rep_ || rep_->allocated_size == total_size_) {
-    Reserve(total_size_ + 1);
-  }
-  ++rep_->allocated_size;
   typename TypeHandler::Type* result =
       TypeHandler::NewFromPrototype(prototype, arena_);
-  rep_->elements[current_size_++] = result;
-  return result;
+  return reinterpret_cast<typename TypeHandler::Type*>(
+      AddOutOfLineHelper(result));
 }
 
 template <typename TypeHandler,
@@ -1828,9 +1858,19 @@
 void RepeatedPtrFieldBase::MergeFromInnerLoop(void** our_elems,
                                               void** other_elems, int length,
                                               int already_allocated) {
-  // Split into two loops, over ranges [0, allocated) and [allocated, length),
-  // to avoid a branch within the loop.
-  for (int i = 0; i < already_allocated && i < length; i++) {
+  if (already_allocated < length) {
+    Arena* arena = GetArena();
+    typename TypeHandler::Type* elem_prototype =
+        reinterpret_cast<typename TypeHandler::Type*>(other_elems[0]);
+    for (int i = already_allocated; i < length; i++) {
+      // Allocate a new empty element that we'll merge into below
+      typename TypeHandler::Type* new_elem =
+          TypeHandler::NewFromPrototype(elem_prototype, arena);
+      our_elems[i] = new_elem;
+    }
+  }
+  // Main loop that does the actual merging
+  for (int i = 0; i < length; i++) {
     // Already allocated: use existing element.
     typename TypeHandler::Type* other_elem =
         reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
@@ -1838,16 +1878,6 @@
         reinterpret_cast<typename TypeHandler::Type*>(our_elems[i]);
     TypeHandler::Merge(*other_elem, new_elem);
   }
-  Arena* arena = GetArena();
-  for (int i = already_allocated; i < length; i++) {
-    // Not allocated: alloc a new element first, then merge it.
-    typename TypeHandler::Type* other_elem =
-        reinterpret_cast<typename TypeHandler::Type*>(other_elems[i]);
-    typename TypeHandler::Type* new_elem =
-        TypeHandler::NewFromPrototype(other_elem, arena);
-    TypeHandler::Merge(*other_elem, new_elem);
-    our_elems[i] = new_elem;
-  }
 }
 
 template <typename TypeHandler>
@@ -2110,16 +2140,9 @@
 }
 
 template <typename Element>
-template <typename Iter>
-inline RepeatedPtrField<Element>::RepeatedPtrField(Iter begin,
-                                                   const Iter& end) {
-  int reserve = internal::CalculateReserve(begin, end);
-  if (reserve != -1) {
-    Reserve(reserve);
-  }
-  for (; begin != end; ++begin) {
-    *Add() = *begin;
-  }
+template <typename Iter, typename>
+inline RepeatedPtrField<Element>::RepeatedPtrField(Iter begin, Iter end) {
+  Add(begin, end);
 }
 
 template <typename Element>
@@ -2205,6 +2228,18 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedPtrField<Element>::Add(Iter begin, Iter end) {
+  int reserve = internal::CalculateReserve(begin, end);
+  if (reserve != -1) {
+    Reserve(size() + reserve);
+  }
+  for (; begin != end; ++begin) {
+    *Add() = *begin;
+  }
+}
+
+template <typename Element>
 inline void RepeatedPtrField<Element>::RemoveLast() {
   RepeatedPtrFieldBase::RemoveLast<TypeHandler>();
 }
@@ -2311,6 +2346,13 @@
 }
 
 template <typename Element>
+template <typename Iter>
+inline void RepeatedPtrField<Element>::Assign(Iter begin, Iter end) {
+  Clear();
+  Add(begin, end);
+}
+
+template <typename Element>
 inline typename RepeatedPtrField<Element>::iterator
 RepeatedPtrField<Element>::erase(const_iterator position) {
   return erase(position, position + 1);
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index a396b61..f3e8c2d 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -488,6 +488,30 @@
   ASSERT_EQ(me.Get(1), 2);
 }
 
+TEST(RepeatedField, AddAndAssignRanges) {
+  RepeatedField<int> field;
+
+  int vals[] = {2, 27, 2875, 609250};
+  field.Assign(std::begin(vals), std::end(vals));
+
+  ASSERT_EQ(field.size(), 4);
+  EXPECT_EQ(field.Get(0), 2);
+  EXPECT_EQ(field.Get(1), 27);
+  EXPECT_EQ(field.Get(2), 2875);
+  EXPECT_EQ(field.Get(3), 609250);
+
+  field.Add(std::begin(vals), std::end(vals));
+  ASSERT_EQ(field.size(), 8);
+  EXPECT_EQ(field.Get(0), 2);
+  EXPECT_EQ(field.Get(1), 27);
+  EXPECT_EQ(field.Get(2), 2875);
+  EXPECT_EQ(field.Get(3), 609250);
+  EXPECT_EQ(field.Get(4), 2);
+  EXPECT_EQ(field.Get(5), 27);
+  EXPECT_EQ(field.Get(6), 2875);
+  EXPECT_EQ(field.Get(7), 609250);
+}
+
 TEST(RepeatedField, CopyConstruct) {
   RepeatedField<int> source;
   source.Add(1);
@@ -837,6 +861,45 @@
   EXPECT_TRUE(field.empty());
 }
 
+// This helper overload set tests whether X::f can be called with a braced pair,
+// X::f({a, b}) of std::string iterators (specifically, pointers: That call is
+// ambiguous if and only if the call to ValidResolutionPointerRange is not.
+template <typename X>
+auto ValidResolutionPointerRange(const std::string* p)
+    -> decltype(X::f({p, p + 2}), std::true_type{});
+template <typename X>
+std::false_type ValidResolutionPointerRange(void*);
+
+TEST(RepeatedPtrField, UnambiguousConstructor) {
+  struct X {
+    static bool f(std::vector<std::string>) { return false; }
+    static bool f(google::protobuf::RepeatedPtrField<std::string>) { return true; }
+
+    static bool g(std::vector<int>) { return false; }
+    static bool g(google::protobuf::RepeatedPtrField<std::string>) { return true; }
+  };
+
+  // RepeatedPtrField has no initializer-list constructor, and a constructor
+  // from to const char* values is excluded by its constraints.
+  EXPECT_FALSE(X::f({"abc", "xyz"}));
+
+  // Construction from a pair of int* is also not ambiguous.
+  int a[5] = {};
+  EXPECT_FALSE(X::g({a, a + 5}));
+
+  // Construction from string iterators for the unique string overload "g"
+  // works.
+  std::string b[2] = {"abc", "xyz"};
+  // Disabling this for now, this is actually ambiguous with libstdc++.
+  // EXPECT_TRUE(X::g({b, b + 2}));
+
+  // Construction from string iterators for "f" is ambiguous, since both
+  // containers are equally good.
+  //
+  // X::f({b, b + 2});  // error => ValidResolutionPointerRange is unambiguous.
+  EXPECT_FALSE(decltype(ValidResolutionPointerRange<X>(nullptr))::value);
+}
+
 TEST(RepeatedPtrField, Small) {
   RepeatedPtrField<std::string> field;
 
@@ -899,6 +962,30 @@
   EXPECT_GE(field.SpaceUsedExcludingSelf(), min_expected_usage);
 }
 
+TEST(RepeatedPtrField, AddAndAssignRanges) {
+  RepeatedPtrField<std::string> field;
+
+  const char* vals[] = {"abc", "x", "yz", "xyzzy"};
+  field.Assign(std::begin(vals), std::end(vals));
+
+  ASSERT_EQ(field.size(), 4);
+  EXPECT_EQ(field.Get(0), "abc");
+  EXPECT_EQ(field.Get(1), "x");
+  EXPECT_EQ(field.Get(2), "yz");
+  EXPECT_EQ(field.Get(3), "xyzzy");
+
+  field.Add(std::begin(vals), std::end(vals));
+  ASSERT_EQ(field.size(), 8);
+  EXPECT_EQ(field.Get(0), "abc");
+  EXPECT_EQ(field.Get(1), "x");
+  EXPECT_EQ(field.Get(2), "yz");
+  EXPECT_EQ(field.Get(3), "xyzzy");
+  EXPECT_EQ(field.Get(4), "abc");
+  EXPECT_EQ(field.Get(5), "x");
+  EXPECT_EQ(field.Get(6), "yz");
+  EXPECT_EQ(field.Get(7), "xyzzy");
+}
+
 TEST(RepeatedPtrField, SwapSmallSmall) {
   RepeatedPtrField<std::string> field1;
   RepeatedPtrField<std::string> field2;
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index 641862e..3994ceb 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -65,10 +65,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto, file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
-  return descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -138,7 +136,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string file_name = 1;
       case 1:
@@ -151,7 +148,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -271,10 +269,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceContext::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter, &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 0789bb9..cd3213a 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class SourceContext;
 struct SourceContextDefaultTypeInternal;
@@ -70,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);
@@ -96,10 +95,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const SourceContext& default_instance() {
     return *internal_default_instance();
@@ -167,12 +166,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -184,10 +177,8 @@
   // string file_name = 1;
   void clear_file_name();
   const std::string& file_name() const;
-  void set_file_name(const std::string& value);
-  void set_file_name(std::string&& value);
-  void set_file_name(const char* value);
-  void set_file_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_file_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_file_name();
   std::string* release_file_name();
   void set_allocated_file_name(std::string* file_name);
@@ -227,8 +218,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name)
   return _internal_file_name();
 }
-inline void SourceContext::set_file_name(const std::string& value) {
-  _internal_set_file_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void SourceContext::set_file_name(ArgT0&& arg0, ArgT... args) {
+ 
+ file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name)
 }
 inline std::string* SourceContext::mutable_file_name() {
@@ -242,25 +236,6 @@
   
   file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void SourceContext::set_file_name(std::string&& value) {
-  
-  file_name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceContext.file_name)
-}
-inline void SourceContext::set_file_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name)
-}
-inline void SourceContext::set_file_name(const char* value,
-    size_t size) {
-  
-  file_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name)
-}
 inline std::string* SourceContext::_internal_mutable_file_name() {
   
   return file_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 61e9f80..fbe98e7 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -143,10 +143,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fstruct_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto, file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-  return descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fstruct_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -175,7 +173,9 @@
   MergeFromInternal(other);
 }
 ::PROTOBUF_NAMESPACE_ID::Metadata Struct_FieldsEntry_DoNotUse::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[0]);
 }
 void Struct_FieldsEntry_DoNotUse::MergeFrom(
     const ::PROTOBUF_NAMESPACE_ID::Message& other) {
@@ -241,7 +241,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // map<string, .google.protobuf.Value> fields = 1;
       case 1:
@@ -257,7 +256,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -408,10 +408,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Struct::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[1]);
 }
 
-
 // ===================================================================
 
 class Value::_Internal {
@@ -581,7 +582,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // .google.protobuf.NullValue null_value = 1;
       case 1:
@@ -630,7 +630,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -847,10 +848,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[2]);
 }
 
-
 // ===================================================================
 
 class ListValue::_Internal {
@@ -909,7 +911,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // repeated .google.protobuf.Value values = 1;
       case 1:
@@ -925,7 +926,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1041,10 +1043,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ListValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fstruct_2eproto[3]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index 3c116da..8dbefa4 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -57,7 +57,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class ListValue;
 struct ListValueDefaultTypeInternal;
@@ -127,13 +126,6 @@
   static bool ValidateValue(void*) { return true; }
   void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& other) final;
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_google_2fprotobuf_2fstruct_2eproto);
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto.file_level_metadata[0];
-  }
-
-  public:
 };
 
 // -------------------------------------------------------------------
@@ -142,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);
@@ -168,10 +160,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Struct& default_instance() {
     return *internal_default_instance();
@@ -239,12 +231,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -292,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);
@@ -318,10 +304,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Value& default_instance() {
     return *internal_default_instance();
@@ -399,12 +385,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -451,10 +431,8 @@
   public:
   void clear_string_value();
   const std::string& string_value() const;
-  void set_string_value(const std::string& value);
-  void set_string_value(std::string&& value);
-  void set_string_value(const char* value);
-  void set_string_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_string_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_string_value();
   std::string* release_string_value();
   void set_allocated_string_value(std::string* string_value);
@@ -552,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);
@@ -578,10 +556,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const ListValue& default_instance() {
     return *internal_default_instance();
@@ -649,12 +627,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fstruct_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -834,8 +806,14 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value)
   return _internal_string_value();
 }
-inline void Value::set_string_value(const std::string& value) {
-  _internal_set_string_value(value);
+template <typename ArgT0, typename... ArgT>
+inline void Value::set_string_value(ArgT0&& arg0, ArgT... args) {
+  if (!_internal_has_string_value()) {
+    clear_kind();
+    set_has_string_value();
+    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+  }
+  kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
 }
 inline std::string* Value::mutable_string_value() {
@@ -856,41 +834,6 @@
   }
   kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Value::set_string_value(std::string&& value) {
-  // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value)
-  if (!_internal_has_string_value()) {
-    clear_kind();
-    set_has_string_value();
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  kind_.string_value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value)
-}
-inline void Value::set_string_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  if (!_internal_has_string_value()) {
-    clear_kind();
-    set_has_string_value();
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  kind_.string_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{},
-      ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value)
-}
-inline void Value::set_string_value(const char* value,
-                             size_t size) {
-  if (!_internal_has_string_value()) {
-    clear_kind();
-    set_has_string_value();
-    kind_.string_value_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
-  }
-  kind_.string_value_.Set(
-      ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size),
-      GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value)
-}
 inline std::string* Value::_internal_mutable_string_value() {
   if (!_internal_has_string_value()) {
     clear_kind();
diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc
index a0f298e..980d6f6 100644
--- a/src/google/protobuf/stubs/bytestream.cc
+++ b/src/google/protobuf/stubs/bytestream.cc
@@ -173,12 +173,8 @@
 }
 
 StringPiece LimitByteSource::Peek() {
-  StringPiece piece(source_->Peek());
-  if (piece.size() > limit_) {
-    piece.set(piece.data(), limit_);
-  }
-
-  return piece;
+  StringPiece piece = source_->Peek();
+  return StringPiece(piece.data(), std::min(piece.size(), limit_));
 }
 
 void LimitByteSource::Skip(size_t n) {
diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
index d8a49ce..ad29dac 100644
--- a/src/google/protobuf/stubs/casts.h
+++ b/src/google/protobuf/stubs/casts.h
@@ -116,8 +116,7 @@
 
 template<typename To, typename From>
 inline To bit_cast(const From& from) {
-  GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To),
-                        bit_cast_with_different_sizes);
+  static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes");
   To dest;
   memcpy(&dest, &from, sizeof(dest));
   return dest;
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index 303cf38..4bac057 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -123,7 +123,6 @@
 // ===================================================================
 // from google3/util/utf8/public/unilib.h
 
-class StringPiece;
 namespace internal {
 
 // Checks if the buffer contains structurally-valid UTF-8.  Implemented in
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
index 7fc7dd8..840f2d1 100644
--- a/src/google/protobuf/stubs/int128.cc
+++ b/src/google/protobuf/stubs/int128.cc
@@ -33,6 +33,7 @@
 #include <iomanip>
 #include <ostream>  // NOLINT(readability/streams)
 #include <sstream>
+#include <string>
 
 #include <google/protobuf/stubs/logging.h>
 
@@ -40,11 +41,7 @@
 
 namespace google {
 namespace protobuf {
-
-const uint128_pod kuint128max = {
-    static_cast<uint64>(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF)),
-    static_cast<uint64>(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF))
-};
+namespace int128_internal {
 
 // Returns the 0-based position of the last set bit (i.e., most significant bit)
 // in the given uint64. The argument may not be 0.
@@ -188,6 +185,14 @@
   return o << rep;
 }
 
+void VerifyValidShift(std::string op, int amount) {
+  // Shifting more than 127 is UB in Abseil, just crash for now to verify
+  // callers don't depend on it returning 0.
+  GOOGLE_CHECK_LT(amount, 128) << "Error executing operator " << op
+                               << ": shifts of more than 127 are undefined";
+}
+
+}  // namespace int128_internal
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/int128.h b/src/google/protobuf/stubs/int128.h
index dc70d96..8ae4897 100644
--- a/src/google/protobuf/stubs/int128.h
+++ b/src/google/protobuf/stubs/int128.h
@@ -33,38 +33,33 @@
 #include <google/protobuf/stubs/common.h>
 
 #include <iosfwd>
+#include <limits>
+#include <string>
 
 #include <google/protobuf/port_def.inc>
 
 namespace google {
 namespace protobuf {
-
-struct uint128_pod;
-
-// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
-// available.
-#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
-# define UINT128_CONSTEXPR constexpr
-#else
-# define UINT128_CONSTEXPR
-#endif
+namespace int128_internal {
 
 // An unsigned 128-bit integer type. Thread-compatible.
 class PROTOBUF_EXPORT uint128 {
  public:
-  UINT128_CONSTEXPR uint128();  // Sets to 0, but don't trust on this behavior.
-  UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom);
+  uint128() = default;
+
+ private:
+  // Use `MakeUint128` instead.
+  constexpr uint128(uint64 top, uint64 bottom);
+
+ public:
 #ifndef SWIG
-  UINT128_CONSTEXPR uint128(int bottom);
-  UINT128_CONSTEXPR uint128(uint32 bottom);   // Top 96 bits = 0
+  constexpr uint128(int bottom);
+  constexpr uint128(uint32 bottom);   // Top 96 bits = 0
 #endif
-  UINT128_CONSTEXPR uint128(uint64 bottom);   // hi_ = 0
-  UINT128_CONSTEXPR uint128(const uint128_pod &val);
+  constexpr uint128(uint64 bottom);   // hi_ = 0
 
   // Trivial copy constructor, assignment operator and destructor.
 
-  void Initialize(uint64 top, uint64 bottom);
-
   // Arithmetic operators.
   uint128& operator+=(const uint128& b);
   uint128& operator-=(const uint128& b);
@@ -82,8 +77,10 @@
   uint128& operator++();
   uint128& operator--();
 
-  friend uint64 Uint128Low64(const uint128& v);
-  friend uint64 Uint128High64(const uint128& v);
+  friend constexpr uint64 Uint128Low64(const uint128& v);
+  friend constexpr uint64 Uint128High64(const uint128& v);
+
+  friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
 
   // We add "std::" to avoid including all of port.h.
   PROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
@@ -100,26 +97,12 @@
   uint64        hi_;
 
   // Not implemented, just declared for catching automatic type conversions.
-  uint128(uint8);
-  uint128(uint16);
-  uint128(float v);
-  uint128(double v);
+  uint128(uint8) = delete;
+  uint128(uint16) = delete;
+  uint128(float v) = delete;
+  uint128(double v) = delete;
 };
 
-// This is a POD form of uint128 which can be used for static variables which
-// need to be operated on as uint128.
-struct uint128_pod {
-  // Note: The ordering of fields is different than 'class uint128' but the
-  // same as its 2-arg constructor.  This enables more obvious initialization
-  // of static instances, which is the primary reason for this struct in the
-  // first place.  This does not seem to defeat any optimizations wrt
-  // operations involving this struct.
-  uint64 hi;
-  uint64 lo;
-};
-
-PROTOBUF_EXPORT extern const uint128_pod kuint128max;
-
 // allow uint128 to be logged
 PROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
                                                 const uint128& b);
@@ -127,8 +110,12 @@
 // Methods to access low and high pieces of 128-bit value.
 // Defined externally from uint128 to facilitate conversion
 // to native 128-bit types when compilers support them.
-inline uint64 Uint128Low64(const uint128& v) { return v.lo_; }
-inline uint64 Uint128High64(const uint128& v) { return v.hi_; }
+inline constexpr uint64 Uint128Low64(const uint128& v) { return v.lo_; }
+inline constexpr uint64 Uint128High64(const uint128& v) { return v.hi_; }
+
+constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
+  return uint128(high, low);
+}
 
 // TODO: perhaps it would be nice to have int128, a signed 128-bit type?
 
@@ -143,27 +130,17 @@
   return !(lhs == rhs);
 }
 
-inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
-inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom)
+inline constexpr uint128::uint128(uint64 top, uint64 bottom)
     : lo_(bottom), hi_(top) {}
-inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
-    : lo_(v.lo), hi_(v.hi) {}
-inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom)
+inline constexpr uint128::uint128(uint64 bottom)
     : lo_(bottom), hi_(0) {}
 #ifndef SWIG
-inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom)
+inline constexpr uint128::uint128(uint32 bottom)
     : lo_(bottom), hi_(0) {}
-inline UINT128_CONSTEXPR uint128::uint128(int bottom)
+inline constexpr uint128::uint128(int bottom)
     : lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {}
 #endif
 
-#undef UINT128_CONSTEXPR
-
-inline void uint128::Initialize(uint64 top, uint64 bottom) {
-  hi_ = top;
-  lo_ = bottom;
-}
-
 // Comparison operators.
 
 #define CMP128(op)                                                \
@@ -187,9 +164,9 @@
   const uint64 lo_flip = ~Uint128Low64(val);
   const uint64 lo_add = lo_flip + 1;
   if (lo_add < lo_flip) {
-    return uint128(hi_flip + 1, lo_add);
+    return MakeUint128(hi_flip + 1, lo_add);
   }
-  return uint128(hi_flip, lo_add);
+  return MakeUint128(hi_flip, lo_add);
 }
 
 inline bool operator!(const uint128& val) {
@@ -199,13 +176,13 @@
 // Logical operators.
 
 inline uint128 operator~(const uint128& val) {
-  return uint128(~Uint128High64(val), ~Uint128Low64(val));
+  return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
 }
 
 #define LOGIC128(op)                                                 \
 inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
-  return uint128(Uint128High64(lhs) op Uint128High64(rhs),           \
-                 Uint128Low64(lhs) op Uint128Low64(rhs));            \
+  return MakeUint128(Uint128High64(lhs) op Uint128High64(rhs),       \
+                     Uint128Low64(lhs) op Uint128Low64(rhs));        \
 }
 
 LOGIC128(|)
@@ -229,7 +206,11 @@
 
 // Shift operators.
 
+void VerifyValidShift(std::string op, int amount);
+
 inline uint128 operator<<(const uint128& val, int amount) {
+  VerifyValidShift("<<", amount);
+
   // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
   if (amount < 64) {
     if (amount == 0) {
@@ -238,15 +219,14 @@
     uint64 new_hi = (Uint128High64(val) << amount) |
                     (Uint128Low64(val) >> (64 - amount));
     uint64 new_lo = Uint128Low64(val) << amount;
-    return uint128(new_hi, new_lo);
-  } else if (amount < 128) {
-    return uint128(Uint128Low64(val) << (amount - 64), 0);
-  } else {
-    return uint128(0, 0);
+    return MakeUint128(new_hi, new_lo);
   }
+  return MakeUint128(Uint128Low64(val) << (amount - 64), 0);
 }
 
 inline uint128 operator>>(const uint128& val, int amount) {
+  VerifyValidShift(">>", amount);
+
   // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
   if (amount < 64) {
     if (amount == 0) {
@@ -255,12 +235,10 @@
     uint64 new_hi = Uint128High64(val) >> amount;
     uint64 new_lo = (Uint128Low64(val) >> amount) |
                     (Uint128High64(val) << (64 - amount));
-    return uint128(new_hi, new_lo);
-  } else if (amount < 128) {
-    return uint128(0, Uint128High64(val) >> (amount - 64));
-  } else {
-    return uint128(0, 0);
+    return MakeUint128(new_hi, new_lo);
   }
+
+  return MakeUint128(0, Uint128High64(val) >> (amount - 64));
 }
 
 inline uint128& uint128::operator<<=(int amount) {
@@ -379,6 +357,17 @@
   return *this;
 }
 
+constexpr uint128 Uint128Max() {
+  return MakeUint128((std::numeric_limits<uint64>::max)(),
+                     (std::numeric_limits<uint64>::max)());
+}
+
+}  // namespace int128_internal
+
+using google::protobuf::int128_internal::uint128;
+using google::protobuf::int128_internal::Uint128Max;
+using google::protobuf::int128_internal::MakeUint128;
+
 }  // namespace protobuf
 }  // namespace google
 
diff --git a/src/google/protobuf/stubs/int128_unittest.cc b/src/google/protobuf/stubs/int128_unittest.cc
index 53dbd09..3689104 100644
--- a/src/google/protobuf/stubs/int128_unittest.cc
+++ b/src/google/protobuf/stubs/int128_unittest.cc
@@ -33,6 +33,7 @@
 #include <algorithm>
 #include <sstream>
 #include <utility>
+#include <type_traits>
 
 #include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
@@ -44,16 +45,18 @@
 
 TEST(Int128, AllTests) {
   uint128 zero(0);
+  EXPECT_EQ(zero, uint128());
+
   uint128 one(1);
-  uint128 one_2arg(0, 1);
-  uint128 two(0, 2);
-  uint128 three(0, 3);
-  uint128 big(2000, 2);
-  uint128 big_minus_one(2000, 1);
-  uint128 bigger(2001, 1);
-  uint128 biggest(kuint128max);
-  uint128 high_low(1, 0);
-  uint128 low_high(0, kuint64max);
+  uint128 one_2arg = MakeUint128(0, 1);
+  uint128 two = MakeUint128(0, 2);
+  uint128 three = MakeUint128(0, 3);
+  uint128 big = MakeUint128(2000, 2);
+  uint128 big_minus_one = MakeUint128(2000, 1);
+  uint128 bigger = MakeUint128(2001, 1);
+  uint128 biggest(Uint128Max());
+  uint128 high_low = MakeUint128(1, 0);
+  uint128 low_high = MakeUint128(0, kuint64max);
   EXPECT_LT(one, two);
   EXPECT_GT(two, one);
   EXPECT_LT(one, big);
@@ -92,8 +95,6 @@
   EXPECT_EQ(big, (big >> 1) << 1);
   EXPECT_EQ(one, (one << 80) >> 80);
   EXPECT_EQ(zero, (one >> 80) << 80);
-  EXPECT_EQ(zero, big >> 128);
-  EXPECT_EQ(zero, big << 128);
 
   // Shift assignments.
   uint128 big_copy = big;
@@ -117,9 +118,9 @@
   big_copy = big;
   EXPECT_EQ(big >> 73, big_copy >>= 73);
   big_copy = big;
-  EXPECT_EQ(big << 128, big_copy <<= 128);
+  EXPECT_EQ(big << 127, big_copy <<= 127);
   big_copy = big;
-  EXPECT_EQ(big >> 128, big_copy >>= 128);
+  EXPECT_EQ(big >> 127, big_copy >>= 127);
 
   EXPECT_EQ(Uint128High64(biggest), kuint64max);
   EXPECT_EQ(Uint128Low64(biggest), kuint64max);
@@ -170,92 +171,13 @@
 
   EXPECT_EQ(big, -(-big));
   EXPECT_EQ(two, -((-one) - 1));
-  EXPECT_EQ(kuint128max, -one);
+  EXPECT_EQ(Uint128Max(), -one);
   EXPECT_EQ(zero, -zero);
 
   GOOGLE_LOG(INFO) << one;
   GOOGLE_LOG(INFO) << big_minus_one;
 }
 
-TEST(Int128, PodTests) {
-  uint128_pod pod = { 12345, 67890 };
-  uint128 from_pod(pod);
-  EXPECT_EQ(12345, Uint128High64(from_pod));
-  EXPECT_EQ(67890, Uint128Low64(from_pod));
-
-  uint128 zero(0);
-  uint128_pod zero_pod = {0, 0};
-  uint128 one(1);
-  uint128_pod one_pod = {0, 1};
-  uint128 two(2);
-  uint128_pod two_pod = {0, 2};
-  uint128 three(3);
-  uint128_pod three_pod = {0, 3};
-  uint128 big(1, 0);
-  uint128_pod big_pod = {1, 0};
-
-  EXPECT_EQ(zero, zero_pod);
-  EXPECT_EQ(zero_pod, zero);
-  EXPECT_EQ(zero_pod, zero_pod);
-  EXPECT_EQ(one, one_pod);
-  EXPECT_EQ(one_pod, one);
-  EXPECT_EQ(one_pod, one_pod);
-  EXPECT_EQ(two, two_pod);
-  EXPECT_EQ(two_pod, two);
-  EXPECT_EQ(two_pod, two_pod);
-
-  EXPECT_NE(one, two_pod);
-  EXPECT_NE(one_pod, two);
-  EXPECT_NE(one_pod, two_pod);
-
-  EXPECT_LT(one, two_pod);
-  EXPECT_LT(one_pod, two);
-  EXPECT_LT(one_pod, two_pod);
-  EXPECT_LE(one, one_pod);
-  EXPECT_LE(one_pod, one);
-  EXPECT_LE(one_pod, one_pod);
-  EXPECT_LE(one, two_pod);
-  EXPECT_LE(one_pod, two);
-  EXPECT_LE(one_pod, two_pod);
-
-  EXPECT_GT(two, one_pod);
-  EXPECT_GT(two_pod, one);
-  EXPECT_GT(two_pod, one_pod);
-  EXPECT_GE(two, two_pod);
-  EXPECT_GE(two_pod, two);
-  EXPECT_GE(two_pod, two_pod);
-  EXPECT_GE(two, one_pod);
-  EXPECT_GE(two_pod, one);
-  EXPECT_GE(two_pod, one_pod);
-
-  EXPECT_EQ(three, one | two_pod);
-  EXPECT_EQ(three, one_pod | two);
-  EXPECT_EQ(three, one_pod | two_pod);
-  EXPECT_EQ(one, three & one_pod);
-  EXPECT_EQ(one, three_pod & one);
-  EXPECT_EQ(one, three_pod & one_pod);
-  EXPECT_EQ(two, three ^ one_pod);
-  EXPECT_EQ(two, three_pod ^ one);
-  EXPECT_EQ(two, three_pod ^ one_pod);
-  EXPECT_EQ(two, three & (~one));
-  EXPECT_EQ(three, ~~three);
-
-  EXPECT_EQ(two, two_pod << 0);
-  EXPECT_EQ(two, one_pod << 1);
-  EXPECT_EQ(big, one_pod << 64);
-  EXPECT_EQ(zero, one_pod << 128);
-  EXPECT_EQ(two, two_pod >> 0);
-  EXPECT_EQ(one, two_pod >> 1);
-  EXPECT_EQ(one, big_pod >> 64);
-
-  EXPECT_EQ(one, zero + one_pod);
-  EXPECT_EQ(one, zero_pod + one);
-  EXPECT_EQ(one, zero_pod + one_pod);
-  EXPECT_EQ(one, two - one_pod);
-  EXPECT_EQ(one, two_pod - one);
-  EXPECT_EQ(one, two_pod - one_pod);
-}
-
 TEST(Int128, OperatorAssignReturnRef) {
   uint128 v(1);
   (v += 4) -= 3;
@@ -293,38 +215,38 @@
   }
 
   // Verified with dc.
-  a = uint128(PROTOBUF_ULONGLONG(0xffffeeeeddddcccc),
-              PROTOBUF_ULONGLONG(0xbbbbaaaa99998888));
-  b = uint128(PROTOBUF_ULONGLONG(0x7777666655554444),
-              PROTOBUF_ULONGLONG(0x3333222211110000));
+  a = MakeUint128(PROTOBUF_ULONGLONG(0xffffeeeeddddcccc),
+                  PROTOBUF_ULONGLONG(0xbbbbaaaa99998888));
+  b = MakeUint128(PROTOBUF_ULONGLONG(0x7777666655554444),
+                  PROTOBUF_ULONGLONG(0x3333222211110000));
   c = a * b;
-  EXPECT_EQ(uint128(PROTOBUF_ULONGLONG(0x530EDA741C71D4C3),
-                    PROTOBUF_ULONGLONG(0xBF25975319080000)),
+  EXPECT_EQ(MakeUint128(PROTOBUF_ULONGLONG(0x530EDA741C71D4C3),
+                        PROTOBUF_ULONGLONG(0xBF25975319080000)),
             c);
   EXPECT_EQ(0, c - b * a);
   EXPECT_EQ(a * a - b * b, (a + b) * (a - b));
 
   // Verified with dc.
-  a = uint128(PROTOBUF_ULONGLONG(0x0123456789abcdef),
-              PROTOBUF_ULONGLONG(0xfedcba9876543210));
-  b = uint128(PROTOBUF_ULONGLONG(0x02468ace13579bdf),
-              PROTOBUF_ULONGLONG(0xfdb97531eca86420));
+  a = MakeUint128(PROTOBUF_ULONGLONG(0x0123456789abcdef),
+                  PROTOBUF_ULONGLONG(0xfedcba9876543210));
+  b = MakeUint128(PROTOBUF_ULONGLONG(0x02468ace13579bdf),
+                  PROTOBUF_ULONGLONG(0xfdb97531eca86420));
   c = a * b;
-  EXPECT_EQ(uint128(PROTOBUF_ULONGLONG(0x97a87f4f261ba3f2),
-                    PROTOBUF_ULONGLONG(0x342d0bbf48948200)),
+  EXPECT_EQ(MakeUint128(PROTOBUF_ULONGLONG(0x97a87f4f261ba3f2),
+                        PROTOBUF_ULONGLONG(0x342d0bbf48948200)),
             c);
   EXPECT_EQ(0, c - b * a);
   EXPECT_EQ(a*a - b*b, (a+b) * (a-b));
 }
 
 TEST(Int128, AliasTests) {
-  uint128 x1(1, 2);
-  uint128 x2(2, 4);
+  uint128 x1 = MakeUint128(1, 2);
+  uint128 x2 = MakeUint128(2, 4);
   x1 += x1;
   EXPECT_EQ(x2, x1);
 
-  uint128 x3(1, static_cast<uint64>(1) << 63);
-  uint128 x4(3, 0);
+  uint128 x3 = MakeUint128(1, static_cast<uint64>(1) << 63);
+  uint128 x4 = MakeUint128(3, 0);
   x3 += x3;
   EXPECT_EQ(x4, x3);
 }
@@ -345,6 +267,12 @@
   a = 123;
   EXPECT_DEATH(a % b, "Division or mod by zero:");
 }
+
+TEST(Int128, ShiftGreater128) {
+  uint128 a;
+  EXPECT_DEATH(a << 128, "Left-shift greater or equal 128");
+  EXPECT_DEATH(a >> 128, "Right-shift greater or equal 128");
+}
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
 TEST(Int128, DivideAndMod) {
@@ -359,10 +287,10 @@
   EXPECT_EQ(0, q);
   EXPECT_EQ(0, r);
 
-  a = uint128(PROTOBUF_ULONGLONG(0x530eda741c71d4c3),
-              PROTOBUF_ULONGLONG(0xbf25975319080000));
-  q = uint128(PROTOBUF_ULONGLONG(0x4de2cab081),
-              PROTOBUF_ULONGLONG(0x14c34ab4676e4bab));
+  a = MakeUint128(PROTOBUF_ULONGLONG(0x530eda741c71d4c3),
+                  PROTOBUF_ULONGLONG(0xbf25975319080000));
+  q = MakeUint128(PROTOBUF_ULONGLONG(0x4de2cab081),
+                  PROTOBUF_ULONGLONG(0x14c34ab4676e4bab));
   b = uint128(0x1110001);
   r = uint128(0x3eb455);
   ASSERT_EQ(a, q * b + r);  // Sanity-check.
@@ -400,8 +328,8 @@
 
   // Try a large remainder.
   b = a / 2 + 1;
-  uint128 expected_r(PROTOBUF_ULONGLONG(0x29876d3a0e38ea61),
-                     PROTOBUF_ULONGLONG(0xdf92cba98c83ffff));
+  uint128 expected_r = MakeUint128(PROTOBUF_ULONGLONG(0x29876d3a0e38ea61),
+                                   PROTOBUF_ULONGLONG(0xdf92cba98c83ffff));
   // Sanity checks.
   ASSERT_EQ(a / 2 - 1, expected_r);
   ASSERT_EQ(a, b + expected_r);
@@ -421,8 +349,8 @@
 TEST(Int128, DivideAndModRandomInputs) {
   const int kNumIters = 1 << 18;
   for (int i = 0; i < kNumIters; ++i) {
-    const uint128 a(RandomUint64(), RandomUint64());
-    const uint128 b(RandomUint64(), RandomUint64());
+    const uint128 a = MakeUint128(RandomUint64(), RandomUint64());
+    const uint128 b = MakeUint128(RandomUint64(), RandomUint64());
     if (b == 0) {
       continue;  // Avoid a div-by-zero.
     }
@@ -432,24 +360,22 @@
   }
 }
 
-#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
 TEST(Int128, ConstexprTest) {
-  constexpr uint128 zero;
   constexpr uint128 one = 1;
-  constexpr uint128_pod pod = {2, 3};
-  constexpr uint128 from_pod = pod;
   constexpr uint128 minus_two = -2;
   EXPECT_EQ(one, uint128(1));
-  EXPECT_EQ(from_pod, uint128(2, 3));
-  EXPECT_EQ(minus_two, uint128(-1ULL, -2ULL));
+  EXPECT_EQ(minus_two, MakeUint128(-1ULL, -2ULL));
 }
 
+#if !defined(__GNUC__) || __GNUC__ > 4
+// libstdc++ is missing the required type traits pre gcc-5.0.0
+// https://gcc.gnu.org/onlinedocs/gcc-4.9.4/libstdc++/manual/manual/status.html#:~:text=20.9.4.3
 TEST(Int128, Traits) {
   EXPECT_TRUE(std::is_trivially_copy_constructible<uint128>::value);
   EXPECT_TRUE(std::is_trivially_copy_assignable<uint128>::value);
   EXPECT_TRUE(std::is_trivially_destructible<uint128>::value);
 }
-#endif  // GOOGLE_PROTOBUF_HAS_CONSTEXPR
+#endif  // !defined(__GNUC__) || __GNUC__ > 4
 
 TEST(Int128, OStream) {
   struct {
@@ -464,28 +390,28 @@
       {uint128(0), std::ios::oct, 0, '_', "0"},
       {uint128(0), std::ios::hex, 0, '_', "0"},
       // crossover between lo_ and hi_
-      {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"},
-      {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"},
-      {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"},
-      {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"},
-      {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
-      {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
+      {MakeUint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"},
+      {MakeUint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"},
+      {MakeUint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"},
+      {MakeUint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"},
+      {MakeUint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
+      {MakeUint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
       // just the top bit
-      {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0,
+      {MakeUint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0,
        '_', "170141183460469231731687303715884105728"},
-      {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0,
+      {MakeUint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0,
        '_', "2000000000000000000000000000000000000000000"},
-      {uint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0,
+      {MakeUint128(PROTOBUF_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0,
        '_', "80000000000000000000000000000000"},
       // maximum uint128 value
-      {uint128(-1, -1), std::ios::dec, 0, '_',
+      {MakeUint128(-1, -1), std::ios::dec, 0, '_',
        "340282366920938463463374607431768211455"},
-      {uint128(-1, -1), std::ios::oct, 0, '_',
+      {MakeUint128(-1, -1), std::ios::oct, 0, '_',
        "3777777777777777777777777777777777777777777"},
-      {uint128(-1, -1), std::ios::hex, 0, '_',
+      {MakeUint128(-1, -1), std::ios::hex, 0, '_',
        "ffffffffffffffffffffffffffffffff"},
       // uppercase
-      {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_',
+      {MakeUint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_',
        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
       // showbase
       {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"},
diff --git a/src/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
index f37048d..20b61f7 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -31,8 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_
 #define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
 
+#include <google/protobuf/stubs/int128.h>
 #include <google/protobuf/stubs/macros.h>
 #include <google/protobuf/stubs/port.h>
+#include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/stringpiece.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -63,11 +66,6 @@
 #endif
 };
 
-class StringPiece;
-namespace util {
-class Status;
-}
-class uint128;
 namespace internal {
 
 class LogFinisher;
diff --git a/src/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h
index c556d02..fcb0687 100644
--- a/src/google/protobuf/stubs/macros.h
+++ b/src/google/protobuf/stubs/macros.h
@@ -31,21 +31,19 @@
 #ifndef GOOGLE_PROTOBUF_MACROS_H__
 #define GOOGLE_PROTOBUF_MACROS_H__
 
-#include <google/protobuf/stubs/port.h>
-
 namespace google {
 namespace protobuf {
 
 #undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
 #define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName)    \
-  TypeName(const TypeName&);                           \
-  void operator=(const TypeName&)
+  TypeName(const TypeName&) = delete;                  \
+  void operator=(const TypeName&) = delete
 
 #undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS
 #define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
-  TypeName();                                           \
-  TypeName(const TypeName&);                            \
-  void operator=(const TypeName&)
+  TypeName() = delete;                                  \
+  TypeName(const TypeName&) = delete;                   \
+  void operator=(const TypeName&) = delete
 
 // ===================================================================
 // from google3/base/basictypes.h
@@ -89,31 +87,6 @@
   ((sizeof(a) / sizeof(*(a))) / \
    static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
 
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-//   COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
-//                  content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-//   COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-
-namespace internal {
-
-template <bool>
-struct CompileAssert {
-};
-
-}  // namespace internal
-
-#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
-
 }  // namespace protobuf
 }  // namespace google
 
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..f5c0fa4 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,14 @@
   // 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 +110,153 @@
 }
 
 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_) + ":" +
-          error_message_;
+      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..c858cf6 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,16 @@
 
   // 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;
-  }
-  int error_code() const {
-    return error_code_;
-  }
-  error::Code code() const {
-    return error_code_;
-  }
-  StringPiece error_message() const {
-    return error_message_;
-  }
+  bool ok() const { return error_code_ == StatusCode::kOk; }
+  StatusCode code() const { return error_code_; }
   StringPiece message() const {
     return error_message_;
   }
@@ -109,13 +93,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::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::OkStatus;
+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_macros.h b/src/google/protobuf/stubs/status_macros.h
index 0c64317..407ff4c 100644
--- a/src/google/protobuf/stubs/status_macros.h
+++ b/src/google/protobuf/stubs/status_macros.h
@@ -60,7 +60,7 @@
 template<typename T>
 Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
   if (result.ok()) {
-    lhs = result.ValueOrDie();
+    lhs = result.value();
   }
   return result.status();
 }
diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
index 8f4398c..9e9edf7 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());
@@ -106,33 +247,32 @@
   ASSERT_TRUE(a.ok());
 }
 
-TEST(Status, EqualsOK) {
-  ASSERT_EQ(util::Status::OK, util::Status());
-}
+TEST(Status, EqualsOK) { 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.cc b/src/google/protobuf/stubs/statusor.cc
index c744b8d..9c0a178 100644
--- a/src/google/protobuf/stubs/statusor.cc
+++ b/src/google/protobuf/stubs/statusor.cc
@@ -35,14 +35,14 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace internal {
+namespace statusor_internal {
 
 void StatusOrHelper::Crash(const Status& status) {
   GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
                     << status.ToString();
 }
 
-}  // namespace internal
+}  // namespace statusor_internal
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index c02e89a..a569502 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
@@ -42,7 +42,7 @@
 //
 //  StatusOr<float> result = DoBigCalculationThatCouldFail();
 //  if (result.ok()) {
-//    float answer = result.ValueOrDie();
+//    float answer = result.value();
 //    printf("Big calculation yielded: %f", answer);
 //  } else {
 //    LOG(ERROR) << result.status();
@@ -52,17 +52,7 @@
 //
 //  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
 //  if (result.ok()) {
-//    std::unique_ptr<Foo> foo(result.ValueOrDie());
-//    foo->DoSomethingCool();
-//  } else {
-//    LOG(ERROR) << result.status();
-//  }
-//
-// Example client usage for a StatusOr<std::unique_ptr<T>>:
-//
-//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
-//  if (result.ok()) {
-//    std::unique_ptr<Foo> foo = result.ConsumeValueOrDie();
+//    std::unique_ptr<Foo> foo(result.value());
 //    foo->DoSomethingCool();
 //  } else {
 //    LOG(ERROR) << result.status();
@@ -72,8 +62,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);
 //    }
@@ -94,30 +83,34 @@
 namespace google {
 namespace protobuf {
 namespace util {
+namespace statusor_internal {
 
 template<typename T>
 class StatusOr {
   template<typename U> friend class StatusOr;
 
  public:
-  // Construct a new StatusOr with Status::UNKNOWN status
-  StatusOr();
+  using value_type = T;
+
+  // Construct a new StatusOr with Status::UNKNOWN status.
+  // Construct a new StatusOr with UnknownError() status.
+  explicit StatusOr();
 
   // Construct a new StatusOr with the given non-ok status. After calling
-  // this constructor, calls to ValueOrDie() will CHECK-fail.
+  // this constructor, calls to value() will CHECK-fail.
   //
   // NOTE: Not explicit - we want to use StatusOr<T> as a return
   // 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
 
   // Construct a new StatusOr with the given value. If T is a plain pointer,
   // value must not be nullptr. After calling this constructor, calls to
-  // ValueOrDie() will succeed, and calls to status() will return OK.
+  // value() will succeed, and calls to status() will return OK.
   //
   // NOTE: Not explicit - we want to use StatusOr<T> as a return type
   // so it is convenient and sensible to be able to do 'return T()'
@@ -143,16 +136,13 @@
   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()
   bool ok() const;
 
   // Returns a reference to our current value, or CHECK-fails if !this->ok().
-  // If you need to initialize a T object from the stored value,
-  // ConsumeValueOrDie() may be more efficient.
-  const T& ValueOrDie() const;
   const T& value () const;
 
  private:
@@ -163,8 +153,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Implementation details for StatusOr<T>
 
-namespace internal {
-
 class PROTOBUF_EXPORT StatusOrHelper {
  public:
   // Move type-agnostic error handling to the .cc.
@@ -186,17 +174,13 @@
   static inline bool IsValueNull(const T* t) { return t == nullptr; }
 };
 
-}  // namespace internal
-
-template<typename T>
-inline StatusOr<T>::StatusOr()
-    : status_(util::Status::UNKNOWN) {
-}
+template <typename T>
+inline StatusOr<T>::StatusOr() : 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;
   }
@@ -204,10 +188,10 @@
 
 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.");
+  if (StatusOrHelper::Specialize<T>::IsValueNull(value)) {
+    status_ = util::InternalError("nullptr is not a valid argument.");
   } else {
-    status_ = Status::OK;
+    status_ = util::OkStatus();
     value_ = value;
   }
 }
@@ -249,20 +233,17 @@
 }
 
 template<typename T>
-inline const T& StatusOr<T>::ValueOrDie() const {
+inline const T& StatusOr<T>::value() const {
   if (!status_.ok()) {
-    internal::StatusOrHelper::Crash(status_);
+    StatusOrHelper::Crash(status_);
   }
   return value_;
 }
 
-template<typename T>
-inline const T& StatusOr<T>::value() const {
-  if (!status_.ok()) {
-    internal::StatusOrHelper::Crash(status_);
-  }
-  return value_;
-}
+}  // namespace statusor_internal
+
+using ::google::protobuf::util::statusor_internal::StatusOr;
+
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
index 6e2a9e5..403adcc 100644
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -71,20 +71,20 @@
 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) {
   const int kI = 4;
   StatusOr<int> thing(kI);
   EXPECT_TRUE(thing.ok());
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusOk) {
@@ -92,11 +92,11 @@
   StatusOr<int> original(kI);
   StatusOr<int> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOk) {
-  StatusOr<int> original(Status::CANCELLED);
+  StatusOr<int> original(util::CancelledError(""));
   StatusOr<int> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -106,11 +106,11 @@
   StatusOr<int>    original(kI);
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
-  StatusOr<int>    original(Status::CANCELLED);
+  StatusOr<int> original(util::CancelledError(""));
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -121,11 +121,11 @@
   StatusOr<int> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOk) {
-  StatusOr<int> source(Status::CANCELLED);
+  StatusOr<int> source(util::CancelledError(""));
   StatusOr<int> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -137,11 +137,11 @@
   StatusOr<double> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_DOUBLE_EQ(source.value(), target.value());
 }
 
 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,40 +150,40 @@
 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) {
   const int kI = 4;
   StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 TEST(StatusOr, TestValueConst) {
   const int kI = 4;
   const StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.ValueOrDie());
+  EXPECT_EQ(kI, thing.value());
 }
 
 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) {
   const int kI = 4;
   StatusOr<const int*> thing(&kI);
   EXPECT_TRUE(thing.ok());
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusOk) {
@@ -191,11 +191,11 @@
   StatusOr<const int*> original(&kI);
   StatusOr<const int*> copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie());
+  EXPECT_EQ(original.value(), copy.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
-  StatusOr<int*> original(Status::CANCELLED);
+  StatusOr<int*> original(util::CancelledError(""));
   StatusOr<int*> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -205,12 +205,11 @@
   StatusOr<Derived*> original(&derived);
   StatusOr<Base2*>   copy(original);
   EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(static_cast<const Base2*>(original.ValueOrDie()),
-            copy.ValueOrDie());
+  EXPECT_EQ(static_cast<const Base2*>(original.value()), copy.value());
 }
 
 TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
-  StatusOr<Derived*> original(Status::CANCELLED);
+  StatusOr<Derived*> original(util::CancelledError(""));
   StatusOr<Base2*>   copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -221,11 +220,11 @@
   StatusOr<const int*> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie());
+  EXPECT_EQ(source.value(), target.value());
 }
 
 TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
-  StatusOr<int*> source(Status::CANCELLED);
+  StatusOr<int*> source(util::CancelledError(""));
   StatusOr<int*> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
@@ -237,12 +236,11 @@
   StatusOr<Base2*>   target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(static_cast<const Base2*>(source.ValueOrDie()),
-            target.ValueOrDie());
+  EXPECT_EQ(static_cast<const Base2*>(source.value()), target.value());
 }
 
 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,20 +250,20 @@
   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) {
   const int kI = 0;
   StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 TEST(StatusOr, TestPointerValueConst) {
   const int kI = 0;
   const StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.ValueOrDie());
+  EXPECT_EQ(&kI, thing.value());
 }
 
 }  // namespace
diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc
index 353c78c..a014d1f 100644
--- a/src/google/protobuf/stubs/stringpiece.cc
+++ b/src/google/protobuf/stubs/stringpiece.cc
@@ -39,31 +39,13 @@
 
 namespace google {
 namespace protobuf {
+namespace stringpiece_internal {
+
 std::ostream& operator<<(std::ostream& o, StringPiece piece) {
   o.write(piece.data(), piece.size());
   return o;
 }
 
-// Out-of-line error path.
-void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
-  GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
-}
-
-StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos)
-    : ptr_(x.ptr_ + pos), length_(x.length_ - pos) {
-  GOOGLE_DCHECK_LE(0, pos);
-  GOOGLE_DCHECK_LE(pos, x.length_);
-}
-
-StringPiece::StringPiece(StringPiece x,
-                         stringpiece_ssize_type pos,
-                         stringpiece_ssize_type len)
-    : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) {
-  GOOGLE_DCHECK_LE(0, pos);
-  GOOGLE_DCHECK_LE(pos, x.length_);
-  GOOGLE_DCHECK_GE(len, 0);
-}
-
 void StringPiece::CopyToString(std::string* target) const {
   target->assign(ptr_, length_);
 }
@@ -89,10 +71,9 @@
   return false;
 }
 
-stringpiece_ssize_type StringPiece::copy(char* buf,
-                                         size_type n,
-                                         size_type pos) const {
-  stringpiece_ssize_type ret = std::min(length_ - pos, n);
+StringPiece::size_type StringPiece::copy(
+    char* buf, size_type n, size_type pos) const {
+  size_type ret = std::min(length_ - pos, n);
   memcpy(buf, ptr_ + pos, ret);
   return ret;
 }
@@ -101,7 +82,8 @@
   return find(s, 0) != npos;
 }
 
-stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const {
+StringPiece::size_type StringPiece::find(
+    StringPiece s, size_type pos) const {
   if (length_ <= 0 || pos > static_cast<size_type>(length_)) {
     if (length_ == 0 && pos == 0 && s.length_ == 0) return 0;
     return npos;
@@ -111,7 +93,7 @@
   return result == ptr_ + length_ ? npos : result - ptr_;
 }
 
-stringpiece_ssize_type StringPiece::find(char c, size_type pos) const {
+StringPiece::size_type StringPiece::find(char c, size_type pos) const {
   if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
     return npos;
   }
@@ -120,7 +102,7 @@
   return result != nullptr ? result - ptr_ : npos;
 }
 
-stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const {
+StringPiece::size_type StringPiece::rfind(StringPiece s, size_type pos) const {
   if (length_ < s.length_) return npos;
   const size_t ulen = length_;
   if (s.length_ == 0) return std::min(ulen, pos);
@@ -131,10 +113,10 @@
 }
 
 // Search range is [0..pos] inclusive.  If pos == npos, search everything.
-stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const {
+StringPiece::size_type StringPiece::rfind(char c, size_type pos) const {
   // Note: memrchr() is not available on Windows.
-  if (length_ <= 0) return npos;
-  for (stringpiece_ssize_type i =
+  if (empty()) return npos;
+  for (difference_type i =
       std::min(pos, static_cast<size_type>(length_ - 1));
        i >= 0; --i) {
     if (ptr_[i] == c) {
@@ -154,16 +136,16 @@
 //   bool table[UCHAR_MAX + 1]
 static inline void BuildLookupTable(StringPiece characters_wanted,
                                     bool* table) {
-  const stringpiece_ssize_type length = characters_wanted.length();
+  const StringPiece::size_type length = characters_wanted.length();
   const char* const data = characters_wanted.data();
-  for (stringpiece_ssize_type i = 0; i < length; ++i) {
+  for (StringPiece::size_type i = 0; i < length; ++i) {
     table[static_cast<unsigned char>(data[i])] = true;
   }
 }
 
-stringpiece_ssize_type StringPiece::find_first_of(StringPiece s,
-                                                  size_type pos) const {
-  if (length_ <= 0 || s.length_ <= 0) {
+StringPiece::size_type StringPiece::find_first_of(
+    StringPiece s, size_type pos) const {
+  if (empty() || s.empty()) {
     return npos;
   }
   // Avoid the cost of BuildLookupTable() for a single-character search.
@@ -171,7 +153,7 @@
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+  for (size_type i = pos; i < length_; ++i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
@@ -179,16 +161,16 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s,
-                                                      size_type pos) const {
-  if (length_ <= 0) return npos;
-  if (s.length_ <= 0) return 0;
+StringPiece::size_type StringPiece::find_first_not_of(
+    StringPiece s, size_type pos) const {
+  if (empty()) return npos;
+  if (s.empty()) return 0;
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i = pos; i < length_; ++i) {
+  for (size_type i = pos; i < length_; ++i) {
     if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
     }
@@ -196,9 +178,9 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_first_not_of(char c,
-                                                      size_type pos) const {
-  if (length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_first_not_of(
+    char c, size_type pos) const {
+  if (empty()) return npos;
 
   for (; pos < static_cast<size_type>(length_); ++pos) {
     if (ptr_[pos] != c) {
@@ -208,15 +190,15 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_of(StringPiece s,
-                                                 size_type pos) const {
-  if (length_ <= 0 || s.length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_last_of(
+    StringPiece s, size_type pos) const {
+  if (empty() || s.empty()) return npos;
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_last_of(s.ptr_[0], pos);
 
   bool lookup[UCHAR_MAX + 1] = { false };
   BuildLookupTable(s, lookup);
-  for (stringpiece_ssize_type i =
+  for (difference_type i =
        std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
     if (lookup[static_cast<unsigned char>(ptr_[i])]) {
       return i;
@@ -225,12 +207,12 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s,
-                                                     size_type pos) const {
-  if (length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_last_not_of(
+    StringPiece s, size_type pos) const {
+  if (empty()) return npos;
 
-  stringpiece_ssize_type i = std::min(pos, static_cast<size_type>(length_ - 1));
-  if (s.length_ <= 0) return i;
+  size_type i = std::min(pos, length()-1);
+  if (s.empty()) return i;
 
   // Avoid the cost of BuildLookupTable() for a single-character search.
   if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos);
@@ -245,11 +227,11 @@
   return npos;
 }
 
-stringpiece_ssize_type StringPiece::find_last_not_of(char c,
-                                                     size_type pos) const {
-  if (length_ <= 0) return npos;
+StringPiece::size_type StringPiece::find_last_not_of(
+    char c, size_type pos) const {
+  if (empty()) return npos;
 
-  for (stringpiece_ssize_type i =
+  for (difference_type i =
        std::min(pos, static_cast<size_type>(length_ - 1)); i >= 0; --i) {
     if (ptr_[i] != c) {
       return i;
@@ -259,12 +241,13 @@
 }
 
 StringPiece StringPiece::substr(size_type pos, size_type n) const {
-  if (pos > length_) pos = length_;
-  if (n > length_ - pos) n = length_ - pos;
+  if (pos > length()) pos = length();
+  if (n > length_ - pos) n = length() - pos;
   return StringPiece(ptr_ + pos, n);
 }
 
 const StringPiece::size_type StringPiece::npos = size_type(-1);
 
+}  // namespace stringpiece_internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
index fbcb20a..1e896e0 100644
--- a/src/google/protobuf/stubs/stringpiece.h
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -154,52 +154,26 @@
 
 namespace google {
 namespace protobuf {
-// StringPiece has *two* size types.
-// StringPiece::size_type
-//   is unsigned
-//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
-//   no future changes intended
-// stringpiece_ssize_type
-//   is signed
-//   is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64
-//   future changes intended: http://go/64BitStringPiece
-//
-typedef std::string::difference_type stringpiece_ssize_type;
-
-// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows.
-// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit.
-#if !defined(NDEBUG)
-#define STRINGPIECE_CHECK_SIZE 1
-#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
-#define STRINGPIECE_CHECK_SIZE 1
-#else
-#define STRINGPIECE_CHECK_SIZE 0
-#endif
+namespace stringpiece_internal {
 
 class PROTOBUF_EXPORT StringPiece {
+ public:
+  using traits_type = std::char_traits<char>;
+  using value_type = char;
+  using pointer = char*;
+  using const_pointer = const char*;
+  using reference = char&;
+  using const_reference = const char&;
+  using const_iterator = const char*;
+  using iterator = const_iterator;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using reverse_iterator = const_reverse_iterator;
+  using size_type = size_t;
+  using difference_type = std::ptrdiff_t;
+
  private:
   const char* ptr_;
-  stringpiece_ssize_type length_;
-
-  // Prevent overflow in debug mode or fortified mode.
-  // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t).
-  static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) {
-#if STRINGPIECE_CHECK_SIZE > 0
-#ifdef max
-#undef max
-#endif
-    if (size > static_cast<size_t>(
-        std::numeric_limits<stringpiece_ssize_type>::max())) {
-      // Some people grep for this message in logs
-      // so take care if you ever change it.
-      LogFatalSizeTooBig(size, "size_t to int conversion");
-    }
-#endif
-    return static_cast<stringpiece_ssize_type>(size);
-  }
-
-  // Out-of-line error path.
-  static void LogFatalSizeTooBig(size_t size, const char* details);
+  size_type length_;
 
  public:
   // We provide non-explicit singleton constructors so users can pass
@@ -213,7 +187,7 @@
   StringPiece(const char* str)  // NOLINT(runtime/explicit)
       : ptr_(str), length_(0) {
     if (str != nullptr) {
-      length_ = CheckedSsizeTFromSizeT(strlen(str));
+      length_ = strlen(str);
     }
   }
 
@@ -221,78 +195,40 @@
   StringPiece(  // NOLINT(runtime/explicit)
       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
       : ptr_(str.data()), length_(0) {
-    length_ = CheckedSsizeTFromSizeT(str.size());
+    length_ = str.size();
   }
 
-  StringPiece(const char* offset, stringpiece_ssize_type len)
-      : ptr_(offset), length_(len) {
-    assert(len >= 0);
-  }
-
-  // Substring of another StringPiece.
-  // pos must be non-negative and <= x.length().
-  StringPiece(StringPiece x, stringpiece_ssize_type pos);
-  // Substring of another StringPiece.
-  // pos must be non-negative and <= x.length().
-  // len must be non-negative and will be pinned to at most x.length() - pos.
-  StringPiece(StringPiece x,
-              stringpiece_ssize_type pos,
-              stringpiece_ssize_type len);
+  StringPiece(const char* offset, size_type len)
+      : ptr_(offset), length_(len) {}
 
   // data() may return a pointer to a buffer with embedded NULs, and the
   // returned buffer may or may not be null terminated.  Therefore it is
   // typically a mistake to pass data() to a routine that expects a NUL
   // terminated string.
-  const char* data() const { return ptr_; }
-  stringpiece_ssize_type size() const { return length_; }
-  stringpiece_ssize_type length() const { return length_; }
+  const_pointer data() const { return ptr_; }
+  size_type size() const { return length_; }
+  size_type length() const { return length_; }
   bool empty() const { return length_ == 0; }
 
-  void clear() {
-    ptr_ = nullptr;
-    length_ = 0;
-  }
-
-  void set(const char* data, stringpiece_ssize_type len) {
-    assert(len >= 0);
-    ptr_ = data;
-    length_ = len;
-  }
-
-  void set(const char* str) {
-    ptr_ = str;
-    if (str != nullptr)
-      length_ = CheckedSsizeTFromSizeT(strlen(str));
-    else
-      length_ = 0;
-  }
-
-  void set(const void* data, stringpiece_ssize_type len) {
-    ptr_ = reinterpret_cast<const char*>(data);
-    length_ = len;
-  }
-
-  char operator[](stringpiece_ssize_type i) const {
-    assert(0 <= i);
+  char operator[](size_type i) const {
     assert(i < length_);
     return ptr_[i];
   }
 
-  void remove_prefix(stringpiece_ssize_type n) {
+  void remove_prefix(size_type n) {
     assert(length_ >= n);
     ptr_ += n;
     length_ -= n;
   }
 
-  void remove_suffix(stringpiece_ssize_type n) {
+  void remove_suffix(size_type n) {
     assert(length_ >= n);
     length_ -= n;
   }
 
   // returns {-1, 0, 1}
   int compare(StringPiece x) const {
-    const stringpiece_ssize_type min_size =
-        length_ < x.length_ ? length_ : x.length_;
+    size_type min_size = length_ < x.length_ ? length_ : x.length_;
     int r = memcmp(ptr_, x.ptr_, static_cast<size_t>(min_size));
     if (r < 0) return -1;
     if (r > 0) return 1;
@@ -336,53 +272,41 @@
   bool ConsumeFromEnd(StringPiece x);
 
   // standard STL container boilerplate
-  typedef char value_type;
-  typedef const char* pointer;
-  typedef const char& reference;
-  typedef const char& const_reference;
-  typedef size_t size_type;
-  typedef ptrdiff_t difference_type;
   static const size_type npos;
-  typedef const char* const_iterator;
-  typedef const char* iterator;
-  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
-  typedef std::reverse_iterator<iterator> reverse_iterator;
-  iterator begin() const { return ptr_; }
-  iterator end() const { return ptr_ + length_; }
+  const_iterator begin() const { return ptr_; }
+  const_iterator end() const { return ptr_ + length_; }
   const_reverse_iterator rbegin() const {
     return const_reverse_iterator(ptr_ + length_);
   }
   const_reverse_iterator rend() const {
     return const_reverse_iterator(ptr_);
   }
-  stringpiece_ssize_type max_size() const { return length_; }
-  stringpiece_ssize_type capacity() const { return length_; }
+  size_type max_size() const { return length_; }
+  size_type capacity() const { return length_; }
 
   // cpplint.py emits a false positive [build/include_what_you_use]
-  stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
+  size_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
 
   bool contains(StringPiece s) const;
 
-  stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const;
-  stringpiece_ssize_type find(char c, size_type pos = 0) const;
-  stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const;
-  stringpiece_ssize_type rfind(char c, size_type pos = npos) const;
+  size_type find(StringPiece s, size_type pos = 0) const;
+  size_type find(char c, size_type pos = 0) const;
+  size_type rfind(StringPiece s, size_type pos = npos) const;
+  size_type rfind(char c, size_type pos = npos) const;
 
-  stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const;
-  stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const {
+  size_type find_first_of(StringPiece s, size_type pos = 0) const;
+  size_type find_first_of(char c, size_type pos = 0) const {
     return find(c, pos);
   }
-  stringpiece_ssize_type find_first_not_of(StringPiece s,
-                                           size_type pos = 0) const;
-  stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const;
-  stringpiece_ssize_type find_last_of(StringPiece s,
-                                      size_type pos = npos) const;
-  stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const {
+  size_type find_first_not_of(StringPiece s, size_type pos = 0) const;
+  size_type find_first_not_of(char c, size_type pos = 0) const;
+  size_type find_last_of(StringPiece s, size_type pos = npos) const;
+  size_type find_last_of(char c, size_type pos = npos) const {
     return rfind(c, pos);
   }
-  stringpiece_ssize_type find_last_not_of(StringPiece s,
+  size_type find_last_not_of(StringPiece s,
                                           size_type pos = npos) const;
-  stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const;
+  size_type find_last_not_of(char c, size_type pos = npos) const;
 
   StringPiece substr(size_type pos, size_type n = npos) const;
 };
@@ -391,7 +315,7 @@
 // one of the arguments is a literal, the compiler can elide a lot of the
 // following comparisons.
 inline bool operator==(StringPiece x, StringPiece y) {
-  stringpiece_ssize_type len = x.size();
+  StringPiece::size_type len = x.size();
   if (len != y.size()) {
     return false;
   }
@@ -405,7 +329,7 @@
 }
 
 inline bool operator<(StringPiece x, StringPiece y) {
-  const stringpiece_ssize_type min_size =
+  const StringPiece::size_type min_size =
       x.size() < y.size() ? x.size() : y.size();
   const int r = memcmp(x.data(), y.data(), static_cast<size_t>(min_size));
   return (r < 0) || (r == 0 && x.size() < y.size());
@@ -426,49 +350,10 @@
 // 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;
-  }
+}  // namespace stringpiece_internal
 
-  // Cast to StringPiece.
-  operator StringPiece() const { return StringPiece(data_, size_); }
+using ::google::protobuf::stringpiece_internal::StringPiece;
 
-  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/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc
index 846e1ae..e85a2e5 100644
--- a/src/google/protobuf/stubs/stringpiece_unittest.cc
+++ b/src/google/protobuf/stubs/stringpiece_unittest.cc
@@ -305,16 +305,9 @@
   const StringPiece a("abcdefghijklmnopqrstuvwxyz");
   const StringPiece b("abc");
   const StringPiece c("xyz");
-  StringPiece d("foobar");
   const StringPiece e;
   const StringPiece f("123" "\0" "456", 7);
 
-  d.clear();
-  EXPECT_EQ(d.size(), 0);
-  EXPECT_TRUE(d.empty());
-  EXPECT_TRUE(d.data() == nullptr);
-  EXPECT_TRUE(d.begin() == d.end());
-
   EXPECT_EQ(StringPiece::npos, std::string::npos);
 
   EXPECT_EQ(a.find(b), 0);
@@ -324,26 +317,16 @@
   EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos);
   EXPECT_EQ(b.find(c), StringPiece::npos);
   EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos);
-  EXPECT_EQ(a.find(d), 0);
   EXPECT_EQ(a.find(e), 0);
-  EXPECT_EQ(a.find(d, 12), 12);
   EXPECT_EQ(a.find(e, 17), 17);
   StringPiece g("xx not found bb");
   EXPECT_EQ(a.find(g), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.find(b), StringPiece::npos);
   EXPECT_EQ(e.find(b), StringPiece::npos);
-  EXPECT_EQ(d.find(b, 4), StringPiece::npos);
   EXPECT_EQ(e.find(b, 7), StringPiece::npos);
 
   size_t empty_search_pos = std::string().find(std::string());
-  EXPECT_EQ(d.find(d), empty_search_pos);
-  EXPECT_EQ(d.find(e), empty_search_pos);
-  EXPECT_EQ(e.find(d), empty_search_pos);
   EXPECT_EQ(e.find(e), empty_search_pos);
-  EXPECT_EQ(d.find(d, 4), std::string().find(std::string(), 4));
-  EXPECT_EQ(d.find(e, 4), std::string().find(std::string(), 4));
-  EXPECT_EQ(e.find(d, 4), std::string().find(std::string(), 4));
   EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
 
   EXPECT_EQ(a.find('a'), 0);
@@ -359,13 +342,9 @@
   EXPECT_EQ(g.find('o', 5), 8);
   EXPECT_EQ(a.find('b', 5), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.find('\0'), StringPiece::npos);
   EXPECT_EQ(e.find('\0'), StringPiece::npos);
-  EXPECT_EQ(d.find('\0', 4), StringPiece::npos);
   EXPECT_EQ(e.find('\0', 7), StringPiece::npos);
-  EXPECT_EQ(d.find('x'), StringPiece::npos);
   EXPECT_EQ(e.find('x'), StringPiece::npos);
-  EXPECT_EQ(d.find('x', 4), StringPiece::npos);
   EXPECT_EQ(e.find('x', 7), StringPiece::npos);
 
   EXPECT_EQ(a.rfind(b), 0);
@@ -376,23 +355,13 @@
   EXPECT_EQ(a.rfind(c, 0), StringPiece::npos);
   EXPECT_EQ(b.rfind(c), StringPiece::npos);
   EXPECT_EQ(b.rfind(c, 0), StringPiece::npos);
-  EXPECT_EQ(a.rfind(d), a.as_string().rfind(std::string()));
   EXPECT_EQ(a.rfind(e), a.as_string().rfind(std::string()));
-  EXPECT_EQ(a.rfind(d, 12), 12);
   EXPECT_EQ(a.rfind(e, 17), 17);
   EXPECT_EQ(a.rfind(g), StringPiece::npos);
-  EXPECT_EQ(d.rfind(b), StringPiece::npos);
   EXPECT_EQ(e.rfind(b), StringPiece::npos);
-  EXPECT_EQ(d.rfind(b, 4), StringPiece::npos);
   EXPECT_EQ(e.rfind(b, 7), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
-  EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
-  EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
   EXPECT_EQ(e.rfind(e, 7), std::string().rfind(std::string()));
-  EXPECT_EQ(d.rfind(d), std::string().rfind(std::string()));
-  EXPECT_EQ(e.rfind(d), std::string().rfind(std::string()));
-  EXPECT_EQ(d.rfind(e), std::string().rfind(std::string()));
   EXPECT_EQ(e.rfind(e), std::string().rfind(std::string()));
 
   EXPECT_EQ(g.rfind('o'), 8);
@@ -405,9 +374,7 @@
   EXPECT_EQ(f.rfind('3'), 2);
   EXPECT_EQ(f.rfind('5'), 5);
   // empty string nonsense
-  EXPECT_EQ(d.rfind('o'), StringPiece::npos);
   EXPECT_EQ(e.rfind('o'), StringPiece::npos);
-  EXPECT_EQ(d.rfind('o', 4), StringPiece::npos);
   EXPECT_EQ(e.rfind('o', 7), StringPiece::npos);
 
   EXPECT_EQ(a.find_first_of(b), 0);
@@ -425,13 +392,8 @@
   EXPECT_EQ(a.find_first_of(f), StringPiece::npos);
   EXPECT_EQ(f.find_first_of(a), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(a.find_first_of(d), StringPiece::npos);
   EXPECT_EQ(a.find_first_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(b), StringPiece::npos);
   EXPECT_EQ(e.find_first_of(b), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(d), StringPiece::npos);
-  EXPECT_EQ(e.find_first_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_first_of(e), StringPiece::npos);
   EXPECT_EQ(e.find_first_of(e), StringPiece::npos);
 
   EXPECT_EQ(a.find_first_not_of(b), 3);
@@ -440,14 +402,9 @@
   EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos);
   EXPECT_EQ(f.find_first_not_of(a), 0);
   EXPECT_EQ(a.find_first_not_of(f), 0);
-  EXPECT_EQ(a.find_first_not_of(d), 0);
   EXPECT_EQ(a.find_first_not_of(e), 0);
   // empty string nonsense
-  EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos);
-  EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos);
 
   StringPiece h("====");
@@ -459,9 +416,7 @@
   EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
   EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
   // empty string nonsense
-  EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos);
   EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos);
 
   //  StringPiece g("xx not found bb");
@@ -483,21 +438,11 @@
   EXPECT_EQ(f.find_last_of(i, 6), 6);
   EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(f.find_last_of(d), StringPiece::npos);
   EXPECT_EQ(f.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos);
   EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(d), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(f), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(f), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos);
 
   EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
@@ -509,21 +454,11 @@
   EXPECT_EQ(a.find_last_not_of(b, 3), 3);
   EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos);
   // empty string nonsense
-  EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
   EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
-  EXPECT_EQ(f.find_last_not_of(d, 4), 4);
   EXPECT_EQ(f.find_last_not_of(e, 4), 4);
-  EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos);
 
   EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1);
@@ -533,9 +468,7 @@
   EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos);
   EXPECT_EQ(b.find_last_not_of('b', 1), 0);
   // empty string nonsense
-  EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos);
   EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos);
 
   EXPECT_EQ(a.substr(0, 3), b);
@@ -546,33 +479,15 @@
   EXPECT_EQ(a.substr(3, 2), "de");
   // empty string nonsense
   EXPECT_EQ(a.substr(99, 2), e);
-  EXPECT_EQ(d.substr(99), e);
-  EXPECT_EQ(d.substr(0, 99), e);
-  EXPECT_EQ(d.substr(99, 99), e);
+  EXPECT_EQ(e.substr(99), e);
+  EXPECT_EQ(e.substr(0, 99), e);
+  EXPECT_EQ(e.substr(99, 99), e);
   // use of npos
   EXPECT_EQ(a.substr(0, StringPiece::npos), a);
   EXPECT_EQ(a.substr(23, StringPiece::npos), c);
   EXPECT_EQ(a.substr(StringPiece::npos, 0), e);
   EXPECT_EQ(a.substr(StringPiece::npos, 1), e);
   EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e);
-
-  // Substring constructors.
-  EXPECT_EQ(StringPiece(a, 0, 3), b);
-  EXPECT_EQ(StringPiece(a, 23), c);
-  EXPECT_EQ(StringPiece(a, 23, 3), c);
-  EXPECT_EQ(StringPiece(a, 23, 99), c);
-  EXPECT_EQ(StringPiece(a, 0), a);
-  EXPECT_EQ(StringPiece(a, 3, 2), "de");
-  // empty string nonsense
-  EXPECT_EQ(StringPiece(d, 0, 99), e);
-  // Verify that they work taking an actual string, not just a StringPiece.
-  std::string a2 = a.as_string();
-  EXPECT_EQ(StringPiece(a2, 0, 3), b);
-  EXPECT_EQ(StringPiece(a2, 23), c);
-  EXPECT_EQ(StringPiece(a2, 23, 3), c);
-  EXPECT_EQ(StringPiece(a2, 23, 99), c);
-  EXPECT_EQ(StringPiece(a2, 0), a);
-  EXPECT_EQ(StringPiece(a2, 3, 2), "de");
 }
 
 TEST(StringPiece, Custom) {
@@ -647,23 +562,7 @@
   c.remove_suffix(c.size());
   EXPECT_EQ(c, e);
 
-  // set
-  c.set("foobar", 6);
-  EXPECT_EQ(c, a);
-  c.set("foobar", 0);
-  EXPECT_EQ(c, e);
-  c.set("foobar", 7);
-  EXPECT_NE(c, a);
-
-  c.set("foobar");
-  EXPECT_EQ(c, a);
-
-  c.set(static_cast<const void*>("foobar"), 6);
-  EXPECT_EQ(c, a);
-  c.set(static_cast<const void*>("foobar"), 0);
-  EXPECT_EQ(c, e);
-  c.set(static_cast<const void*>("foobar"), 7);
-  EXPECT_NE(c, a);
+  c = StringPiece("foobar", 7);
 
   // as_string
   std::string s3(a.as_string().c_str(), 7);
@@ -680,21 +579,25 @@
   }
 
   // Consume
-  a.set("foobar");
-  EXPECT_TRUE(a.Consume("foo"));
-  EXPECT_EQ(a, "bar");
-  EXPECT_FALSE(a.Consume("foo"));
-  EXPECT_FALSE(a.Consume("barbar"));
-  EXPECT_FALSE(a.Consume("ar"));
-  EXPECT_EQ(a, "bar");
+  {
+    StringPiece str("foobar");
+    EXPECT_TRUE(str.Consume("foo"));
+    EXPECT_EQ(str, "bar");
+    EXPECT_FALSE(str.Consume("foo"));
+    EXPECT_FALSE(str.Consume("barbar"));
+    EXPECT_FALSE(str.Consume("ar"));
+    EXPECT_EQ(str, "bar");
+  }
 
-  a.set("foobar");
-  EXPECT_TRUE(a.ConsumeFromEnd("bar"));
-  EXPECT_EQ(a, "foo");
-  EXPECT_FALSE(a.ConsumeFromEnd("bar"));
-  EXPECT_FALSE(a.ConsumeFromEnd("foofoo"));
-  EXPECT_FALSE(a.ConsumeFromEnd("fo"));
-  EXPECT_EQ(a, "foo");
+  {
+  StringPiece str("foobar");
+  EXPECT_TRUE(str.ConsumeFromEnd("bar"));
+  EXPECT_EQ(str, "foo");
+  EXPECT_FALSE(str.ConsumeFromEnd("bar"));
+  EXPECT_FALSE(str.ConsumeFromEnd("foofoo"));
+  EXPECT_FALSE(str.ConsumeFromEnd("fo"));
+  EXPECT_EQ(str, "foo");
+  }
 }
 
 TEST(StringPiece, Contains) {
@@ -713,10 +616,6 @@
   EXPECT_EQ(s.data(), (const char*)nullptr);
   EXPECT_EQ(s.size(), 0);
 
-  s.set(nullptr);
-  EXPECT_EQ(s.data(), (const char*)nullptr);
-  EXPECT_EQ(s.size(), 0);
-
   // .ToString() on a StringPiece with nullptr should produce the empty string.
   EXPECT_EQ("", s.ToString());
   EXPECT_EQ("", s.as_string());
diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc
index 2603164..0761986 100644
--- a/src/google/protobuf/stubs/stringprintf.cc
+++ b/src/google/protobuf/stubs/stringprintf.cc
@@ -162,7 +162,7 @@
   // that accepts an array of arguments.  The best I can do is stick
   // this COMPILE_ASSERT right next to the actual statement.
 
-  GOOGLE_COMPILE_ASSERT(kStringPrintfVectorMaxArgs == 32, arg_count_mismatch);
+  static_assert(kStringPrintfVectorMaxArgs == 32, "arg_count_mismatch");
   return StringPrintf(format,
                       cstr[0], cstr[1], cstr[2], cstr[3], cstr[4],
                       cstr[5], cstr[6], cstr[7], cstr[8], cstr[9],
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
index 2ecdb2b..84ea62e 100644
--- a/src/google/protobuf/stubs/strutil.cc
+++ b/src/google/protobuf/stubs/strutil.cc
@@ -545,7 +545,7 @@
   };
 
   size_t escaped_len = 0;
-  for (int i = 0; i < src.size(); ++i) {
+  for (StringPiece::size_type i = 0; i < src.size(); ++i) {
     unsigned char c = static_cast<unsigned char>(src[i]);
     escaped_len += c_escaped_len[c];
   }
@@ -569,7 +569,7 @@
   dest->resize(cur_dest_len + escaped_len);
   char* append_ptr = &(*dest)[cur_dest_len];
 
-  for (int i = 0; i < src.size(); ++i) {
+  for (StringPiece::size_type i = 0; i < src.size(); ++i) {
     unsigned char c = static_cast<unsigned char>(src[i]);
     switch (c) {
       case '\n': *append_ptr++ = '\\'; *append_ptr++ = 'n'; break;
@@ -1244,7 +1244,7 @@
   // platforms these days.  Just in case some system exists where DBL_DIG
   // is significantly larger -- and risks overflowing our buffer -- we have
   // this assert.
-  GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big);
+  static_assert(DBL_DIG < 20, "DBL_DIG_is_too_big");
 
   if (value == std::numeric_limits<double>::infinity()) {
     strcpy(buffer, "inf");
@@ -1362,7 +1362,7 @@
   // platforms these days.  Just in case some system exists where FLT_DIG
   // is significantly larger -- and risks overflowing our buffer -- we have
   // this assert.
-  GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big);
+  static_assert(FLT_DIG < 10, "FLT_DIG_is_too_big");
 
   if (value == std::numeric_limits<double>::infinity()) {
     strcpy(buffer, "inf");
@@ -1619,7 +1619,8 @@
   std::string tmp;
   int num_replacements = 0;
   int pos = 0;
-  for (int match_pos = s->find(substring.data(), pos, substring.length());
+  for (StringPiece::size_type match_pos =
+           s->find(substring.data(), pos, substring.length());
        match_pos != std::string::npos; pos = match_pos + substring.length(),
            match_pos = s->find(substring.data(), pos, substring.length())) {
     ++num_replacements;
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
index 8ce81f2..84fc232 100644
--- a/src/google/protobuf/stubs/strutil.h
+++ b/src/google/protobuf/stubs/strutil.h
@@ -377,14 +377,14 @@
 // For now, long long is 64-bit on all the platforms we care about, so these
 // functions can simply pass the call to strto[u]ll.
 inline int64 strto64(const char *nptr, char **endptr, int base) {
-  GOOGLE_COMPILE_ASSERT(sizeof(int64) == sizeof(long long),
-                        sizeof_int64_is_not_sizeof_long_long);
+  static_assert(sizeof(int64) == sizeof(long long),
+                "sizeof_int64_is_not_sizeof_long_long");
   return strtoll(nptr, endptr, base);
 }
 
 inline uint64 strtou64(const char *nptr, char **endptr, int base) {
-  GOOGLE_COMPILE_ASSERT(sizeof(uint64) == sizeof(unsigned long long),
-                        sizeof_uint64_is_not_sizeof_long_long);
+  static_assert(sizeof(uint64) == sizeof(unsigned long long),
+                "sizeof_uint64_is_not_sizeof_long_long");
   return strtoull(nptr, endptr, base);
 }
 
@@ -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.cc b/src/google/protobuf/timestamp.pb.cc
index ac920a1..a3040a6 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -67,10 +67,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
-  return descriptor_table_google_2fprotobuf_2ftimestamp_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -142,7 +140,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1:
@@ -160,7 +157,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -297,10 +295,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Timestamp::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[0]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index 6d0fe0e..f399dd0 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Timestamp;
 struct TimestampDefaultTypeInternal;
@@ -70,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);
@@ -96,10 +95,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Timestamp& default_instance() {
     return *internal_default_instance();
@@ -167,12 +166,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index e2f7a8f..024b277 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -229,10 +229,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2ftype_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2ftype_2eproto, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto, file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
-  return descriptor_table_google_2fprotobuf_2ftype_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2ftype_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2ftype_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -432,7 +430,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -498,7 +495,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -712,10 +710,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Type::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[0]);
 }
 
-
 // ===================================================================
 
 class Field::_Internal {
@@ -816,7 +815,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // .google.protobuf.Field.Kind kind = 1;
       case 1:
@@ -905,7 +903,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1189,10 +1188,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Field::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[1]);
 }
 
-
 // ===================================================================
 
 class Enum::_Internal {
@@ -1289,7 +1289,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1341,7 +1340,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1535,10 +1535,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Enum::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[2]);
 }
 
-
 // ===================================================================
 
 class EnumValue::_Internal {
@@ -1608,7 +1609,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1640,7 +1640,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1794,10 +1795,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[3]);
 }
 
-
 // ===================================================================
 
 class Option::_Internal {
@@ -1883,7 +1885,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
@@ -1903,7 +1904,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -2042,10 +2044,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Option::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2ftype_2eproto[4]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index 10c74c6..7d0cd6d 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -56,7 +56,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class Enum;
 struct EnumDefaultTypeInternal;
@@ -183,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);
@@ -209,10 +208,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Type& default_instance() {
     return *internal_default_instance();
@@ -280,12 +279,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -362,10 +355,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -424,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);
@@ -450,10 +441,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Field& default_instance() {
     return *internal_default_instance();
@@ -521,12 +512,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -663,10 +648,8 @@
   // string name = 4;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -679,10 +662,8 @@
   // string type_url = 6;
   void clear_type_url();
   const std::string& type_url() const;
-  void set_type_url(const std::string& value);
-  void set_type_url(std::string&& value);
-  void set_type_url(const char* value);
-  void set_type_url(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_type_url(ArgT0&& arg0, ArgT... args);
   std::string* mutable_type_url();
   std::string* release_type_url();
   void set_allocated_type_url(std::string* type_url);
@@ -695,10 +676,8 @@
   // string json_name = 10;
   void clear_json_name();
   const std::string& json_name() const;
-  void set_json_name(const std::string& value);
-  void set_json_name(std::string&& value);
-  void set_json_name(const char* value);
-  void set_json_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_json_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_json_name();
   std::string* release_json_name();
   void set_allocated_json_name(std::string* json_name);
@@ -711,10 +690,8 @@
   // string default_value = 11;
   void clear_default_value();
   const std::string& default_value() const;
-  void set_default_value(const std::string& value);
-  void set_default_value(std::string&& value);
-  void set_default_value(const char* value);
-  void set_default_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_default_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_default_value();
   std::string* release_default_value();
   void set_allocated_default_value(std::string* default_value);
@@ -795,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);
@@ -821,10 +798,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Enum& default_instance() {
     return *internal_default_instance();
@@ -892,12 +869,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -949,10 +920,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -1010,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);
@@ -1036,10 +1005,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const EnumValue& default_instance() {
     return *internal_default_instance();
@@ -1107,12 +1076,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1144,10 +1107,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -1185,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);
@@ -1211,10 +1172,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Option& default_instance() {
     return *internal_default_instance();
@@ -1282,12 +1243,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2ftype_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1300,10 +1255,8 @@
   // string name = 1;
   void clear_name();
   const std::string& name() const;
-  void set_name(const std::string& value);
-  void set_name(std::string&& value);
-  void set_name(const char* value);
-  void set_name(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_name(ArgT0&& arg0, ArgT... args);
   std::string* mutable_name();
   std::string* release_name();
   void set_allocated_name(std::string* name);
@@ -1362,8 +1315,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Type.name)
   return _internal_name();
 }
-inline void Type::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Type::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Type.name)
 }
 inline std::string* Type::mutable_name() {
@@ -1377,25 +1333,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Type::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Type.name)
-}
-inline void Type::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Type.name)
-}
-inline void Type::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.name)
-}
 inline std::string* Type::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1736,8 +1673,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Field.name)
   return _internal_name();
 }
-inline void Field::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Field::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.name)
 }
 inline std::string* Field::mutable_name() {
@@ -1751,25 +1691,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Field::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.name)
-}
-inline void Field::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.name)
-}
-inline void Field::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.name)
-}
 inline std::string* Field::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1797,8 +1718,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Field.type_url)
   return _internal_type_url();
 }
-inline void Field::set_type_url(const std::string& value) {
-  _internal_set_type_url(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Field::set_type_url(ArgT0&& arg0, ArgT... args) {
+ 
+ type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.type_url)
 }
 inline std::string* Field::mutable_type_url() {
@@ -1812,25 +1736,6 @@
   
   type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Field::set_type_url(std::string&& value) {
-  
-  type_url_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.type_url)
-}
-inline void Field::set_type_url(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.type_url)
-}
-inline void Field::set_type_url(const char* value,
-    size_t size) {
-  
-  type_url_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.type_url)
-}
 inline std::string* Field::_internal_mutable_type_url() {
   
   return type_url_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1937,8 +1842,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Field.json_name)
   return _internal_json_name();
 }
-inline void Field::set_json_name(const std::string& value) {
-  _internal_set_json_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Field::set_json_name(ArgT0&& arg0, ArgT... args) {
+ 
+ json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.json_name)
 }
 inline std::string* Field::mutable_json_name() {
@@ -1952,25 +1860,6 @@
   
   json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Field::set_json_name(std::string&& value) {
-  
-  json_name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.json_name)
-}
-inline void Field::set_json_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.json_name)
-}
-inline void Field::set_json_name(const char* value,
-    size_t size) {
-  
-  json_name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.json_name)
-}
 inline std::string* Field::_internal_mutable_json_name() {
   
   return json_name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1998,8 +1887,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Field.default_value)
   return _internal_default_value();
 }
-inline void Field::set_default_value(const std::string& value) {
-  _internal_set_default_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Field::set_default_value(ArgT0&& arg0, ArgT... args) {
+ 
+ default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Field.default_value)
 }
 inline std::string* Field::mutable_default_value() {
@@ -2013,25 +1905,6 @@
   
   default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Field::set_default_value(std::string&& value) {
-  
-  default_value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Field.default_value)
-}
-inline void Field::set_default_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Field.default_value)
-}
-inline void Field::set_default_value(const char* value,
-    size_t size) {
-  
-  default_value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Field.default_value)
-}
 inline std::string* Field::_internal_mutable_default_value() {
   
   return default_value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -2063,8 +1936,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Enum.name)
   return _internal_name();
 }
-inline void Enum::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Enum::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Enum.name)
 }
 inline std::string* Enum::mutable_name() {
@@ -2078,25 +1954,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Enum::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Enum.name)
-}
-inline void Enum::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Enum.name)
-}
-inline void Enum::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Enum.name)
-}
 inline std::string* Enum::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -2303,8 +2160,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.name)
   return _internal_name();
 }
-inline void EnumValue::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void EnumValue::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.name)
 }
 inline std::string* EnumValue::mutable_name() {
@@ -2318,25 +2178,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void EnumValue::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.EnumValue.name)
-}
-inline void EnumValue::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValue.name)
-}
-inline void EnumValue::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValue.name)
-}
 inline std::string* EnumValue::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -2427,8 +2268,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.Option.name)
   return _internal_name();
 }
-inline void Option::set_name(const std::string& value) {
-  _internal_set_name(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void Option::set_name(ArgT0&& arg0, ArgT... args) {
+ 
+ name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.Option.name)
 }
 inline std::string* Option::mutable_name() {
@@ -2442,25 +2286,6 @@
   
   name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void Option::set_name(std::string&& value) {
-  
-  name_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Option.name)
-}
-inline void Option::set_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.Option.name)
-}
-inline void Option::set_name(const char* value,
-    size_t size) {
-  
-  name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.Option.name)
-}
 inline std::string* Option::_internal_mutable_name() {
   
   return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index a4d5045..75b65f0 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -1115,3 +1115,33 @@
   ENUM_LABEL_99 = 99;
   ENUM_LABEL_100 = 100;
 };
+
+message TestExtensionRangeSerialize {
+  optional int32 foo_one = 1;
+
+  extensions 2 to 2;
+  extensions 3 to 4;
+
+  optional int32 foo_two = 6;
+  optional int32 foo_three = 7;
+
+  extensions 9 to 10;
+
+  optional int32 foo_four = 13;
+
+  extensions 15 to 15;
+  extensions 17 to 17;
+  extensions 19 to 19;
+
+  extend TestExtensionRangeSerialize {
+    optional int32 bar_one = 2;
+    optional int32 bar_two = 4;
+
+    optional int32 bar_three = 10;
+
+    optional int32 bar_four = 15;
+    optional int32 bar_five = 19;
+  }
+}
+
+
diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
index f501f50..92282a6 100644
--- a/src/google/protobuf/unittest_lite.proto
+++ b/src/google/protobuf/unittest_lite.proto
@@ -494,3 +494,8 @@
     BAR2 = 2;
   }
 }
+
+message RecursiveMessage {
+  optional RecursiveMessage recurse = 1;
+  optional bytes payload = 2;
+}
diff --git a/src/google/protobuf/unittest_proto3_optional.proto b/src/google/protobuf/unittest_proto3_optional.proto
index e760021..09d1718 100644
--- a/src/google/protobuf/unittest_proto3_optional.proto
+++ b/src/google/protobuf/unittest_proto3_optional.proto
@@ -32,6 +32,8 @@
 
 package protobuf_unittest;
 
+import "google/protobuf/descriptor.proto";
+
 option java_multiple_files = true;
 option java_package = "com.google.protobuf.testing.proto";
 
@@ -86,3 +88,13 @@
   NestedMessage nested_message = 1;
   optional NestedMessage optional_nested_message = 2;
 }
+
+message Proto3OptionalExtensions {
+  option (protobuf_unittest.Proto3OptionalExtensions.ext_no_optional) = 8;
+  option (protobuf_unittest.Proto3OptionalExtensions.ext_with_optional) = 16;
+
+  extend google.protobuf.MessageOptions {
+    int32 ext_no_optional = 355886728;
+    optional int32 ext_with_optional = 355886729;
+  }
+}
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
index 54abcd4..46d5dba 100644
--- a/src/google/protobuf/util/field_comparator.cc
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -48,14 +48,14 @@
 FieldComparator::FieldComparator() {}
 FieldComparator::~FieldComparator() {}
 
-DefaultFieldComparator::DefaultFieldComparator()
+SimpleFieldComparator::SimpleFieldComparator()
     : float_comparison_(EXACT),
       treat_nan_as_equal_(false),
       has_default_tolerance_(false) {}
 
-DefaultFieldComparator::~DefaultFieldComparator() {}
+SimpleFieldComparator::~SimpleFieldComparator() {}
 
-FieldComparator::ComparisonResult DefaultFieldComparator::Compare(
+FieldComparator::ComparisonResult SimpleFieldComparator::SimpleCompare(
     const Message& message_1, const Message& message_2,
     const FieldDescriptor* field, int index_1, int index_2,
     const util::FieldContext* field_context) {
@@ -127,23 +127,22 @@
   }
 }
 
-bool DefaultFieldComparator::Compare(MessageDifferencer* differencer,
-                                     const Message& message1,
-                                     const Message& message2,
-                                     const util::FieldContext* field_context) {
+bool SimpleFieldComparator::CompareWithDifferencer(
+    MessageDifferencer* differencer, const Message& message1,
+    const Message& message2, const util::FieldContext* field_context) {
   return differencer->Compare(message1, message2,
                               field_context->parent_fields());
 }
 
-void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction,
-                                                         double margin) {
+void SimpleFieldComparator::SetDefaultFractionAndMargin(double fraction,
+                                                        double margin) {
   default_tolerance_ = Tolerance(fraction, margin);
   has_default_tolerance_ = true;
 }
 
-void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
-                                                  double fraction,
-                                                  double margin) {
+void SimpleFieldComparator::SetFractionAndMargin(const FieldDescriptor* field,
+                                                 double fraction,
+                                                 double margin) {
   GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() ||
         FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type())
       << "Field has to be float or double type. Field name is: "
@@ -151,25 +150,25 @@
   map_tolerance_[field] = Tolerance(fraction, margin);
 }
 
-bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field,
-                                           double value_1, double value_2) {
+bool SimpleFieldComparator::CompareDouble(const FieldDescriptor& field,
+                                          double value_1, double value_2) {
   return CompareDoubleOrFloat(field, value_1, value_2);
 }
 
-bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field,
-                                         const EnumValueDescriptor* value_1,
-                                         const EnumValueDescriptor* value_2) {
+bool SimpleFieldComparator::CompareEnum(const FieldDescriptor& field,
+                                        const EnumValueDescriptor* value_1,
+                                        const EnumValueDescriptor* value_2) {
   return value_1->number() == value_2->number();
 }
 
-bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field,
-                                          float value_1, float value_2) {
+bool SimpleFieldComparator::CompareFloat(const FieldDescriptor& field,
+                                         float value_1, float value_2) {
   return CompareDoubleOrFloat(field, value_1, value_2);
 }
 
 template <typename T>
-bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
-                                                  T value_1, T value_2) {
+bool SimpleFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field,
+                                                 T value_1, T value_2) {
   if (value_1 == value_2) {
     // Covers +inf and -inf (which are not within margin or fraction of
     // themselves), and is a shortcut for finite values.
@@ -201,7 +200,7 @@
   }
 }
 
-FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean(
+FieldComparator::ComparisonResult SimpleFieldComparator::ResultFromBoolean(
     bool boolean_result) const {
   return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT;
 }
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index 9058bbe..dd1a486 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -33,12 +33,12 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 #define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
 
+#include <cstdint>
 #include <map>
 #include <string>
 #include <vector>
 
 #include <google/protobuf/stubs/common.h>
-
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -97,7 +97,7 @@
 // Basic implementation of FieldComparator.  Supports three modes of floating
 // point value comparison: exact, approximate using MathUtil::AlmostEqual
 // method, and arbitrarily precise using MathUtil::WithinFractionOrMargin.
-class PROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator {
+class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
  public:
   enum FloatComparison {
     EXACT,        // Floats and doubles are compared exactly.
@@ -109,14 +109,9 @@
   };
 
   // Creates new comparator with float comparison set to EXACT.
-  DefaultFieldComparator();
+  SimpleFieldComparator();
 
-  ~DefaultFieldComparator() override;
-
-  ComparisonResult Compare(const Message& message_1, const Message& message_2,
-                           const FieldDescriptor* field, int index_1,
-                           int index_2,
-                           const util::FieldContext* field_context) override;
+  ~SimpleFieldComparator() override;
 
   void set_float_comparison(FloatComparison float_comparison) {
     float_comparison_ = float_comparison;
@@ -151,12 +146,27 @@
   void SetDefaultFractionAndMargin(double fraction, double margin);
 
  protected:
+  // Returns the comparison result for the given field in two messages.
+  //
+  // This function is called directly by DefaultFieldComparator::Compare.
+  // Subclasses can call this function to compare fields they do not need to
+  // handle specially.
+  ComparisonResult SimpleCompare(const Message& message_1,
+                                 const Message& message_2,
+                                 const FieldDescriptor* field, int index_1,
+                                 int index_2,
+                                 const util::FieldContext* field_context);
+
   // Compare using the provided message_differencer. For example, a subclass can
   // use this method to compare some field in a certain way using the same
   // message_differencer instance and the field context.
-  bool Compare(MessageDifferencer* differencer, const Message& message1,
-               const Message& message2,
-               const util::FieldContext* field_context);
+  bool CompareWithDifferencer(MessageDifferencer* differencer,
+                              const Message& message1, const Message& message2,
+                              const util::FieldContext* field_context);
+
+  // Returns FieldComparator::SAME if boolean_result is true and
+  // FieldComparator::DIFFERENT otherwise.
+  ComparisonResult ResultFromBoolean(bool boolean_result) const;
 
  private:
   // Defines the tolerance for floating point comparison (fraction and margin).
@@ -193,13 +203,13 @@
   // CompareFloat.
   bool CompareFloat(const FieldDescriptor& field, float value_1, float value_2);
 
-  bool CompareInt32(const FieldDescriptor& /* unused */, int32 value_1,
-                    int32 value_2) {
+  bool CompareInt32(const FieldDescriptor& /* unused */, int32_t value_1,
+                    int32_t value_2) {
     return value_1 == value_2;
   }
 
-  bool CompareInt64(const FieldDescriptor& /* unused */, int64 value_1,
-                    int64 value_2) {
+  bool CompareInt64(const FieldDescriptor& /* unused */, int64_t value_1,
+                    int64_t value_2) {
     return value_1 == value_2;
   }
 
@@ -208,13 +218,13 @@
     return value_1 == value_2;
   }
 
-  bool CompareUInt32(const FieldDescriptor& /* unused */, uint32 value_1,
-                     uint32 value_2) {
+  bool CompareUInt32(const FieldDescriptor& /* unused */, uint32_t value_1,
+                     uint32_t value_2) {
     return value_1 == value_2;
   }
 
-  bool CompareUInt64(const FieldDescriptor& /* unused */, uint64 value_1,
-                     uint64 value_2) {
+  bool CompareUInt64(const FieldDescriptor& /* unused */, uint64_t value_1,
+                     uint64_t value_2) {
     return value_1 == value_2;
   }
 
@@ -224,10 +234,6 @@
   template <typename T>
   bool CompareDoubleOrFloat(const FieldDescriptor& field, T value_1, T value_2);
 
-  // Returns FieldComparator::SAME if boolean_result is true and
-  // FieldComparator::DIFFERENT otherwise.
-  ComparisonResult ResultFromBoolean(bool boolean_result) const;
-
   FloatComparison float_comparison_;
 
   // If true, floats and doubles that are both NaN are considered to be
@@ -249,7 +255,25 @@
   // those particular fields.
   ToleranceMap map_tolerance_;
 
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator);
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleFieldComparator);
+};
+
+// Default field comparison: use the basic implementation of FieldComparator.
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+class PROTOBUF_EXPORT DefaultFieldComparator final
+    : public SimpleFieldComparator
+#else   // PROTOBUF_FUTURE_BREAKING_CHANGES
+class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator
+#endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
+{
+ public:
+  ComparisonResult Compare(const Message& message_1, const Message& message_2,
+                           const FieldDescriptor* field, int index_1,
+                           int index_2,
+                           const util::FieldContext* field_context) override {
+    return SimpleCompare(message_1, message_2, field, index_1, index_2,
+                         field_context);
+  }
 };
 
 }  // namespace util
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index 2380018..c5f713f 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -30,10 +30,13 @@
 
 #include <google/protobuf/util/field_mask_util.h>
 
+#include <cstdint>
+
 #include <google/protobuf/message.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/stubs/map_util.h>
 
+// Must be included last.
 #include <google/protobuf/port_def.inc>
 
 namespace google {
@@ -552,7 +555,7 @@
 
 void FieldMaskTree::AddRequiredFieldPath(Node* node,
                                          const Descriptor* descriptor) {
-  const int32 field_count = descriptor->field_count();
+  const int32_t field_count = descriptor->field_count();
   for (int index = 0; index < field_count; ++index) {
     const FieldDescriptor* field = descriptor->field(index);
     if (field->is_required()) {
@@ -589,7 +592,7 @@
   GOOGLE_DCHECK(!node->children.empty());
   const Reflection* reflection = message->GetReflection();
   const Descriptor* descriptor = message->GetDescriptor();
-  const int32 field_count = descriptor->field_count();
+  const int32_t field_count = descriptor->field_count();
   bool modified = false;
   for (int index = 0; index < field_count; ++index) {
     const FieldDescriptor* field = descriptor->field(index);
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index 3ca9359..84cd120 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -33,6 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
 #define GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
 
+#include <cstdint>
 #include <string>
 
 #include <google/protobuf/field_mask.pb.h>
@@ -58,7 +59,7 @@
   // Populates the FieldMask with the paths corresponding to the fields with the
   // given numbers, after checking that all field numbers are valid.
   template <typename T>
-  static void FromFieldNumbers(const std::vector<int64>& field_numbers,
+  static void FromFieldNumbers(const std::vector<int64_t>& field_numbers,
                                FieldMask* out) {
     for (const auto field_number : field_numbers) {
       const FieldDescriptor* field_desc =
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
index f639b32..df5d087 100644
--- a/src/google/protobuf/util/field_mask_util_test.cc
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/util/field_mask_util.h>
 
 #include <algorithm>
+#include <cstdint>
 #include <vector>
 
 #include <google/protobuf/field_mask.pb.h>
@@ -164,7 +165,7 @@
 
 TEST(FieldMaskUtilTest, FromFieldNumbers) {
   FieldMask mask;
-  std::vector<int64> field_numbers = {
+  std::vector<int64_t> field_numbers = {
       TestAllTypes::kOptionalInt64FieldNumber,
       TestAllTypes::kOptionalBoolFieldNumber,
       TestAllTypes::kRepeatedStringFieldNumber,
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
index adaf030..65f1a34 100644
--- a/src/google/protobuf/util/internal/constants.h
+++ b/src/google/protobuf/util/internal/constants.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 
 // This file contains constants used by //net/proto2/util/converter.
@@ -50,19 +52,19 @@
 const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
 
 // Minimum seconds allowed in a google.protobuf.Timestamp value.
-const int64 kTimestampMinSeconds = -62135596800LL;
+const int64_t kTimestampMinSeconds = -62135596800LL;
 
 // Maximum seconds allowed in a google.protobuf.Timestamp value.
-const int64 kTimestampMaxSeconds = 253402300799LL;
+const int64_t kTimestampMaxSeconds = 253402300799LL;
 
 // Minimum seconds allowed in a google.protobuf.Duration value.
-const int64 kDurationMinSeconds = -315576000000LL;
+const int64_t kDurationMinSeconds = -315576000000LL;
 
 // Maximum seconds allowed in a google.protobuf.Duration value.
-const int64 kDurationMaxSeconds = 315576000000LL;
+const int64_t kDurationMaxSeconds = 315576000000LL;
 
 // Nano seconds in a second.
-const int32 kNanosPerSecond = 1000000000;
+const int32_t kNanosPerSecond = 1000000000;
 
 // Type url representing NULL values in google.protobuf.Struct type.
 const char kStructNullValueTypeUrl[] =
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 4246956..52c335d 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/util/internal/datapiece.h>
 
 #include <cmath>
+#include <cstdint>
 #include <limits>
 
 #include <google/protobuf/struct.pb.h>
@@ -47,25 +48,19 @@
 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
-                               ? ValueAsString(before)
-                               : std::is_same<From, double>::value
-                                     ? DoubleAsString(before)
-                                     : FloatAsString(before));
+    return util::InvalidArgumentError(
+        std::is_integral<From>::value       ? ValueAsString(before)
+        : std::is_same<From, double>::value ? DoubleAsString(before)
+                                            : FloatAsString(before));
   }
 }
 
@@ -106,7 +101,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);
   }
@@ -114,54 +109,56 @@
 
 }  // namespace
 
-util::StatusOr<int32> DataPiece::ToInt32() const {
-  if (type_ == TYPE_STRING) return StringToNumber<int32>(safe_strto32);
-
-  if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<int32, double>(double_);
-
-  if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<int32, float>(float_);
-
-  return GenericConvert<int32>();
-}
-
-util::StatusOr<uint32> DataPiece::ToUint32() const {
+util::StatusOr<int32_t> DataPiece::ToInt32() const {
   if (type_ == TYPE_STRING)
-    return StringToNumber<uint32>(safe_strtou32);
+    return StringToNumber<int32_t>(safe_strto32);
 
   if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<uint32, double>(double_);
+    return FloatingPointToIntConvertAndCheck<int32_t, double>(double_);
 
   if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<uint32, float>(float_);
+    return FloatingPointToIntConvertAndCheck<int32_t, float>(float_);
 
-  return GenericConvert<uint32>();
+  return GenericConvert<int32_t>();
 }
 
-util::StatusOr<int64> DataPiece::ToInt64() const {
-  if (type_ == TYPE_STRING) return StringToNumber<int64>(safe_strto64);
-
-  if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<int64, double>(double_);
-
-  if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<int64, float>(float_);
-
-  return GenericConvert<int64>();
-}
-
-util::StatusOr<uint64> DataPiece::ToUint64() const {
+util::StatusOr<uint32_t> DataPiece::ToUint32() const {
   if (type_ == TYPE_STRING)
-    return StringToNumber<uint64>(safe_strtou64);
+    return StringToNumber<uint32_t>(safe_strtou32);
 
   if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<uint64, double>(double_);
+    return FloatingPointToIntConvertAndCheck<uint32_t, double>(double_);
 
   if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<uint64, float>(float_);
+    return FloatingPointToIntConvertAndCheck<uint32_t, float>(float_);
 
-  return GenericConvert<uint64>();
+  return GenericConvert<uint32_t>();
+}
+
+util::StatusOr<int64_t> DataPiece::ToInt64() const {
+  if (type_ == TYPE_STRING)
+    return StringToNumber<int64_t>(safe_strto64);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<int64_t, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<int64_t, float>(float_);
+
+  return GenericConvert<int64_t>();
+}
+
+util::StatusOr<uint64_t> DataPiece::ToUint64() const {
+  if (type_ == TYPE_STRING)
+    return StringToNumber<uint64_t>(safe_strtou64);
+
+  if (type_ == TYPE_DOUBLE)
+    return FloatingPointToIntConvertAndCheck<uint64_t, double>(double_);
+
+  if (type_ == TYPE_FLOAT)
+    return FloatingPointToIntConvertAndCheck<uint64_t, float>(float_);
+
+  return GenericConvert<uint64_t>();
 }
 
 util::StatusOr<double> DataPiece::ToDouble() const {
@@ -176,7 +173,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;
     }
@@ -206,7 +203,7 @@
     case TYPE_STRING:
       return StringToNumber<bool>(safe_strtob);
     default:
-      return InvalidArgument(
+      return util::InvalidArgumentError(
           ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
   }
 }
@@ -221,7 +218,7 @@
       return base64;
     }
     default:
-      return InvalidArgument(
+      return util::InvalidArgumentError(
           ValueAsStringOrDefault("Cannot convert to string."));
   }
 }
@@ -262,11 +259,12 @@
   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."));
   }
 }
@@ -286,7 +284,7 @@
     if (value != nullptr) return value->number();
 
     // Check if int version of enum is sent as string.
-    util::StatusOr<int32> int_value = ToInt32();
+    util::StatusOr<int32_t> int_value = ToInt32();
     if (int_value.ok()) {
       if (const google::protobuf::EnumValue* enum_value =
               FindEnumValueByNumberOrNull(enum_type, int_value.value())) {
@@ -326,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."));
 }
 
@@ -334,19 +332,19 @@
 util::StatusOr<To> DataPiece::GenericConvert() const {
   switch (type_) {
     case TYPE_INT32:
-      return NumberConvertAndCheck<To, int32>(i32_);
+      return NumberConvertAndCheck<To, int32_t>(i32_);
     case TYPE_INT64:
-      return NumberConvertAndCheck<To, int64>(i64_);
+      return NumberConvertAndCheck<To, int64_t>(i64_);
     case TYPE_UINT32:
-      return NumberConvertAndCheck<To, uint32>(u32_);
+      return NumberConvertAndCheck<To, uint32_t>(u32_);
     case TYPE_UINT64:
-      return NumberConvertAndCheck<To, uint64>(u64_);
+      return NumberConvertAndCheck<To, uint64_t>(u64_);
     case TYPE_DOUBLE:
       return NumberConvertAndCheck<To, double>(double_);
     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."));
   }
@@ -356,11 +354,12 @@
 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 03ea128..c27ea5c 100644
--- a/src/google/protobuf/util/internal/datapiece.h
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
 
+#include <cstdint>
 #include <string>
 
 #include <google/protobuf/stubs/common.h>
@@ -75,13 +76,13 @@
   };
 
   // Constructors and Destructor
-  explicit DataPiece(const int32 value)
+  explicit DataPiece(const int32_t value)
       : type_(TYPE_INT32), i32_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const int64 value)
+  explicit DataPiece(const int64_t value)
       : type_(TYPE_INT64), i64_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const uint32 value)
+  explicit DataPiece(const uint32_t value)
       : type_(TYPE_UINT32), u32_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const uint64 value)
+  explicit DataPiece(const uint64_t value)
       : type_(TYPE_UINT64), u64_(value), use_strict_base64_decoding_(false) {}
   explicit DataPiece(const double value)
       : type_(TYPE_DOUBLE),
@@ -93,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); }
@@ -125,16 +126,16 @@
 
 
   // Parses, casts or converts the value stored in the DataPiece into an int32.
-  util::StatusOr<int32> ToInt32() const;
+  util::StatusOr<int32_t> ToInt32() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a uint32.
-  util::StatusOr<uint32> ToUint32() const;
+  util::StatusOr<uint32_t> ToUint32() const;
 
   // Parses, casts or converts the value stored in the DataPiece into an int64.
-  util::StatusOr<int64> ToInt64() const;
+  util::StatusOr<int64_t> ToInt64() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a uint64.
-  util::StatusOr<uint64> ToUint64() const;
+  util::StatusOr<uint64_t> ToUint64() const;
 
   // Parses, casts or converts the value stored in the DataPiece into a double.
   util::StatusOr<double> ToDouble() const;
@@ -161,7 +162,7 @@
   DataPiece();
 
   // Helper to create NULL or ENUM types.
-  DataPiece(Type type, int32 val)
+  DataPiece(Type type, int32_t val)
       : type_(type), i32_(val), use_strict_base64_decoding_(false) {}
 
   // Same as the ToEnum() method above but with additional flag to ignore
@@ -191,18 +192,16 @@
   // Data type for this piece of data.
   Type type_;
 
-  typedef ::google::protobuf::internal::StringPiecePod StringPiecePod;
-
   // Stored piece of data.
   union {
-    int32 i32_;
-    int64 i64_;
-    uint32 u32_;
-    uint64 u64_;
+    int32_t i32_;
+    int64_t i64_;
+    uint32_t u32_;
+    uint64_t u64_;
     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/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
index c9ab446..d6bb788 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/default_value_objectwriter.h>
 
+#include <cstdint>
 #include <unordered_map>
 
 #include <google/protobuf/util/internal/constants.h>
@@ -85,7 +86,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
-    StringPiece name, int32 value) {
+    StringPiece name, int32_t value) {
   if (current_ == nullptr) {
     ow_->RenderInt32(name, value);
   } else {
@@ -95,7 +96,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
-    StringPiece name, uint32 value) {
+    StringPiece name, uint32_t value) {
   if (current_ == nullptr) {
     ow_->RenderUint32(name, value);
   } else {
@@ -105,7 +106,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
-    StringPiece name, int64 value) {
+    StringPiece name, int64_t value) {
   if (current_ == nullptr) {
     ow_->RenderInt64(name, value);
   } else {
@@ -115,7 +116,7 @@
 }
 
 DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
-    StringPiece name, uint64 value) {
+    StringPiece name, uint64_t value) {
   if (current_ == nullptr) {
     ow_->RenderUint64(name, value);
   } else {
@@ -445,19 +446,20 @@
     case google::protobuf::Field::TYPE_INT64:
     case google::protobuf::Field::TYPE_SINT64:
     case google::protobuf::Field::TYPE_SFIXED64: {
-      return DataPiece(ConvertTo<int64>(
-          field.default_value(), &DataPiece::ToInt64, static_cast<int64>(0)));
+      return DataPiece(ConvertTo<int64_t>(
+          field.default_value(), &DataPiece::ToInt64, static_cast<int64_t>(0)));
     }
     case google::protobuf::Field::TYPE_UINT64:
     case google::protobuf::Field::TYPE_FIXED64: {
-      return DataPiece(ConvertTo<uint64>(
-          field.default_value(), &DataPiece::ToUint64, static_cast<uint64>(0)));
+      return DataPiece(ConvertTo<uint64_t>(field.default_value(),
+                                           &DataPiece::ToUint64,
+                                           static_cast<uint64_t>(0)));
     }
     case google::protobuf::Field::TYPE_INT32:
     case google::protobuf::Field::TYPE_SINT32:
     case google::protobuf::Field::TYPE_SFIXED32: {
-      return DataPiece(ConvertTo<int32>(
-          field.default_value(), &DataPiece::ToInt32, static_cast<int32>(0)));
+      return DataPiece(ConvertTo<int32_t>(
+          field.default_value(), &DataPiece::ToInt32, static_cast<int32_t>(0)));
     }
     case google::protobuf::Field::TYPE_BOOL: {
       return DataPiece(
@@ -471,8 +473,9 @@
     }
     case google::protobuf::Field::TYPE_UINT32:
     case google::protobuf::Field::TYPE_FIXED32: {
-      return DataPiece(ConvertTo<uint32>(
-          field.default_value(), &DataPiece::ToUint32, static_cast<uint32>(0)));
+      return DataPiece(ConvertTo<uint32_t>(field.default_value(),
+                                           &DataPiece::ToUint32,
+                                           static_cast<uint32_t>(0)));
     }
     case google::protobuf::Field::TYPE_ENUM: {
       return FindEnumDefault(field, typeinfo, use_ints_for_enums);
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
index 08793fc..8236f0a 100644
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__
 
+#include <cstdint>
 #include <functional>
 #include <memory>
 #include <stack>
@@ -95,16 +96,16 @@
                                        bool value) override;
 
   DefaultValueObjectWriter* RenderInt32(StringPiece name,
-                                        int32 value) override;
+                                        int32_t value) override;
 
   DefaultValueObjectWriter* RenderUint32(StringPiece name,
-                                         uint32 value) override;
+                                         uint32_t value) override;
 
   DefaultValueObjectWriter* RenderInt64(StringPiece name,
-                                        int64 value) override;
+                                        int64_t value) override;
 
   DefaultValueObjectWriter* RenderUint64(StringPiece name,
-                                         uint64 value) override;
+                                         uint64_t value) override;
 
   DefaultValueObjectWriter* RenderDouble(StringPiece name,
                                          double value) override;
diff --git a/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h
index 2cb7f69..09b2e78 100644
--- a/src/google/protobuf/util/internal/expecting_objectwriter.h
+++ b/src/google/protobuf/util/internal/expecting_objectwriter.h
@@ -50,6 +50,8 @@
 //         ->RenderString("key", "value")
 //       ->EndObject();
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/util/internal/object_writer.h>
 #include <gmock/gmock.h>
@@ -77,13 +79,13 @@
   MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override));
   MOCK_METHOD(ObjectWriter*, EndList, (), (override));
   MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32),
+  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32),
+  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64),
+  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64_t),
               (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64),
+  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64_t),
               (override));
   MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double),
               (override));
@@ -139,41 +141,41 @@
     return this;
   }
 
-  virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) {
+  virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) {
     (name.empty()
-         ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32>(value)))
+         ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq<int32_t>(value)))
          : EXPECT_CALL(*mock_, RenderInt32(Eq(std::string(name)),
-                                           TypedEq<int32>(value))))
+                                           TypedEq<int32_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) {
-    (name.empty()
-         ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq<uint32>(value)))
-         : EXPECT_CALL(*mock_, RenderUint32(Eq(std::string(name)),
-                                            TypedEq<uint32>(value))))
+  virtual ObjectWriter* RenderUint32(StringPiece name, uint32_t value) {
+    (name.empty() ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(),
+                                                     TypedEq<uint32_t>(value)))
+                  : EXPECT_CALL(*mock_, RenderUint32(Eq(std::string(name)),
+                                                     TypedEq<uint32_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) {
+  virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) {
     (name.empty()
-         ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64>(value)))
+         ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq<int64_t>(value)))
          : EXPECT_CALL(*mock_, RenderInt64(Eq(std::string(name)),
-                                           TypedEq<int64>(value))))
+                                           TypedEq<int64_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
   }
 
-  virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) {
-    (name.empty()
-         ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq<uint64>(value)))
-         : EXPECT_CALL(*mock_, RenderUint64(Eq(std::string(name)),
-                                            TypedEq<uint64>(value))))
+  virtual ObjectWriter* RenderUint64(StringPiece name, uint64_t value) {
+    (name.empty() ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(),
+                                                     TypedEq<uint64_t>(value)))
+                  : EXPECT_CALL(*mock_, RenderUint64(Eq(std::string(name)),
+                                                     TypedEq<uint64_t>(value))))
         .WillOnce(Return(mock_))
         .RetiresOnSaturation();
     return this;
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index 0beff99..f211a54 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -134,11 +134,9 @@
         }
         // Un-escaped '"' must be followed with a ']'.
         if (i >= length - 1 || paths[i + 1] != ']') {
-          return util::Status(
-              util::error::INVALID_ARGUMENT,
-              StrCat(
-                  "Invalid FieldMask '", paths,
-                  "'. Map keys should be represented as [\"some_key\"]."));
+          return util::InvalidArgumentError(StrCat(
+              "Invalid FieldMask '", paths,
+              "'. Map keys should be represented as [\"some_key\"]."));
         }
         // The end of the map key ("\"]") has been found.
         in_map_key = false;
@@ -147,11 +145,9 @@
         // 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,
-              StrCat(
-                  "Invalid FieldMask '", paths,
-                  "'. Map keys should be at the end of a path segment."));
+          return util::InvalidArgumentError(StrCat(
+              "Invalid FieldMask '", paths,
+              "'. Map keys should be at the end of a path segment."));
         }
         is_escaping = false;
         continue;
@@ -160,11 +156,9 @@
       // 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,
-              StrCat(
-                  "Invalid FieldMask '", paths,
-                  "'. Map keys should be represented as [\"some_key\"]."));
+          return util::InvalidArgumentError(StrCat(
+              "Invalid FieldMask '", paths,
+              "'. Map keys should be represented as [\"some_key\"]."));
         }
         // "[\"" starts a map key.
         in_map_key = true;
@@ -197,8 +191,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 +200,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_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
index c5c406f..e4fa8cf 100644
--- a/src/google/protobuf/util/internal/json_escaping.cc
+++ b/src/google/protobuf/util/internal/json_escaping.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/internal/json_escaping.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 
@@ -77,7 +79,7 @@
 
 // Determines if the given char value is a unicode surrogate code unit (either
 // high-surrogate or low-surrogate).
-inline bool IsSurrogate(uint32 c) {
+inline bool IsSurrogate(uint32_t c) {
   // Optimized form of:
   // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate;
   // (Reduced from 3 ALU instructions to 2 ALU instructions)
@@ -86,13 +88,13 @@
 
 // Returns true if the given unicode code point cp is a valid
 // unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint).
-inline bool IsValidCodePoint(uint32 cp) {
+inline bool IsValidCodePoint(uint32_t cp) {
   return cp <= JsonEscaping::kMaxCodePoint;
 }
 
 // Returns the low surrogate for the given unicode code point. The result is
 // meaningless if the given code point is not a supplementary character.
-inline uint16 ToLowSurrogate(uint32 cp) {
+inline uint16_t ToLowSurrogate(uint32_t cp) {
   return (cp &
           (JsonEscaping::kMaxLowSurrogate - JsonEscaping::kMinLowSurrogate)) +
          JsonEscaping::kMinLowSurrogate;
@@ -100,7 +102,7 @@
 
 // Returns the high surrogate for the given unicode code point. The result is
 // meaningless if the given code point is not a supplementary character.
-inline uint16 ToHighSurrogate(uint32 cp) {
+inline uint16_t ToHighSurrogate(uint32_t cp) {
   return (cp >> 10) + (JsonEscaping::kMinHighSurrogate -
                        (JsonEscaping::kMinSupplementaryCodePoint >> 10));
 }
@@ -125,11 +127,11 @@
 // Returns false if we encounter an invalid UTF-8 string. Returns true
 // otherwise, including the case when we reach the end of the input (str)
 // before a complete unicode code point is read.
-bool ReadCodePoint(StringPiece str, int index, uint32* cp, int* num_left,
-                   int* num_read) {
+bool ReadCodePoint(StringPiece str, int index, uint32_t* cp,
+                   int* num_left, int* num_read) {
   if (*num_left == 0) {
     // Last read was complete. Start reading a new unicode code point.
-    *cp = static_cast<uint8>(str[index++]);
+    *cp = static_cast<uint8_t>(str[index++]);
     *num_read = 1;
     // The length of the code point is determined from reading the first byte.
     //
@@ -178,7 +180,7 @@
     *num_read = 0;
   }
   while (*num_left > 0 && index < str.size()) {
-    uint32 ch = static_cast<uint8>(str[index++]);
+    uint32_t ch = static_cast<uint8_t>(str[index++]);
     --(*num_left);
     ++(*num_read);
     *cp = (*cp << 6) | (ch & 0x3f);
@@ -190,7 +192,7 @@
 // Stores the 16-bit unicode code point as its hexadecimal digits in buffer
 // and returns a StringPiece that points to this buffer. The input buffer needs
 // to be at least 6 bytes long.
-StringPiece ToHex(uint16 cp, char* buffer) {
+StringPiece ToHex(uint16_t cp, char* buffer) {
   buffer[5] = kHex[cp & 0x0f];
   cp >>= 4;
   buffer[4] = kHex[cp & 0x0f];
@@ -204,9 +206,9 @@
 // Stores the 32-bit unicode code point as its hexadecimal digits in buffer
 // and returns a StringPiece that points to this buffer. The input buffer needs
 // to be at least 12 bytes long.
-StringPiece ToSurrogateHex(uint32 cp, char* buffer) {
-  uint16 low = ToLowSurrogate(cp);
-  uint16 high = ToHighSurrogate(cp);
+StringPiece ToSurrogateHex(uint32_t cp, char* buffer) {
+  uint16_t low = ToLowSurrogate(cp);
+  uint16_t high = ToHighSurrogate(cp);
 
   buffer[11] = kHex[low & 0x0f];
   low >>= 4;
@@ -234,7 +236,7 @@
 //
 // If the given unicode code point does not need escaping, an empty
 // StringPiece is returned.
-StringPiece EscapeCodePoint(uint32 cp, char* buffer) {
+StringPiece EscapeCodePoint(uint32_t cp, char* buffer) {
   if (cp < 0xa0) return kCommonEscapes[cp];
   switch (cp) {
     // These are not required by json spec
@@ -272,7 +274,8 @@
 // Tries to escape the given code point first. If the given code point
 // does not need to be escaped, but force_output is true, then render
 // the given multi-byte code point in UTF8 in the buffer and returns it.
-StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) {
+StringPiece EscapeCodePoint(uint32_t cp, char* buffer,
+                                  bool force_output) {
   StringPiece sp = EscapeCodePoint(cp, buffer);
   if (force_output && sp.empty()) {
     buffer[5] = (cp & 0x3f) | 0x80;
@@ -301,7 +304,7 @@
 void JsonEscaping::Escape(strings::ByteSource* input,
                           strings::ByteSink* output) {
   char buffer[12] = "\\udead\\ubee";
-  uint32 cp = 0;     // Current unicode code point.
+  uint32_t cp = 0;   // Current unicode code point.
   int num_left = 0;  // Num of chars to read to complete the code point.
   while (input->Available() > 0) {
     StringPiece str = input->Peek();
diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h
index d05c335..38cb645 100644
--- a/src/google/protobuf/util/internal/json_escaping.h
+++ b/src/google/protobuf/util/internal/json_escaping.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__
 #define GOOGLE_PROTOBUF_UTIL_INTERNAL__JSON_ESCAPING_H__
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/bytestream.h>
 
@@ -44,34 +46,34 @@
   // The minimum value of a unicode high-surrogate code unit in the utf-16
   // encoding. A high-surrogate is also known as a leading-surrogate.
   // See http://www.unicode.org/glossary/#high_surrogate_code_unit
-  static constexpr uint16 kMinHighSurrogate = 0xd800;
+  static constexpr uint16_t kMinHighSurrogate = 0xd800;
 
   // The maximum value of a unicide high-surrogate code unit in the utf-16
   // encoding. A high-surrogate is also known as a leading-surrogate.
   // See http://www.unicode.org/glossary/#high_surrogate_code_unit
-  static constexpr uint16 kMaxHighSurrogate = 0xdbff;
+  static constexpr uint16_t kMaxHighSurrogate = 0xdbff;
 
   // The minimum value of a unicode low-surrogate code unit in the utf-16
   // encoding. A low-surrogate is also known as a trailing-surrogate.
   // See http://www.unicode.org/glossary/#low_surrogate_code_unit
-  static constexpr uint16 kMinLowSurrogate = 0xdc00;
+  static constexpr uint16_t kMinLowSurrogate = 0xdc00;
 
   // The maximum value of a unicode low-surrogate code unit in the utf-16
   // encoding. A low-surrogate is also known as a trailing surrogate.
   // See http://www.unicode.org/glossary/#low_surrogate_code_unit
-  static constexpr uint16 kMaxLowSurrogate = 0xdfff;
+  static constexpr uint16_t kMaxLowSurrogate = 0xdfff;
 
   // The minimum value of a unicode supplementary code point.
   // See http://www.unicode.org/glossary/#supplementary_code_point
-  static constexpr uint32 kMinSupplementaryCodePoint = 0x010000;
+  static constexpr uint32_t kMinSupplementaryCodePoint = 0x010000;
 
   // The minimum value of a unicode code point.
   // See http://www.unicode.org/glossary/#code_point
-  static constexpr uint32 kMinCodePoint = 0x000000;
+  static constexpr uint32_t kMinCodePoint = 0x000000;
 
   // The maximum value of a unicode code point.
   // See http://www.unicode.org/glossary/#code_point
-  static constexpr uint32 kMaxCodePoint = 0x10ffff;
+  static constexpr uint32_t kMaxCodePoint = 0x10ffff;
 
   JsonEscaping() {}
   virtual ~JsonEscaping() {}
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
index 32ce2dc..c03eb1d 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -31,6 +31,7 @@
 #include <google/protobuf/util/internal/json_objectwriter.h>
 
 #include <cmath>
+#include <cstdint>
 #include <limits>
 
 #include <google/protobuf/stubs/casts.h>
@@ -86,17 +87,17 @@
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
-                                                int32 value) {
+                                                int32_t value) {
   return RenderSimple(name, StrCat(value));
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
-                                                 uint32 value) {
+                                                 uint32_t value) {
   return RenderSimple(name, StrCat(value));
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
-                                                int64 value) {
+                                                int64_t value) {
   WritePrefix(name);
   WriteChar('"');
   WriteRawString(StrCat(value));
@@ -105,7 +106,7 @@
 }
 
 JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
-                                                 uint64 value) {
+                                                 uint64_t value) {
   WritePrefix(name);
   WriteChar('"');
   WriteRawString(StrCat(value));
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
index ab372ab..2e9c684 100644
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__
 
+#include <cstdint>
 #include <memory>
 #include <string>
 
@@ -118,10 +119,12 @@
   JsonObjectWriter* StartList(StringPiece name) override;
   JsonObjectWriter* EndList() override;
   JsonObjectWriter* RenderBool(StringPiece name, bool value) override;
-  JsonObjectWriter* RenderInt32(StringPiece name, int32 value) override;
-  JsonObjectWriter* RenderUint32(StringPiece name, uint32 value) override;
-  JsonObjectWriter* RenderInt64(StringPiece name, int64 value) override;
-  JsonObjectWriter* RenderUint64(StringPiece name, uint64 value) override;
+  JsonObjectWriter* RenderInt32(StringPiece name, int32_t value) override;
+  JsonObjectWriter* RenderUint32(StringPiece name,
+                                 uint32_t value) override;
+  JsonObjectWriter* RenderInt64(StringPiece name, int64_t value) override;
+  JsonObjectWriter* RenderUint64(StringPiece name,
+                                 uint64_t value) override;
   JsonObjectWriter* RenderDouble(StringPiece name, double value) override;
   JsonObjectWriter* RenderFloat(StringPiece name, float value) override;
   JsonObjectWriter* RenderString(StringPiece name,
@@ -218,7 +221,7 @@
       // Take the slow-path if we don't have sufficient characters remaining in
       // our buffer or we have a non-trivial indent string which would prevent
       // us from using memset.
-      uint8* out = nullptr;
+      uint8_t* out = nullptr;
       if (indent_count_ > 0) {
         out = stream_->GetDirectBufferForNBytesAndAdvance(len);
       }
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
index e9f252b..03395da 100644
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/internal/json_objectwriter.h>
 
+#include <cstdint>
+
 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <google/protobuf/util/internal/utility.h>
 #include <gtest/gtest.h>
@@ -147,8 +149,8 @@
       ->RenderBool("bool", true)
       ->RenderDouble("double", std::numeric_limits<double>::max())
       ->RenderFloat("float", std::numeric_limits<float>::max())
-      ->RenderInt32("int", std::numeric_limits<int32>::min())
-      ->RenderInt64("long", std::numeric_limits<int64>::min())
+      ->RenderInt32("int", std::numeric_limits<int32_t>::min())
+      ->RenderInt64("long", std::numeric_limits<int64_t>::min())
       ->RenderBytes("bytes", "abracadabra")
       ->RenderString("string", "string")
       ->RenderBytes("emptybytes", "")
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index db18b1a..c3030b5 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -32,16 +32,15 @@
 
 #include <algorithm>
 #include <cctype>
-#include <cerrno>
 #include <cmath>
-#include <cstdlib>
-#include <cstring>
-#include <limits>
 #include <memory>
+#include <stack>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/util/internal/object_writer.h>
 #include <google/protobuf/util/internal/json_escaping.h>
 
@@ -50,14 +49,6 @@
 namespace protobuf {
 namespace util {
 
-// Allow these symbols to be referenced as util::Status, util::error::* in
-// this file.
-namespace error {
-using util::error::CANCELLED;
-using util::error::INTERNAL;
-using util::error::INVALID_ARGUMENT;
-}  // namespace error
-
 namespace converter {
 
 // Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
@@ -146,6 +137,8 @@
       key_(),
       key_storage_(),
       finishing_(false),
+      seen_non_whitespace_(false),
+      allow_no_root_element_(false),
       parsed_(),
       parsed_storage_(),
       string_open_(0),
@@ -214,7 +207,8 @@
   } else {
     p_ = json_ = leftover_;
     if (!is_valid_utf8) {
-      return ReportFailure("Encountered non UTF-8 code points.");
+      return ReportFailure("Encountered non UTF-8 code points.",
+                           ParseErrorType::NON_UTF_8);
     }
   }
 
@@ -225,7 +219,9 @@
   if (result.ok()) {
     SkipWhitespace();
     if (!p_.empty()) {
-      result = ReportFailure("Parsing terminated before end of input.");
+      result =
+          ReportFailure("Parsing terminated before end of input.",
+                        ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
     }
   }
   return result;
@@ -249,7 +245,9 @@
     // If we do not expect anything i.e. stack is empty, and we have non-empty
     // string left to parse, we report an error.
     if (stack_.empty()) {
-      return ReportFailure("Parsing terminated before end of input.");
+      return ReportFailure(
+          "Parsing terminated before end of input.",
+          ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
     }
     // If we expect future data i.e. stack is non-empty, and we have some
     // unparsed data left, we save it for later parse.
@@ -258,6 +256,17 @@
   return util::Status();
 }
 
+bool JsonStreamParser::IsInputAllWhiteSpaces(TokenType type) {
+  // Conclude the whole input is full of white spaces by:
+  // - it is at the finishing stage
+  // - we have run out of the input data
+  // - haven't seen non-whitespace char so far
+  if (finishing_ && p_.empty() && type == UNKNOWN && !seen_non_whitespace_) {
+    return true;
+  }
+  return false;
+}
+
 util::Status JsonStreamParser::RunParser() {
   while (!stack_.empty()) {
     ParseType type = stack_.top();
@@ -266,6 +275,9 @@
     util::Status result;
     switch (type) {
       case VALUE:
+        if (allow_no_root_element_ && IsInputAllWhiteSpaces(t)) {
+          return util::Status();
+        }
         result = ParseValue(t);
         break;
 
@@ -290,14 +302,13 @@
         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.
@@ -330,7 +341,7 @@
     case BEGIN_NULL:
       return ParseNull();
     case UNKNOWN:
-      return ReportUnknown("Expected a value.");
+      return ReportUnknown("Expected a value.", ParseErrorType::EXPECTED_VALUE);
     default: {
       if (allow_empty_null_ && IsEmptyNullAllowed(type)) {
         return ParseEmptyNull();
@@ -341,9 +352,10 @@
       // 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.");
+      return ReportFailure("Unexpected token.",
+                           ParseErrorType::UNEXPECTED_TOKEN);
     }
   }
 }
@@ -379,9 +391,10 @@
       // 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.");
+        return ReportFailure("Closing quote expected in string.",
+                             ParseErrorType::EXPECTED_CLOSING_QUOTE);
       }
       // Parse a unicode escape if we found \u in the string.
       if (data[1] == 'u') {
@@ -447,11 +460,12 @@
   }
   // 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;
-  return ReportFailure("Closing quote expected in string.");
+  return ReportFailure("Closing quote expected in string.",
+                       ParseErrorType::EXPECTED_CLOSING_QUOTE);
 }
 
 // Converts a unicode escaped character to a decimal value stored in a char32
@@ -464,16 +478,18 @@
 util::Status JsonStreamParser::ParseUnicodeEscape() {
   if (p_.length() < kUnicodeEscapedLength) {
     if (!finishing_) {
-      return util::Status(util::error::CANCELLED, "");
+      return util::CancelledError("");
     }
-    return ReportFailure("Illegal hex string.");
+    return ReportFailure("Illegal hex string.",
+                         ParseErrorType::ILLEGAL_HEX_STRING);
   }
   GOOGLE_DCHECK_EQ('\\', p_.data()[0]);
   GOOGLE_DCHECK_EQ('u', p_.data()[1]);
   uint32 code = 0;
   for (int i = 2; i < kUnicodeEscapedLength; ++i) {
     if (!isxdigit(p_.data()[i])) {
-      return ReportFailure("Invalid escape sequence.");
+      return ReportFailure("Invalid escape sequence.",
+                           ParseErrorType::INVALID_ESCAPE_SEQUENCE);
     }
     code = (code << 4) + hex_digit_to_int(p_.data()[i]);
   }
@@ -481,10 +497,11 @@
       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.");
+        return ReportFailure("Missing low surrogate.",
+                             ParseErrorType::MISSING_LOW_SURROGATE);
       }
     } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
                p_.data()[kUnicodeEscapedLength + 1] == 'u') {
@@ -492,7 +509,8 @@
       for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
            ++i) {
         if (!isxdigit(p_.data()[i])) {
-          return ReportFailure("Invalid escape sequence.");
+          return ReportFailure("Invalid escape sequence.",
+                               ParseErrorType::INVALID_ESCAPE_SEQUENCE);
         }
         low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
       }
@@ -504,14 +522,17 @@
         // Advance past the first code unit escape.
         p_.remove_prefix(kUnicodeEscapedLength);
       } else if (!coerce_to_utf8_) {
-        return ReportFailure("Invalid low surrogate.");
+        return ReportFailure("Invalid low surrogate.",
+                             ParseErrorType::INVALID_LOW_SURROGATE);
       }
     } else if (!coerce_to_utf8_) {
-      return ReportFailure("Missing low surrogate.");
+      return ReportFailure("Missing low surrogate.",
+                           ParseErrorType::MISSING_LOW_SURROGATE);
     }
   }
   if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
-    return ReportFailure("Invalid unicode code point.");
+    return ReportFailure("Invalid unicode code point.",
+                         ParseErrorType::INVALID_UNICODE);
   }
   char buf[UTFmax];
   int len = EncodeAsUTF8Char(code, buf);
@@ -542,7 +563,8 @@
         break;
 
       default:
-        return ReportFailure("Unable to parse number.");
+        return ReportFailure("Unable to parse number.",
+                             ParseErrorType::UNABLE_TO_PARSE_NUMBER);
     }
   }
   return result;
@@ -551,10 +573,12 @@
 util::Status JsonStreamParser::ParseDoubleHelper(const std::string& number,
                                                  NumberResult* result) {
   if (!safe_strtod(number, &result->double_val)) {
-    return ReportFailure("Unable to parse number.");
+    return ReportFailure("Unable to parse number.",
+                         ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
   if (!loose_float_number_conversion_ && !std::isfinite(result->double_val)) {
-    return ReportFailure("Number exceeds the range of double.");
+    return ReportFailure("Number exceeds the range of double.",
+                         ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
   result->type = NumberResult::DOUBLE;
   return util::Status();
@@ -587,7 +611,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
@@ -606,7 +630,9 @@
   if (!negative) {
     // Octal/Hex numbers are not valid JSON values.
     if (number.length() >= 2 && number[0] == '0') {
-      return ReportFailure("Octal/hex numbers are not valid JSON values.");
+      return ReportFailure(
+          "Octal/hex numbers are not valid JSON values.",
+          ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
     }
     if (safe_strtou64(number, &result->uint_val)) {
       result->type = NumberResult::UINT;
@@ -624,7 +650,9 @@
 
   // Octal/Hex numbers are not valid JSON values.
   if (number.length() >= 3 && number[1] == '0') {
-    return ReportFailure("Octal/hex numbers are not valid JSON values.");
+    return ReportFailure(
+        "Octal/hex numbers are not valid JSON values.",
+        ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   // Negative non-floating point number, parse as an int64.
   if (safe_strto64(number, &result->int_val)) {
@@ -656,7 +684,8 @@
 
 util::Status JsonStreamParser::ParseObjectMid(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected , or } after key:value pair.");
+    return ReportUnknown("Expected , or } after key:value pair.",
+                         ParseErrorType::EXPECTED_COMMA_OR_BRACES);
   }
 
   // Object is complete, advance past the comma and render the EndObject.
@@ -673,12 +702,14 @@
     return util::Status();
   }
   // Illegal token after key:value pair.
-  return ReportFailure("Expected , or } after key:value pair.");
+  return ReportFailure("Expected , or } after key:value pair.",
+                       ParseErrorType::EXPECTED_COMMA_OR_BRACES);
 }
 
 util::Status JsonStreamParser::ParseEntry(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected an object key or }.");
+    return ReportUnknown("Expected an object key or }.",
+                         ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 
   // Close the object and return. This allows for trailing commas.
@@ -711,11 +742,13 @@
     result = ParseKey();
     if (result.ok() && (key_ == kKeywordNull || key_ == kKeywordTrue ||
                         key_ == kKeywordFalse)) {
-      result = ReportFailure("Expected an object key or }.");
+      result = ReportFailure("Expected an object key or }.",
+                             ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
     }
   } else {
     // Unknown key type, report an error.
-    result = ReportFailure("Expected an object key or }.");
+    result = ReportFailure("Expected an object key or }.",
+                           ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
   // On success we next expect an entry mid ':' then an object mid ',' or '}'
   if (result.ok()) {
@@ -727,14 +760,16 @@
 
 util::Status JsonStreamParser::ParseEntryMid(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected : between key:value pair.");
+    return ReportUnknown("Expected : between key:value pair.",
+                         ParseErrorType::EXPECTED_COLON);
   }
   if (type == ENTRY_SEPARATOR) {
     Advance();
     stack_.push(VALUE);
     return util::Status();
   }
-  return ReportFailure("Expected : between key:value pair.");
+  return ReportFailure("Expected : between key:value pair.",
+                       ParseErrorType::EXPECTED_COLON);
 }
 
 util::Status JsonStreamParser::HandleBeginArray() {
@@ -748,7 +783,8 @@
 
 util::Status JsonStreamParser::ParseArrayValue(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected a value or ] within an array.");
+    return ReportUnknown("Expected a value or ] within an array.",
+                         ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
   }
 
   if (type == END_ARRAY) {
@@ -762,7 +798,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();
@@ -772,7 +808,8 @@
 
 util::Status JsonStreamParser::ParseArrayMid(TokenType type) {
   if (type == UNKNOWN) {
-    return ReportUnknown("Expected , or ] after array value.");
+    return ReportUnknown("Expected , or ] after array value.",
+                         ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
   }
 
   if (type == END_ARRAY) {
@@ -788,7 +825,8 @@
     return util::Status();
   }
   // Illegal token after array value.
-  return ReportFailure("Expected , or ] after array value.");
+  return ReportFailure("Expected , or ] after array value.",
+                       ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
 }
 
 util::Status JsonStreamParser::ParseTrue() {
@@ -824,7 +862,8 @@
          stack_.top() == OBJ_MID;
 }
 
-util::Status JsonStreamParser::ReportFailure(StringPiece message) {
+util::Status JsonStreamParser::ReportFailure(StringPiece message,
+                                             ParseErrorType parse_code) {
   static const int kContextLength = 20;
   const char* p_start = p_.data();
   const char* json_start = json_.data();
@@ -834,28 +873,29 @@
   StringPiece segment(begin, end - begin);
   std::string location(p_start - begin, ' ');
   location.push_back('^');
-  return util::Status(util::error::INVALID_ARGUMENT,
-                      StrCat(message, "\n", segment, "\n", location));
+  auto status = util::InvalidArgumentError(
+      StrCat(message, "\n", segment, "\n", location));
+  return status;
 }
 
-util::Status JsonStreamParser::ReportUnknown(StringPiece message) {
+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));
+    return ReportFailure(StrCat("Unexpected end of string. ", message),
+                         parse_code);
   }
-  return ReportFailure(message);
+  return ReportFailure(message, parse_code);
 }
 
 util::Status JsonStreamParser::IncrementRecursionDepth(
     StringPiece key) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return util::Status(
-        util::error::INVALID_ARGUMENT,
-        StrCat("Message too deep. Max recursion depth reached for key '",
-                     key, "'"));
+    return util::InvalidArgumentError(StrCat(
+        "Message too deep. Max recursion depth reached for key '", key, "'"));
   }
   return util::Status();
 }
@@ -864,6 +904,9 @@
   while (!p_.empty() && ascii_isspace(*p_.data())) {
     Advance();
   }
+  if (!p_.empty() && !ascii_isspace(*p_.data())) {
+    seen_non_whitespace_ = true;
+  }
 }
 
 void JsonStreamParser::Advance() {
@@ -878,11 +921,13 @@
 
   if (allow_permissive_key_naming_) {
     if (!ConsumeKeyPermissive(&p_, &key_)) {
-      return ReportFailure("Invalid key or variable name.");
+      return ReportFailure("Invalid key or variable name.",
+                           ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME);
     }
   } else {
     if (!ConsumeKey(&p_, &key_)) {
-      return ReportFailure("Invalid key or variable name.");
+      return ReportFailure("Invalid key or variable name.",
+                           ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME);
     }
   }
 
@@ -890,7 +935,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 5a9eac8..47dfe82 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ b/src/google/protobuf/util/internal/json_stream_parser.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__
 
+#include <cstdint>
 #include <stack>
 #include <string>
 
@@ -46,6 +47,7 @@
 namespace util {
 namespace converter {
 
+
 class ObjectWriter;
 
 // A JSON parser that can parse a stream of JSON chunks rather than needing the
@@ -74,11 +76,17 @@
   explicit JsonStreamParser(ObjectWriter* ow);
   virtual ~JsonStreamParser();
 
-  // Parses a UTF-8 encoded JSON string from a StringPiece.
+  // Parses a UTF-8 encoded JSON string from a StringPiece. If the returned
+  // status is non-ok, the status might contain a payload ParseErrorType with
+  // type_url kParseErrorTypeUrl and a payload containing string snippet of the
+  // error with type_url kParseErrorSnippetUrl.
   util::Status Parse(StringPiece json);
 
 
-  // Finish parsing the JSON string.
+  // Finish parsing the JSON string. If the returned status is non-ok, the
+  // status might contain a payload ParseErrorType with type_url
+  // kParseErrorTypeUrl and a payload containing string snippet of the error
+  // with type_url kParseErrorSnippetUrl.
   util::Status FinishParse();
 
 
@@ -89,6 +97,30 @@
     max_recursion_depth_ = max_depth;
   }
 
+  // Denotes the cause of error.
+  enum ParseErrorType {
+    UNKNOWN_PARSE_ERROR,
+    OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES,
+    EXPECTED_COLON,
+    EXPECTED_COMMA_OR_BRACKET,
+    EXPECTED_VALUE,
+    EXPECTED_COMMA_OR_BRACES,
+    EXPECTED_OBJECT_KEY_OR_BRACES,
+    EXPECTED_VALUE_OR_BRACKET,
+    INVALID_KEY_OR_VARIABLE_NAME,
+    NON_UTF_8,
+    PARSING_TERMINATED_BEFORE_END_OF_INPUT,
+    UNEXPECTED_TOKEN,
+    EXPECTED_CLOSING_QUOTE,
+    ILLEGAL_HEX_STRING,
+    INVALID_ESCAPE_SEQUENCE,
+    MISSING_LOW_SURROGATE,
+    INVALID_LOW_SURROGATE,
+    INVALID_UNICODE,
+    UNABLE_TO_PARSE_NUMBER,
+    NUMBER_EXCEEDS_RANGE_DOUBLE
+  };
+
  private:
   friend class JsonStreamParserTest;
   // Return the current recursion depth.
@@ -125,8 +157,8 @@
     Type type;
     union {
       double double_val;
-      int64 int_val;
-      uint64 uint_val;
+      int64_t int_val;
+      uint64_t uint_val;
     };
   };
 
@@ -198,16 +230,21 @@
   // Whether an empty-null is allowed in the current state.
   bool IsEmptyNullAllowed(TokenType type);
 
+  // Whether the whole input is all whitespaces.
+  bool IsInputAllWhiteSpaces(TokenType type);
+
   // Report a failure as a util::Status.
-  util::Status ReportFailure(StringPiece message);
+  util::Status ReportFailure(StringPiece message,
+                             ParseErrorType parse_code);
 
   // Report a failure due to an UNKNOWN token type. We check if we hit the
   // end of the stream and if we're finishing or not to detect what type of
   // status to return in this case.
-  util::Status ReportUnknown(StringPiece message);
+  util::Status ReportUnknown(StringPiece message,
+                             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;
 
@@ -253,6 +290,15 @@
   // trying during the next chunk, but during FinishParse() it is an error.
   bool finishing_;
 
+  // Whether non whitespace tokens have been seen during parsing.
+  // It is used to handle the case of a pure whitespace stream input.
+  bool seen_non_whitespace_;
+
+  // The JsonStreamParser requires a root element by default and it will raise
+  // error if the root element is missing. If `allow_no_root_element_` is true,
+  // the JsonStreamParser can also handle this case.
+  bool allow_no_root_element_;
+
   // String we parsed during a call to ParseStringHelper().
   StringPiece parsed_;
 
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 ac6fe3d..4bb1025 100644
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/internal/json_stream_parser.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/logging.h>
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/util/internal/expecting_objectwriter.h>
@@ -42,11 +44,11 @@
 namespace google {
 namespace protobuf {
 namespace util {
-namespace error {
-using util::error::INVALID_ARGUMENT;
-}  // namespace error
 namespace converter {
 
+using ParseErrorType =
+    ::google::protobuf::util::converter::JsonStreamParser::ParseErrorType;
+
 
 // Tests for the JSON Stream Parser. These tests are intended to be
 // comprehensive and cover the following:
@@ -136,8 +138,19 @@
       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()));
+  }
+
+  void DoErrorTest(
+      StringPiece json, int split, StringPiece error_prefix,
+      ParseErrorType expected_parse_error_type,
+      std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
+      }) {
+    util::Status result = RunTest(json, split, setup);
+    EXPECT_TRUE(util::IsInvalidArgument(result));
+    StringPiece error_message(result.message());
     EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size()));
   }
 
@@ -233,7 +246,7 @@
 TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
   StringPiece str = "-79497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderInt64("", int64{-79497823553162765});
+    ow_.RenderInt64("", int64_t{-79497823553162765});
     DoTest(str, i);
   }
 }
@@ -241,7 +254,7 @@
 TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
   StringPiece str = "11779497823553162765";
   for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderUint64("", uint64{11779497823553162765u});
+    ow_.RenderUint64("", uint64_t{11779497823553162765u});
     DoTest(str, i);
   }
 }
@@ -249,26 +262,31 @@
 TEST_F(JsonStreamParserTest, OctalNumberIsInvalid) {
   StringPiece str = "01234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   str = "-01234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
 }
 
 TEST_F(JsonStreamParserTest, HexNumberIsInvalid) {
   StringPiece str = "0x1234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   str = "-0x1234";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.");
+    DoErrorTest(str, i, "Octal/hex numbers are not valid JSON values.",
+                ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
   }
   str = "12x34";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Unable to parse number.");
+    DoErrorTest(str, i, "Unable to parse number.",
+                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
 }
 
@@ -338,14 +356,16 @@
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithReservedKeyword) {
   StringPiece str = "{ null: \"a\", true: \"b\", false: \"c\"}";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
 TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithEmbeddedNonAlphanumeric) {
   StringPiece str = "{ foo-bar-baz: \"a\"}";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected : between key:value pair.");
+    DoErrorTest(str, i, "Expected : between key:value pair.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -376,7 +396,7 @@
         ->RenderInt64("", -127)
         ->RenderDouble("", 45.3)
         ->RenderDouble("", -1056.4)
-        ->RenderUint64("", uint64{11779497823553162765u})
+        ->RenderUint64("", uint64_t{11779497823553162765u})
         ->EndList()
         ->StartObject("")
         ->RenderBool("key", true)
@@ -404,7 +424,7 @@
         ->RenderInt64("ni", -127)
         ->RenderDouble("pd", 45.3)
         ->RenderDouble("nd", -1056.4)
-        ->RenderUint64("pl", uint64{11779497823553162765u})
+        ->RenderUint64("pl", uint64_t{11779497823553162765u})
         ->StartList("l")
         ->StartList("")
         ->EndList()
@@ -421,13 +441,16 @@
 TEST_F(JsonStreamParserTest, RejectNonUtf8WhenNotCoerced) {
   StringPiece json = "{\"address\":\xFF\"חרושת 23, רעננה, ישראל\"}";
   for (int i = 0; i <= json.length(); ++i) {
-    DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+    DoErrorTest(json, i, "Encountered non UTF-8 code points.",
+                ParseErrorType::NON_UTF_8);
   }
   json = "{\"address\": \"חרושת 23,\xFFרעננה, ישראל\"}";
   for (int i = 0; i <= json.length(); ++i) {
-    DoErrorTest(json, i, "Encountered non UTF-8 code points.");
+    DoErrorTest(json, i, "Encountered non UTF-8 code points.",
+                ParseErrorType::NON_UTF_8);
   }
-  DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.");
+  DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.",
+              ParseErrorType::NON_UTF_8);
 }
 
 // - unicode handling in strings
@@ -460,7 +483,8 @@
   // A low surrogate alone.
   StringPiece str = "[\"\\ude36\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid unicode code point.");
+    DoErrorTest(str, i, "Invalid unicode code point.",
+                ParseErrorType::INVALID_UNICODE);
   }
 }
 
@@ -468,22 +492,26 @@
   // A high surrogate alone.
   StringPiece str = "[\"\\ud83d\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Missing low surrogate.");
+    DoErrorTest(str, i, "Missing low surrogate.",
+                ParseErrorType::MISSING_LOW_SURROGATE);
   }
   // A high surrogate with some trailing characters.
   str = "[\"\\ud83d|ude36\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Missing low surrogate.");
+    DoErrorTest(str, i, "Missing low surrogate.",
+                ParseErrorType::MISSING_LOW_SURROGATE);
   }
   // A high surrogate with half a low surrogate.
   str = "[\"\\ud83d\\ude--\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
   // Two high surrogates.
   str = "[\"\\ud83d\\ud83d\"]";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid low surrogate.");
+    DoErrorTest(str, i, "Invalid low surrogate.",
+                ParseErrorType::INVALID_LOW_SURROGATE);
   }
 }
 
@@ -527,21 +555,24 @@
   StringPiece str = "truee";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderBool("", true);
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
 TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) {
   StringPiece str = "-";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Unable to parse number.");
+    DoErrorTest(str, i, "Unable to parse number.",
+                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
 }
 
 TEST_F(JsonStreamParserTest, InvalidNumberDashName) {
   StringPiece str = "-foo";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Unable to parse number.");
+    DoErrorTest(str, i, "Unable to parse number.",
+                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
   }
 }
 
@@ -549,7 +580,7 @@
   StringPiece str = "[nule]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Unexpected token.");
+    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
   }
 }
 
@@ -557,7 +588,8 @@
   StringPiece str = "{123false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -565,14 +597,16 @@
 TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
   StringPiece str = "'Some str\"";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
 TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) {
   StringPiece str = "\"Another string that ends poorly!'";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -580,14 +614,16 @@
 TEST_F(JsonStreamParserTest, UnterminatedLiteralString) {
   StringPiece str = "\"Forgot the rest of i";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
 TEST_F(JsonStreamParserTest, UnterminatedStringEscape) {
   StringPiece str = "\"Forgot the rest of \\";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -595,7 +631,8 @@
   StringPiece str = "[\"Forgot to close the string]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -603,7 +640,8 @@
   StringPiece str = "{f: \"Forgot to close the string}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -611,7 +649,8 @@
   StringPiece str = "{";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected end of string.");
+    DoErrorTest(str, i, "Unexpected end of string.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -621,7 +660,8 @@
   StringPiece str = "{'key': true]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderBool("key", true);
-    DoErrorTest(str, i, "Expected , or } after key:value pair.");
+    DoErrorTest(str, i, "Expected , or } after key:value pair.",
+                ParseErrorType::EXPECTED_COMMA_OR_BRACES);
   }
 }
 
@@ -629,7 +669,8 @@
   StringPiece str = "[true, null}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderBool("", true)->RenderNull("");
-    DoErrorTest(str, i, "Expected , or ] after array value.");
+    DoErrorTest(str, i, "Expected , or ] after array value.",
+                ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
   }
 }
 
@@ -638,7 +679,8 @@
   StringPiece str = "{42: true}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -646,7 +688,8 @@
   StringPiece str = "{{bob: true}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -654,7 +697,8 @@
   StringPiece str = "{[null]}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -662,7 +706,8 @@
   StringPiece str = "{false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -670,7 +715,8 @@
   StringPiece str = "{\"key\"}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected : between key:value pair.");
+    DoErrorTest(str, i, "Expected : between key:value pair.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -678,7 +724,8 @@
   StringPiece str = "{key}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected : between key:value pair.");
+    DoErrorTest(str, i, "Expected : between key:value pair.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -686,7 +733,8 @@
   StringPiece str = "{key";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected end of string.");
+    DoErrorTest(str, i, "Unexpected end of string.",
+                ParseErrorType::EXPECTED_COLON);
   }
 }
 
@@ -694,7 +742,7 @@
   StringPiece str = "{key:}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected token.");
+    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
   }
 }
 
@@ -702,7 +750,8 @@
   StringPiece str = "{key:20 'hello': true}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderUint64("key", 20);
-    DoErrorTest(str, i, "Expected , or } after key:value pair.");
+    DoErrorTest(str, i, "Expected , or } after key:value pair.",
+                ParseErrorType::EXPECTED_COMMA_OR_BRACES);
   }
 }
 
@@ -710,7 +759,8 @@
   StringPiece str = "{false: 20}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -718,7 +768,8 @@
   StringPiece str = "{}}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->EndObject();
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -742,12 +793,14 @@
   StringPiece str = "[1.89769e+308]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Number exceeds the range of double.");
+    DoErrorTest(str, i, "Number exceeds the range of double.",
+                ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
   str = "[-1.89769e+308]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Number exceeds the range of double.");
+    DoErrorTest(str, i, "Number exceeds the range of double.",
+                ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
   }
 }
 
@@ -756,7 +809,8 @@
 TEST_F(JsonStreamParserTest, UnfinishedEscape) {
   StringPiece str = "\"\\";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.");
+    DoErrorTest(str, i, "Closing quote expected in string.",
+                ParseErrorType::EXPECTED_CLOSING_QUOTE);
   }
 }
 
@@ -764,7 +818,8 @@
 TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
   StringPiece str = "\"\\u";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Illegal hex string.");
+    DoErrorTest(str, i, "Illegal hex string.",
+                ParseErrorType::ILLEGAL_HEX_STRING);
   }
 }
 
@@ -772,7 +827,8 @@
 TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
   StringPiece str = "\"\\u12";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Illegal hex string.");
+    DoErrorTest(str, i, "Illegal hex string.",
+                ParseErrorType::ILLEGAL_HEX_STRING);
   }
 }
 
@@ -780,7 +836,8 @@
 TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
   StringPiece str = "\"\\u{1f36f}\"";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
 }
 
@@ -788,7 +845,8 @@
 TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
   StringPiece str = "\"\\u12$4hello";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
 }
 
@@ -796,7 +854,8 @@
 TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
   StringPiece str = "\"\\ud800\\udcfg\"";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.");
+    DoErrorTest(str, i, "Invalid escape sequence.",
+                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
   }
 }
 
@@ -805,7 +864,8 @@
   StringPiece str = "{'k1': true,,'k2': false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderBool("k1", true);
-    DoErrorTest(str, i, "Expected an object key or }.");
+    DoErrorTest(str, i, "Expected an object key or }.",
+                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
   }
 }
 
@@ -813,7 +873,7 @@
   StringPiece str = "[true,,false}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderBool("", true);
-    DoErrorTest(str, i, "Unexpected token.");
+    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
   }
 }
 
@@ -822,7 +882,8 @@
   StringPiece str = "'hello', 'world'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.RenderString("", "hello");
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -830,7 +891,8 @@
   StringPiece str = "{'key': true} 'oops'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("")->RenderBool("key", true)->EndObject();
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -838,7 +900,8 @@
   StringPiece str = "[null] 'oops'";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("")->RenderNull("")->EndList();
-    DoErrorTest(str, i, "Parsing terminated before end of input.");
+    DoErrorTest(str, i, "Parsing terminated before end of input.",
+                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
   }
 }
 
@@ -846,7 +909,7 @@
 TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
   StringPiece str = "*&#25";
   for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected a value.");
+    DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
   }
 }
 
@@ -854,7 +917,8 @@
   StringPiece str = "[*&#25]";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartList("");
-    DoErrorTest(str, i, "Expected a value or ] within an array.");
+    DoErrorTest(str, i, "Expected a value or ] within an array.",
+                ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
   }
 }
 
@@ -862,7 +926,7 @@
   StringPiece str = "{'key': *&#25}";
   for (int i = 0; i <= str.length(); ++i) {
     ow_.StartObject("");
-    DoErrorTest(str, i, "Expected a value.");
+    DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
   }
 }
 
diff --git a/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc
index b7667b6..4dabd37 100644
--- a/src/google/protobuf/util/internal/object_writer.cc
+++ b/src/google/protobuf/util/internal/object_writer.cc
@@ -74,7 +74,7 @@
       break;
     }
     case DataPiece::TYPE_BYTES: {
-      ow->RenderBytes(name, data.ToBytes().ValueOrDie());
+      ow->RenderBytes(name, data.ToBytes().value());
       break;
     }
     case DataPiece::TYPE_NULL: {
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
index 29b05c1..917a280 100644
--- a/src/google/protobuf/util/internal/object_writer.h
+++ b/src/google/protobuf/util/internal/object_writer.h
@@ -31,6 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/stubs/strutil.h>
 
@@ -79,16 +81,18 @@
   virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0;
 
   // Renders an 32-bit integer value.
-  virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) = 0;
+  virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) = 0;
 
   // Renders an 32-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) = 0;
+  virtual ObjectWriter* RenderUint32(StringPiece name,
+                                     uint32_t value) = 0;
 
   // Renders a 64-bit integer value.
-  virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) = 0;
+  virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) = 0;
 
   // Renders an 64-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) = 0;
+  virtual ObjectWriter* RenderUint64(StringPiece name,
+                                     uint64_t value) = 0;
 
 
   // Renders a double value.
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index 0102259..717cee4 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/proto_writer.h>
 
+#include <cstdint>
 #include <functional>
 #include <stack>
 
@@ -54,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,
@@ -122,7 +121,7 @@
 // Writes an INT32 field, including tag to the stream.
 inline util::Status WriteInt32(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
-  util::StatusOr<int32> i32 = data.ToInt32();
+  util::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteInt32(field_number, i32.value(), stream);
   }
@@ -132,7 +131,7 @@
 // writes an SFIXED32 field, including tag, to the stream.
 inline util::Status WriteSFixed32(int field_number, const DataPiece& data,
                                   CodedOutputStream* stream) {
-  util::StatusOr<int32> i32 = data.ToInt32();
+  util::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteSFixed32(field_number, i32.value(), stream);
   }
@@ -142,7 +141,7 @@
 // Writes an SINT32 field, including tag, to the stream.
 inline util::Status WriteSInt32(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<int32> i32 = data.ToInt32();
+  util::StatusOr<int32_t> i32 = data.ToInt32();
   if (i32.ok()) {
     WireFormatLite::WriteSInt32(field_number, i32.value(), stream);
   }
@@ -152,7 +151,7 @@
 // Writes a FIXED32 field, including tag, to the stream.
 inline util::Status WriteFixed32(int field_number, const DataPiece& data,
                                  CodedOutputStream* stream) {
-  util::StatusOr<uint32> u32 = data.ToUint32();
+  util::StatusOr<uint32_t> u32 = data.ToUint32();
   if (u32.ok()) {
     WireFormatLite::WriteFixed32(field_number, u32.value(), stream);
   }
@@ -162,7 +161,7 @@
 // Writes a UINT32 field, including tag, to the stream.
 inline util::Status WriteUInt32(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<uint32> u32 = data.ToUint32();
+  util::StatusOr<uint32_t> u32 = data.ToUint32();
   if (u32.ok()) {
     WireFormatLite::WriteUInt32(field_number, u32.value(), stream);
   }
@@ -172,7 +171,7 @@
 // Writes an INT64 field, including tag, to the stream.
 inline util::Status WriteInt64(int field_number, const DataPiece& data,
                                CodedOutputStream* stream) {
-  util::StatusOr<int64> i64 = data.ToInt64();
+  util::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteInt64(field_number, i64.value(), stream);
   }
@@ -182,7 +181,7 @@
 // Writes an SFIXED64 field, including tag, to the stream.
 inline util::Status WriteSFixed64(int field_number, const DataPiece& data,
                                   CodedOutputStream* stream) {
-  util::StatusOr<int64> i64 = data.ToInt64();
+  util::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteSFixed64(field_number, i64.value(), stream);
   }
@@ -192,7 +191,7 @@
 // Writes an SINT64 field, including tag, to the stream.
 inline util::Status WriteSInt64(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<int64> i64 = data.ToInt64();
+  util::StatusOr<int64_t> i64 = data.ToInt64();
   if (i64.ok()) {
     WireFormatLite::WriteSInt64(field_number, i64.value(), stream);
   }
@@ -202,7 +201,7 @@
 // Writes a FIXED64 field, including tag, to the stream.
 inline util::Status WriteFixed64(int field_number, const DataPiece& data,
                                  CodedOutputStream* stream) {
-  util::StatusOr<uint64> u64 = data.ToUint64();
+  util::StatusOr<uint64_t> u64 = data.ToUint64();
   if (u64.ok()) {
     WireFormatLite::WriteFixed64(field_number, u64.value(), stream);
   }
@@ -212,7 +211,7 @@
 // Writes a UINT64 field, including tag, to the stream.
 inline util::Status WriteUInt64(int field_number, const DataPiece& data,
                                 CodedOutputStream* stream) {
-  util::StatusOr<uint64> u64 = data.ToUint64();
+  util::StatusOr<uint64_t> u64 = data.ToUint64();
   if (u64.ok()) {
     WireFormatLite::WriteUInt64(field_number, u64.value(), stream);
   }
@@ -254,7 +253,7 @@
                                CodedOutputStream* stream) {
   util::StatusOr<std::string> c = data.ToBytes();
   if (c.ok()) {
-    WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream);
+    WireFormatLite::WriteBytes(field_number, c.value(), stream);
   }
   return c.status();
 }
@@ -431,11 +430,11 @@
   return loc;
 }
 
-bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) {
+bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32_t index) {
   return oneof_indices_[index];
 }
 
-void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) {
+void ProtoWriter::ProtoElement::TakeOneofIndex(int32_t index) {
   oneof_indices_[index] = true;
 }
 
@@ -694,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()) {
@@ -801,8 +799,8 @@
     //   size_insert_.front().size: the size (integer) to be inserted.
     if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) {
       // Varint32 occupies at most 10 bytes.
-      uint8 insert_buffer[10];
-      uint8* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray(
+      uint8_t insert_buffer[10];
+      uint8_t* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray(
           size_insert_.front().size, insert_buffer);
       output_->Append(reinterpret_cast<const char*>(insert_buffer),
                       insert_buffer_pos - insert_buffer);
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
index a98c5d8..109c198 100644
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__
 
+#include <cstdint>
 #include <deque>
 #include <string>
 #include <vector>
@@ -82,16 +83,16 @@
   ProtoWriter* RenderBool(StringPiece name, bool value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderInt32(StringPiece name, int32 value) override {
+  ProtoWriter* RenderInt32(StringPiece name, int32_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderUint32(StringPiece name, uint32 value) override {
+  ProtoWriter* RenderUint32(StringPiece name, uint32_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderInt64(StringPiece name, int64 value) override {
+  ProtoWriter* RenderInt64(StringPiece name, int64_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
-  ProtoWriter* RenderUint64(StringPiece name, uint64 value) override {
+  ProtoWriter* RenderUint64(StringPiece name, uint64_t value) override {
     return RenderDataPiece(name, DataPiece(value));
   }
   ProtoWriter* RenderDouble(StringPiece name, double value) override {
@@ -204,11 +205,11 @@
     }
 
     // Returns true if the index is already taken by a preceding oneof input.
-    bool IsOneofIndexTaken(int32 index);
+    bool IsOneofIndexTaken(int32_t index);
 
     // Marks the oneof 'index' as taken. Future inputs to this oneof will
     // generate an error.
-    void TakeOneofIndex(int32 index);
+    void TakeOneofIndex(int32_t index);
 
     bool proto3() { return proto3_; }
 
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index 49074fb..3a37d9c 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/protostream_objectsource.h>
 
+#include <cstdint>
 #include <unordered_map>
 #include <utility>
 
@@ -59,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;
 
@@ -83,7 +81,7 @@
     const google::protobuf::Enum& tech_enum, int number);
 
 // Utility function to format nanos.
-const std::string FormatNanos(uint32 nanos, bool with_trailing_zeros);
+const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros);
 
 util::StatusOr<std::string> MapKeyDefaultValueAsString(
     const google::protobuf::Field& field) {
@@ -104,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
@@ -148,7 +146,7 @@
 }
 
 const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField(
-    const google::protobuf::Type& type, uint32 tag) const {
+    const google::protobuf::Type& type, uint32_t tag) const {
   // Lookup the new field in the type by tag number.
   const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3);
   // Verify if the field corresponds to the wire type in tag.
@@ -169,7 +167,8 @@
 
 util::Status ProtoStreamObjectSource::WriteMessage(
     const google::protobuf::Type& type, StringPiece name,
-    const uint32 end_tag, bool include_start_and_end, ObjectWriter* ow) const {
+    const uint32_t end_tag, bool include_start_and_end,
+    ObjectWriter* ow) const {
 
   const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
   if (type_renderer != nullptr) {
@@ -179,7 +178,7 @@
   const google::protobuf::Field* field = nullptr;
   std::string field_name;
   // last_tag set to dummy value that is different from tag.
-  uint32 tag = stream_->ReadTag(), last_tag = tag + 1;
+  uint32_t tag = stream_->ReadTag(), last_tag = tag + 1;
   UnknownFieldSet unknown_fields;
 
 
@@ -230,10 +229,10 @@
   return util::Status();
 }
 
-util::StatusOr<uint32> ProtoStreamObjectSource::RenderList(
+util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList(
     const google::protobuf::Field* field, StringPiece name,
-    uint32 list_tag, ObjectWriter* ow) const {
-  uint32 tag_to_return = 0;
+    uint32_t list_tag, ObjectWriter* ow) const {
+  uint32_t tag_to_return = 0;
   ow->StartList(name);
   if (IsPackable(*field) &&
       list_tag ==
@@ -252,19 +251,20 @@
   return tag_to_return;
 }
 
-util::StatusOr<uint32> ProtoStreamObjectSource::RenderMap(
+util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap(
     const google::protobuf::Field* field, StringPiece name,
-    uint32 list_tag, ObjectWriter* ow) const {
+    uint32_t list_tag, ObjectWriter* ow) const {
   const google::protobuf::Type* field_type =
       typeinfo_->GetTypeByTypeUrl(field->type_url());
-  uint32 tag_to_return = 0;
+  uint32_t tag_to_return = 0;
   do {
     // Render map entry message type.
-    uint32 buffer32;
+    uint32_t buffer32;
     stream_->ReadVarint32(&buffer32);  // message length
     int old_limit = stream_->PushLimit(buffer32);
     std::string map_key;
-    for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
+    for (uint32_t tag = stream_->ReadTag(); tag != 0;
+         tag = stream_->ReadTag()) {
       const google::protobuf::Field* field =
           FindAndVerifyField(*field_type, tag);
       if (field == nullptr) {
@@ -282,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));
         }
@@ -291,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);
@@ -301,7 +300,7 @@
 
 util::Status ProtoStreamObjectSource::RenderPacked(
     const google::protobuf::Field* field, ObjectWriter* ow) const {
-  uint32 length;
+  uint32_t length;
   stream_->ReadVarint32(&length);
   int old_limit = stream_->PushLimit(length);
   while (stream_->BytesUntilLimit() > 0) {
@@ -314,19 +313,16 @@
 util::Status ProtoStreamObjectSource::RenderTimestamp(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  std::pair<int64, int32> p = os->ReadSecondsAndNanos(type);
-  int64 seconds = p.first;
-  int32 nanos = p.second;
+  std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type);
+  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));
   }
 
@@ -339,26 +335,23 @@
 util::Status ProtoStreamObjectSource::RenderDuration(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  std::pair<int64, int32> p = os->ReadSecondsAndNanos(type);
-  int64 seconds = p.first;
-  int32 nanos = p.second;
+  std::pair<int64_t, int32_t> p = os->ReadSecondsAndNanos(type);
+  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));
@@ -384,8 +377,8 @@
 util::Status ProtoStreamObjectSource::RenderDouble(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // default value of Double wrapper value
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // default value of Double wrapper value
   if (tag != 0) {
     os->stream_->ReadLittleEndian64(&buffer64);
     os->stream_->ReadTag();
@@ -397,8 +390,8 @@
 util::Status ProtoStreamObjectSource::RenderFloat(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32 = 0;  // default value of Float wrapper value
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32 = 0;  // default value of Float wrapper value
   if (tag != 0) {
     os->stream_->ReadLittleEndian32(&buffer32);
     os->stream_->ReadTag();
@@ -410,61 +403,61 @@
 util::Status ProtoStreamObjectSource::RenderInt64(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // default value of Int64 wrapper value
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // default value of Int64 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint64(&buffer64);
     os->stream_->ReadTag();
   }
-  ow->RenderInt64(field_name, bit_cast<int64>(buffer64));
+  ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64));
   return util::Status();
 }
 
 util::Status ProtoStreamObjectSource::RenderUInt64(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // default value of UInt64 wrapper value
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // default value of UInt64 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint64(&buffer64);
     os->stream_->ReadTag();
   }
-  ow->RenderUint64(field_name, bit_cast<uint64>(buffer64));
+  ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64));
   return util::Status();
 }
 
 util::Status ProtoStreamObjectSource::RenderInt32(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32 = 0;  // default value of Int32 wrapper value
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32 = 0;  // default value of Int32 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);
     os->stream_->ReadTag();
   }
-  ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+  ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
   return util::Status();
 }
 
 util::Status ProtoStreamObjectSource::RenderUInt32(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32 = 0;  // default value of UInt32 wrapper value
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32 = 0;  // default value of UInt32 wrapper value
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);
     os->stream_->ReadTag();
   }
-  ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+  ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
   return util::Status();
 }
 
 util::Status ProtoStreamObjectSource::RenderBool(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint64 buffer64 = 0;  // results in 'false' value as default, which is the
-                        // default value of Bool wrapper
+  uint32_t tag = os->stream_->ReadTag();
+  uint64_t buffer64 = 0;  // results in 'false' value as default, which is the
+                          // default value of Bool wrapper
   if (tag != 0) {
     os->stream_->ReadVarint64(&buffer64);
     os->stream_->ReadTag();
@@ -476,8 +469,8 @@
 util::Status ProtoStreamObjectSource::RenderString(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32;
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32;
   std::string str;  // default value of empty for String wrapper
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);  // string size.
@@ -491,8 +484,8 @@
 util::Status ProtoStreamObjectSource::RenderBytes(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
-  uint32 buffer32;
+  uint32_t tag = os->stream_->ReadTag();
+  uint32_t buffer32;
   std::string str;
   if (tag != 0) {
     os->stream_->ReadVarint32(&buffer32);
@@ -507,7 +500,7 @@
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
   const google::protobuf::Field* field = nullptr;
-  uint32 tag = os->stream_->ReadTag();
+  uint32_t tag = os->stream_->ReadTag();
   ow->StartObject(field_name);
   while (tag != 0) {
     field = os->FindAndVerifyField(type, tag);
@@ -530,7 +523,7 @@
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
   const google::protobuf::Field* field = nullptr;
-  for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+  for (uint32_t tag = os->stream_->ReadTag(); tag != 0;
        tag = os->stream_->ReadTag()) {
     field = os->FindAndVerifyField(type, tag);
     if (field == nullptr) {
@@ -546,7 +539,7 @@
 util::Status ProtoStreamObjectSource::RenderStructListValue(
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
-  uint32 tag = os->stream_->ReadTag();
+  uint32_t tag = os->stream_->ReadTag();
 
   // Render empty list when we find empty ListValue message.
   if (tag == 0) {
@@ -571,7 +564,7 @@
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
   // An Any is of the form { string type_url = 1; bytes value = 2; }
-  uint32 tag;
+  uint32_t tag;
   std::string type_url;
   std::string value;
 
@@ -586,12 +579,12 @@
     // //google/protobuf/any.proto
     if (field->number() == 1) {
       // read type_url
-      uint32 type_url_size;
+      uint32_t type_url_size;
       os->stream_->ReadVarint32(&type_url_size);
       os->stream_->ReadString(&type_url, type_url_size);
     } else if (field->number() == 2) {
       // read value
-      uint32 value_size;
+      uint32_t value_size;
       os->stream_->ReadVarint32(&value_size);
       os->stream_->ReadString(&value, value_size);
     }
@@ -611,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 =
@@ -621,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();
@@ -647,9 +638,9 @@
     const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
     StringPiece field_name, ObjectWriter* ow) {
   std::string combined;
-  uint32 buffer32;
-  uint32 paths_field_tag = 0;
-  for (uint32 tag = os->stream_->ReadTag(); tag != 0;
+  uint32_t buffer32;
+  uint32_t paths_field_tag = 0;
+  for (uint32_t tag = os->stream_->ReadTag(); tag != 0;
        tag = os->stream_->ReadTag()) {
     if (paths_field_tag == 0) {
       const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
@@ -659,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.
@@ -737,15 +727,14 @@
   // and ends up using a lot of stack space. Keep the stack usage of this
   // message small in order to preserve stack space and not crash.
   if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) {
-    uint32 buffer32;
+    uint32_t buffer32;
     stream_->ReadVarint32(&buffer32);  // message length
     int old_limit = stream_->PushLimit(buffer32);
     // Get the nested message type for this field.
     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()));
     }
@@ -762,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);
@@ -778,8 +766,8 @@
     const google::protobuf::Field* field, StringPiece field_name,
     ObjectWriter* ow) const {
   // Temporary buffers of different types.
-  uint32 buffer32 = 0;
-  uint64 buffer64 = 0;
+  uint32_t buffer32 = 0;
+  uint64_t buffer64 = 0;
   std::string strbuffer;
   switch (field->kind()) {
     case google::protobuf::Field::TYPE_BOOL: {
@@ -789,7 +777,7 @@
     }
     case google::protobuf::Field::TYPE_INT32: {
       stream_->ReadVarint32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_INT64: {
@@ -799,7 +787,7 @@
     }
     case google::protobuf::Field::TYPE_UINT32: {
       stream_->ReadVarint32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_UINT64: {
@@ -819,7 +807,7 @@
     }
     case google::protobuf::Field::TYPE_SFIXED32: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32>(buffer32));
+      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED64: {
@@ -829,7 +817,7 @@
     }
     case google::protobuf::Field::TYPE_FIXED32: {
       stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32>(buffer32));
+      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED64: {
@@ -907,85 +895,85 @@
   std::string result;
   switch (field.kind()) {
     case google::protobuf::Field::TYPE_BOOL: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
       result = buffer64 != 0 ? "true" : "false";
       break;
     }
     case google::protobuf::Field::TYPE_INT32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<int32>(buffer32));
+      result = StrCat(bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_INT64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
-      result = StrCat(bit_cast<int64>(buffer64));
+      result = StrCat(bit_cast<int64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_UINT32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<uint32>(buffer32));
+      result = StrCat(bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_UINT64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
-      result = StrCat(bit_cast<uint64>(buffer64));
+      result = StrCat(bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SINT32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
       result = StrCat(WireFormatLite::ZigZagDecode32(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SINT64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadVarint64(&buffer64);
       result = StrCat(WireFormatLite::ZigZagDecode64(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<int32>(buffer32));
+      result = StrCat(bit_cast<int32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_SFIXED64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
-      result = StrCat(bit_cast<int64>(buffer64));
+      result = StrCat(bit_cast<int64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED32: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<uint32>(buffer32));
+      result = StrCat(bit_cast<uint32_t>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_FIXED64: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
-      result = StrCat(bit_cast<uint64>(buffer64));
+      result = StrCat(bit_cast<uint64_t>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_FLOAT: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadLittleEndian32(&buffer32);
       result = SimpleFtoa(bit_cast<float>(buffer32));
       break;
     }
     case google::protobuf::Field::TYPE_DOUBLE: {
-      uint64 buffer64;
+      uint64_t buffer64;
       stream_->ReadLittleEndian64(&buffer64);
       result = SimpleDtoa(bit_cast<double>(buffer64));
       break;
     }
     case google::protobuf::Field::TYPE_ENUM: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);
       // Get the nested enum type for this field.
       // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
@@ -1003,13 +991,13 @@
       break;
     }
     case google::protobuf::Field::TYPE_STRING: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);  // string size.
       stream_->ReadString(&result, buffer32);
       break;
     }
     case google::protobuf::Field::TYPE_BYTES: {
-      uint32 buffer32;
+      uint32_t buffer32;
       stream_->ReadVarint32(&buffer32);  // bytes size.
       stream_->ReadString(&result, buffer32);
       break;
@@ -1030,13 +1018,13 @@
          util::converter::IsMap(field, *field_type);
 }
 
-std::pair<int64, int32> ProtoStreamObjectSource::ReadSecondsAndNanos(
+std::pair<int64_t, int32_t> ProtoStreamObjectSource::ReadSecondsAndNanos(
     const google::protobuf::Type& type) const {
-  uint64 seconds = 0;
-  uint32 nanos = 0;
-  uint32 tag = 0;
-  int64 signed_seconds = 0;
-  int32 signed_nanos = 0;
+  uint64_t seconds = 0;
+  uint32_t nanos = 0;
+  uint32_t tag = 0;
+  int64_t signed_seconds = 0;
+  int32_t signed_nanos = 0;
 
   for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) {
     const google::protobuf::Field* field = FindAndVerifyField(type, tag);
@@ -1049,21 +1037,20 @@
     if (field->number() == 1) {
       // read seconds
       stream_->ReadVarint64(&seconds);
-      signed_seconds = bit_cast<int64>(seconds);
+      signed_seconds = bit_cast<int64_t>(seconds);
     } else if (field->number() == 2) {
       // read nanos
       stream_->ReadVarint32(&nanos);
-      signed_nanos = bit_cast<int32>(nanos);
+      signed_nanos = bit_cast<int32_t>(nanos);
     }
   }
-  return std::pair<int64, int32>(signed_seconds, signed_nanos);
+  return std::pair<int64_t, int32_t>(signed_seconds, signed_nanos);
 }
 
 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, "'"));
   }
@@ -1104,7 +1091,7 @@
 
 // TODO(skarvaje): Look into optimizing this by not doing computation on
 // double.
-const std::string FormatNanos(uint32 nanos, bool with_trailing_zeros) {
+const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) {
   if (nanos == 0) {
     return with_trailing_zeros ? ".000" : "";
   }
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
index 807cbf1..60eaf4e 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ b/src/google/protobuf/util/internal/protostream_objectsource.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__
 
+#include <cstdint>
 #include <functional>
 #include <string>
 #include <unordered_map>
@@ -73,6 +74,7 @@
 //   Status status = os.WriteTo(<some ObjectWriter>);
 class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
  public:
+
   struct RenderOptions {
     RenderOptions() = default;
     RenderOptions(const RenderOptions&) = default;
@@ -141,20 +143,20 @@
   // already inside of an object, and skip calling StartObject and EndObject.
   virtual util::Status WriteMessage(const google::protobuf::Type& type,
                                     StringPiece name,
-                                    const uint32 end_tag,
+                                    const uint32_t end_tag,
                                     bool include_start_and_end,
                                     ObjectWriter* ow) const;
 
   // Renders a repeating field (packed or unpacked).  Returns the next tag after
   // reading all sequential repeating elements. The caller should use this tag
   // before reading more tags from the stream.
-  virtual util::StatusOr<uint32> RenderList(
+  virtual util::StatusOr<uint32_t> RenderList(
       const google::protobuf::Field* field, StringPiece name,
-      uint32 list_tag, ObjectWriter* ow) const;
+      uint32_t list_tag, ObjectWriter* ow) const;
 
   // Looks up a field and verify its consistency with wire type in tag.
   const google::protobuf::Field* FindAndVerifyField(
-      const google::protobuf::Type& type, uint32 tag) const;
+      const google::protobuf::Type& type, uint32_t tag) const;
 
   // Renders a field value to the ObjectWriter.
   virtual util::Status RenderField(const google::protobuf::Field* field,
@@ -187,9 +189,9 @@
   // Renders a NWP map.
   // Returns the next tag after reading all map entries. The caller should use
   // this tag before reading more tags from the stream.
-  util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
-                                   StringPiece name, uint32 list_tag,
-                                   ObjectWriter* ow) const;
+  util::StatusOr<uint32_t> RenderMap(const google::protobuf::Field* field,
+                                     StringPiece name, uint32_t list_tag,
+                                     ObjectWriter* ow) const;
 
   // Renders a packed repeating field. A packed field is stored as:
   // {tag length item1 item2 item3} instead of the less efficient
@@ -281,11 +283,11 @@
 
   // Utility to read int64 and int32 values from a message type in stream_.
   // Used for reading google.protobuf.Timestamp and Duration messages.
-  std::pair<int64, int32> ReadSecondsAndNanos(
+  std::pair<int64_t, int32_t> ReadSecondsAndNanos(
       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 100fef9..6ea8b29 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/protostream_objectsource.h>
 
+#include <cstdint>
 #include <memory>
 #include <sstream>
 
@@ -120,9 +121,8 @@
     render_options.use_lower_camel_for_enums = use_lower_camel_for_enums_;
     render_options.use_ints_for_enums = use_ints_for_enums_;
     render_options.preserve_proto_field_names = use_preserve_proto_field_names_;
-    std::unique_ptr<ProtoStreamObjectSource> os(
-        helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor),
-                               render_options));
+    std::unique_ptr<ProtoStreamObjectSource> os(helper_.NewProtoSource(
+        &in_stream, GetTypeUrl(descriptor), render_options));
     os->set_max_recursion_depth(64);
     return os->WriteTo(&mock_);
   }
@@ -130,13 +130,13 @@
   void PrepareExpectingObjectWriterForRepeatedPrimitive() {
     ow_.StartObject("")
         ->StartList("repFix32")
-        ->RenderUint32("", bit_cast<uint32>(3201))
-        ->RenderUint32("", bit_cast<uint32>(0))
-        ->RenderUint32("", bit_cast<uint32>(3202))
+        ->RenderUint32("", bit_cast<uint32_t>(3201))
+        ->RenderUint32("", bit_cast<uint32_t>(0))
+        ->RenderUint32("", bit_cast<uint32_t>(3202))
         ->EndList()
         ->StartList("repU32")
-        ->RenderUint32("", bit_cast<uint32>(3203))
-        ->RenderUint32("", bit_cast<uint32>(0))
+        ->RenderUint32("", bit_cast<uint32_t>(3203))
+        ->RenderUint32("", bit_cast<uint32_t>(0))
         ->EndList()
         ->StartList("repI32")
         ->RenderInt32("", 0)
@@ -153,13 +153,13 @@
         ->RenderInt32("", 3208)
         ->EndList()
         ->StartList("repFix64")
-        ->RenderUint64("", bit_cast<uint64>(int64{6401}))
-        ->RenderUint64("", bit_cast<uint64>(int64{0}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6401}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{0}))
         ->EndList()
         ->StartList("repU64")
-        ->RenderUint64("", bit_cast<uint64>(int64{0}))
-        ->RenderUint64("", bit_cast<uint64>(int64{6402}))
-        ->RenderUint64("", bit_cast<uint64>(int64{6403}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{0}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6402}))
+        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6403}))
         ->EndList()
         ->StartList("repI64")
         ->RenderInt64("", 6404L)
@@ -321,13 +321,13 @@
   primitive.set_bool_(true);
 
   ow_.StartObject("")
-      ->RenderUint32("fix32", bit_cast<uint32>(3201))
-      ->RenderUint32("u32", bit_cast<uint32>(3202))
+      ->RenderUint32("fix32", bit_cast<uint32_t>(3201))
+      ->RenderUint32("u32", bit_cast<uint32_t>(3202))
       ->RenderInt32("i32", 3203)
       ->RenderInt32("sf32", 3204)
       ->RenderInt32("s32", 3205)
-      ->RenderUint64("fix64", bit_cast<uint64>(int64{6401}))
-      ->RenderUint64("u64", bit_cast<uint64>(int64{6402}))
+      ->RenderUint64("fix64", bit_cast<uint64_t>(int64_t{6401}))
+      ->RenderUint64("u64", bit_cast<uint64_t>(int64_t{6402}))
       ->RenderInt64("i64", 6403L)
       ->RenderInt64("sf64", 6404L)
       ->RenderInt64("s64", 6405L)
@@ -425,10 +425,10 @@
       ->RenderBool("", false)
       ->EndList()
       ->StartList("name")
-      ->RenderUint64("", static_cast<uint64>('j'))
-      ->RenderUint64("", static_cast<uint64>('o'))
-      ->RenderUint64("", static_cast<uint64>('h'))
-      ->RenderUint64("", static_cast<uint64>('n'))
+      ->RenderUint64("", static_cast<uint64_t>('j'))
+      ->RenderUint64("", static_cast<uint64_t>('o'))
+      ->RenderUint64("", static_cast<uint64_t>('h'))
+      ->RenderUint64("", static_cast<uint64_t>('n'))
       ->EndList()
       ->RenderString("pseudonym", "phil")
       ->RenderString("pseudonym", "bob")
@@ -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 bccea1f..9878826 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/internal/protostream_objectwriter.h>
 
+#include <cstdint>
 #include <functional>
 #include <stack>
 #include <unordered_map>
@@ -58,7 +59,6 @@
 using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
 using std::placeholders::_1;
 using util::Status;
-using util::error::INVALID_ARGUMENT;
 
 
 ProtoStreamObjectWriter::ProtoStreamObjectWriter(
@@ -129,7 +129,7 @@
 Status GetNanosFromStringPiece(StringPiece s_nanos,
                                const char* parse_failure_message,
                                const char* exceeded_limit_message,
-                               int32* nanos) {
+                               int32_t* nanos) {
   *nanos = 0;
 
   // Count the number of leading 0s and consume them.
@@ -137,30 +137,30 @@
   while (s_nanos.Consume("0")) {
     num_leading_zeros++;
   }
-  int32 i_nanos = 0;
+  int32_t i_nanos = 0;
   // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to
   // "0." + s_nanos.ToString() seconds. An int32 is used for the
   // 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) {
     // 'scale' is the number of digits to the right of the decimal
     // point in "0." + s_nanos.ToString()
-    int32 scale = num_leading_zeros + s_nanos.size();
+    int32_t scale = num_leading_zeros + s_nanos.size();
     // 'conversion' converts i_nanos into nanoseconds.
     // conversion = kNanosPerSecond / static_cast<int32>(std::pow(10, scale))
     // For efficiency, we precompute the conversion factor.
-    int32 conversion = 0;
+    int32_t conversion = 0;
     switch (scale) {
       case 1:
         conversion = 100000000;
@@ -190,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;
   }
@@ -437,7 +436,7 @@
     StrAppend(&value_storage_, value_.str());
     value_ = DataPiece(value_storage_, value_.use_strict_base64_decoding());
   } else if (value_.type() == DataPiece::TYPE_BYTES) {
-    value_storage_ = value_.ToBytes().ValueOrDie();
+    value_storage_ = value_.ToBytes().value();
     value_ =
         DataPiece(value_storage_, true, value_.use_strict_base64_decoding());
   }
@@ -921,7 +920,7 @@
   switch (data.type()) {
     case DataPiece::TYPE_INT32: {
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<int32> int_value = data.ToInt32();
+        util::StatusOr<int32_t> int_value = data.ToInt32();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -934,7 +933,7 @@
     }
     case DataPiece::TYPE_UINT32: {
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<uint32> int_value = data.ToUint32();
+        util::StatusOr<uint32_t> int_value = data.ToUint32();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value",
@@ -949,7 +948,7 @@
       // If the option to treat integers as strings is set, then render them as
       // strings. Otherwise, fallback to rendering them as double.
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<int64> int_value = data.ToInt64();
+        util::StatusOr<int64_t> int_value = data.ToInt64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value", DataPiece(StrCat(int_value.value()), true));
@@ -963,7 +962,7 @@
       // If the option to treat integers as strings is set, then render them as
       // strings. Otherwise, fallback to rendering them as double.
       if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<uint64> int_value = data.ToUint64();
+        util::StatusOr<uint64_t> int_value = data.ToUint64();
         if (int_value.ok()) {
           ow->ProtoWriter::RenderDataPiece(
               "string_value", DataPiece(StrCat(int_value.value()), true));
@@ -1012,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);
@@ -1025,9 +1024,9 @@
                                                 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());
@@ -1036,7 +1035,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));
   }
 
 
@@ -1056,9 +1055,9 @@
                                                 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
@@ -1072,16 +1071,16 @@
                                                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;
@@ -1092,13 +1091,13 @@
 
   StringPiece s_secs, s_nanos;
   SplitSecondsAndNanos(value, &s_secs, &s_nanos);
-  uint64 unsigned_seconds;
+  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 nanos = 0;
+  int32_t nanos = 0;
   Status nanos_status = GetNanosFromStringPiece(
       s_nanos, "Invalid duration format, failed to parse nano seconds",
       "Duration value exceeds limits", &nanos);
@@ -1107,11 +1106,10 @@
   }
   nanos = sign * nanos;
 
-  int64 seconds = sign * unsigned_seconds;
+  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/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
index 1816b68..17ff6dd 100644
--- a/src/google/protobuf/util/internal/utility.cc
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -32,6 +32,7 @@
 
 #include <algorithm>
 #include <cmath>
+#include <cstdint>
 #include <limits>
 
 #include <google/protobuf/stubs/callback.h>
@@ -63,9 +64,9 @@
   return GetBoolFromAny(opt->value());
 }
 
-int64 GetInt64OptionOrDefault(
+int64_t GetInt64OptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64 default_value) {
+    StringPiece option_name, int64_t default_value) {
   const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
   if (opt == nullptr) {
     return default_value;
@@ -106,7 +107,7 @@
   return b.value();
 }
 
-int64 GetInt64FromAny(const google::protobuf::Any& any) {
+int64_t GetInt64FromAny(const google::protobuf::Any& any) {
   google::protobuf::Int64Value i;
   ParseFromAny(any.value(), &i);
   return i.value();
@@ -179,7 +180,7 @@
 }
 
 const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
-    const google::protobuf::Type* type, int32 number) {
+    const google::protobuf::Type* type, int32_t number) {
   if (type != nullptr) {
     for (int i = 0; i < type->fields_size(); ++i) {
       const google::protobuf::Field& field = type->fields(i);
@@ -205,7 +206,7 @@
 }
 
 const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
-    const google::protobuf::Enum* enum_type, int32 value) {
+    const google::protobuf::Enum* enum_type, int32_t value) {
   if (enum_type != nullptr) {
     for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
       const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
index 965579a..b689e84 100644
--- a/src/google/protobuf/util/internal/utility.h
+++ b/src/google/protobuf/util/internal/utility.h
@@ -31,6 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
 #define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__
 
+#include <cstdint>
 #include <memory>
 #include <string>
 #include <utility>
@@ -53,7 +54,7 @@
 namespace converter {
 
 // Size of "type.googleapis.com"
-static const int64 kTypeUrlSize = 19;
+static const int64_t kTypeUrlSize = 19;
 
 // Finds the tech option identified by option_name. Parses the boolean value and
 // returns it.
@@ -64,9 +65,9 @@
 
 // Returns int64 option value. If the option isn't found, returns the
 // default_value.
-PROTOBUF_EXPORT int64 GetInt64OptionOrDefault(
+PROTOBUF_EXPORT int64_t GetInt64OptionOrDefault(
     const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64 default_value);
+    StringPiece option_name, int64_t default_value);
 
 // Returns double option value. If the option isn't found, returns the
 // default_value.
@@ -87,7 +88,7 @@
 PROTOBUF_EXPORT bool GetBoolFromAny(const google::protobuf::Any& any);
 
 // Returns int64 value contained in Any type.
-PROTOBUF_EXPORT int64 GetInt64FromAny(const google::protobuf::Any& any);
+PROTOBUF_EXPORT int64_t GetInt64FromAny(const google::protobuf::Any& any);
 
 // Returns double value contained in Any type.
 PROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any);
@@ -127,7 +128,7 @@
 
 // Similar to FindFieldInTypeOrNull, but this looks up fields by number.
 const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
-    const google::protobuf::Type* type, int32 number);
+    const google::protobuf::Type* type, int32_t number);
 
 // Finds and returns the EnumValue identified by enum_name in the passed tech
 // Enum object. Returns nullptr if none found.
@@ -137,7 +138,7 @@
 // Finds and returns the EnumValue identified by value in the passed tech
 // Enum object. Returns nullptr if none found.
 const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
-    const google::protobuf::Enum* enum_type, int32 value);
+    const google::protobuf::Enum* enum_type, int32_t value);
 
 // Finds and returns the EnumValue identified by enum_name without underscore in
 // the passed tech Enum object. Returns nullptr if none found.
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index eb81b65..3597f9e 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -140,25 +140,22 @@
     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 +268,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.h b/src/google/protobuf/util/json_util.h
index 9954587..73f2783 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -36,6 +36,7 @@
 #include <google/protobuf/message.h>
 #include <google/protobuf/util/type_resolver.h>
 #include <google/protobuf/stubs/bytestream.h>
+#include <google/protobuf/stubs/status.h>
 #include <google/protobuf/stubs/strutil.h>
 
 #include <google/protobuf/port_def.inc>
@@ -93,11 +94,11 @@
 // simple wrapper of BinaryToJsonString(). It will use the DescriptorPool of the
 // passed-in message to resolve Any types.
 PROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message,
-                                                   std::string* output,
-                                                   const JsonOptions& options);
+                                                 std::string* output,
+                                                 const JsonOptions& options);
 
 inline util::Status MessageToJsonString(const Message& message,
-                                          std::string* output) {
+                                        std::string* output) {
   return MessageToJsonString(message, output, JsonOptions());
 }
 
@@ -108,7 +109,7 @@
     StringPiece input, Message* message, const JsonParseOptions& options);
 
 inline util::Status JsonStringToMessage(StringPiece input,
-                                          Message* message) {
+                                        Message* message) {
   return JsonStringToMessage(input, message, JsonParseOptions());
 }
 
@@ -123,10 +124,10 @@
     io::ZeroCopyInputStream* binary_input,
     io::ZeroCopyOutputStream* json_output, const JsonPrintOptions& options);
 
-inline util::Status BinaryToJsonStream(
-    TypeResolver* resolver, const std::string& type_url,
-    io::ZeroCopyInputStream* binary_input,
-    io::ZeroCopyOutputStream* json_output) {
+inline util::Status BinaryToJsonStream(TypeResolver* resolver,
+                                       const std::string& type_url,
+                                       io::ZeroCopyInputStream* binary_input,
+                                       io::ZeroCopyOutputStream* json_output) {
   return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
                             JsonPrintOptions());
 }
@@ -137,9 +138,9 @@
     const JsonPrintOptions& options);
 
 inline util::Status BinaryToJsonString(TypeResolver* resolver,
-                                         const std::string& type_url,
-                                         const std::string& binary_input,
-                                         std::string* json_output) {
+                                       const std::string& type_url,
+                                       const std::string& binary_input,
+                                       std::string* json_output) {
   return BinaryToJsonString(resolver, type_url, binary_input, json_output,
                             JsonPrintOptions());
 }
@@ -168,9 +169,9 @@
     const JsonParseOptions& options);
 
 inline util::Status JsonToBinaryString(TypeResolver* resolver,
-                                         const std::string& type_url,
-                                         StringPiece json_input,
-                                         std::string* binary_output) {
+                                       const std::string& type_url,
+                                       StringPiece json_input,
+                                       std::string* binary_output) {
   return JsonToBinaryString(resolver, type_url, json_input, binary_output,
                             JsonParseOptions());
 }
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
index 9851cc5..c5d8315 100644
--- a/src/google/protobuf/util/json_util_test.cc
+++ b/src/google/protobuf/util/json_util_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/json_util.h>
 
+#include <cstdint>
 #include <list>
 #include <string>
 
@@ -524,7 +525,7 @@
  private:
   std::list<Segment> segments_;
   Segment last_segment_;
-  int64 byte_count_;
+  int64_t byte_count_;
 };
 
 // This test splits the output buffer and also the input data into multiple
@@ -632,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/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index c3c24da..4815178 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -36,7 +36,9 @@
 
 #include <algorithm>
 #include <cstddef>
+#include <cstdint>
 #include <functional>
+#include <limits>
 #include <memory>
 #include <utility>
 
@@ -71,7 +73,7 @@
   NumDiffsReporter() : num_diffs_(0) {}
 
   // Returns the total number of diffs.
-  int32 GetNumDiffs() const { return num_diffs_; }
+  int32_t GetNumDiffs() const { return num_diffs_; }
   void Reset() { num_diffs_ = 0; }
 
   // Report that a field has been added into Message2.
@@ -99,7 +101,7 @@
   }
 
  private:
-  int32 num_diffs_;
+  int32_t num_diffs_;
 };
 
 // When comparing a repeated field as map, MultipleFieldMapKeyComparator can
@@ -145,19 +147,17 @@
       int path_index) const {
     const FieldDescriptor* field = key_field_path[path_index];
     std::vector<SpecificField> current_parent_fields(parent_fields);
-    if (path_index == static_cast<int64>(key_field_path.size() - 1)) {
-      if (field->is_repeated()) {
-        if (!message_differencer_->CompareRepeatedField(
-                message1, message2, field, &current_parent_fields)) {
-          return false;
-        }
+    if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) {
+      if (field->is_map()) {
+        return message_differencer_->CompareMapField(message1, message2, field,
+                                                     &current_parent_fields);
+      } else if (field->is_repeated()) {
+        return message_differencer_->CompareRepeatedField(
+            message1, message2, field, &current_parent_fields);
       } else {
-        if (!message_differencer_->CompareFieldValueUsingParentFields(
-                message1, message2, field, -1, -1, &current_parent_fields)) {
-          return false;
-        }
+        return message_differencer_->CompareFieldValueUsingParentFields(
+            message1, message2, field, -1, -1, &current_parent_fields);
       }
-      return true;
     } else {
       const Reflection* reflection1 = message1.GetReflection();
       const Reflection* reflection2 = message2.GetReflection();
@@ -325,14 +325,7 @@
   const MapKeyComparator* key_comparator = GetMapKeyComparator(field);
   GOOGLE_CHECK(key_comparator == NULL)
       << "Cannot treat this repeated field as both MAP and " << new_comparison
-      << " for"
-      << " comparison.  Field name is: " << field->full_name();
-  GOOGLE_CHECK(repeated_field_comparisons_.find(field) ==
-            repeated_field_comparisons_.end() ||
-        repeated_field_comparisons_[field] == new_comparison)
-      << "Cannot treat the same field as both "
-      << repeated_field_comparisons_[field] << " and " << new_comparison
-      << ". Field name is: " << field->full_name();
+      << " for comparison.  Field name is: " << field->full_name();
 }
 
 void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) {
@@ -835,24 +828,17 @@
 
     bool fieldDifferent = false;
     assert(field1 != NULL);
-    if (field1->is_repeated()) {
+    if (field1->is_map()) {
+      fieldDifferent =
+          !CompareMapField(message1, message2, field1, parent_fields);
+    } else if (field1->is_repeated()) {
       fieldDifferent =
           !CompareRepeatedField(message1, message2, field1, parent_fields);
-      if (fieldDifferent) {
-        if (reporter_ == NULL) return false;
-        isDifferent = true;
-      }
     } else {
       fieldDifferent = !CompareFieldValueUsingParentFields(
           message1, message2, field1, -1, -1, parent_fields);
 
-      // If we have found differences, either report them or terminate if
-      // no reporter is present.
-      if (fieldDifferent && reporter_ == NULL) {
-        return false;
-      }
-
-      if (reporter_ != NULL) {
+      if (reporter_ != nullptr) {
         SpecificField specific_field;
         specific_field.field = field1;
         parent_fields->push_back(specific_field);
@@ -865,6 +851,10 @@
         parent_fields->pop_back();
       }
     }
+    if (fieldDifferent) {
+      if (reporter_ == nullptr) return false;
+      isDifferent = true;
+    }
     // Increment the field indices.
     ++field_index1;
     ++field_index2;
@@ -920,6 +910,11 @@
     const Message& message1, const Message& message2,
     const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields,
     DefaultFieldComparator* comparator) {
+  GOOGLE_DCHECK_EQ(nullptr, reporter_);
+  GOOGLE_DCHECK(map_field->is_map());
+  GOOGLE_DCHECK(map_field_key_comparator_.find(map_field) ==
+         map_field_key_comparator_.end());
+  GOOGLE_DCHECK_EQ(repeated_field_comparison_, AS_LIST);
   const Reflection* reflection1 = message1.GetReflection();
   const Reflection* reflection2 = message2.GetReflection();
   const int count1 = reflection1->MapSize(message1, map_field);
@@ -931,18 +926,28 @@
   if (count1 > count2) {
     return false;
   }
+
+  // First pass: check whether the same keys are present.
+  for (MapIterator it = reflection1->MapBegin(const_cast<Message*>(&message1),
+                                              map_field),
+                   it_end = reflection1->MapEnd(const_cast<Message*>(&message1),
+                                                map_field);
+       it != it_end; ++it) {
+    if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {
+      return false;
+    }
+  }
+
+  // Second pass: compare values for matching keys.
   const FieldDescriptor* val_des = map_field->message_type()->map_value();
   switch (val_des->cpp_type()) {
 #define HANDLE_TYPE(CPPTYPE, METHOD, COMPAREMETHOD)                           \
   case FieldDescriptor::CPPTYPE_##CPPTYPE: {                                  \
     for (MapIterator it = reflection1->MapBegin(                              \
-             const_cast<Message*>(&message1), map_field);                     \
-         it !=                                                                \
-         reflection1->MapEnd(const_cast<Message*>(&message1), map_field);     \
-         ++it) {                                                              \
-      if (!reflection2->ContainsMapKey(message2, map_field, it.GetKey())) {   \
-        return false;                                                         \
-      }                                                                       \
+                         const_cast<Message*>(&message1), map_field),         \
+                     it_end = reflection1->MapEnd(                            \
+                         const_cast<Message*>(&message1), map_field);         \
+         it != it_end; ++it) {                                                \
       MapValueConstRef value2;                                                \
       reflection2->LookupMapValue(message2, map_field, it.GetKey(), &value2); \
       if (!comparator->Compare##COMPAREMETHOD(*val_des,                       \
@@ -992,17 +997,19 @@
   return true;
 }
 
-bool MessageDifferencer::CompareRepeatedField(
+bool MessageDifferencer::CompareMapField(
     const Message& message1, const Message& message2,
     const FieldDescriptor* repeated_field,
     std::vector<SpecificField>* parent_fields) {
+  GOOGLE_DCHECK(repeated_field->is_map());
+
   // the input FieldDescriptor is guaranteed to be repeated field.
   const Reflection* reflection1 = message1.GetReflection();
   const Reflection* reflection2 = message2.GetReflection();
 
   // When both map fields are on map, do not sync to repeated field.
   // TODO(jieluo): Add support for reporter
-  if (repeated_field->is_map() && reporter_ == nullptr &&
+  if (reporter_ == nullptr &&
       // Users didn't set custom map field key comparator
       map_field_key_comparator_.find(repeated_field) ==
           map_field_key_comparator_.end() &&
@@ -1042,6 +1049,26 @@
     }
   }
 
+  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
+}
+
+bool MessageDifferencer::CompareRepeatedField(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* repeated_field,
+    std::vector<SpecificField>* parent_fields) {
+  GOOGLE_DCHECK(!repeated_field->is_map());
+  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
+}
+
+bool MessageDifferencer::CompareRepeatedRep(
+    const Message& message1, const Message& message2,
+    const FieldDescriptor* repeated_field,
+    std::vector<SpecificField>* parent_fields) {
+  // the input FieldDescriptor is guaranteed to be repeated field.
+  GOOGLE_DCHECK(repeated_field->is_repeated());
+  const Reflection* reflection1 = message1.GetReflection();
+  const Reflection* reflection2 = message2.GetReflection();
+
   const int count1 = reflection1->FieldSize(message1, repeated_field);
   const int count2 = reflection2->FieldSize(message2, repeated_field);
   const bool treated_as_subset = IsTreatedAsSubset(repeated_field);
@@ -1723,9 +1750,9 @@
   Reporter* reporter = reporter_;
   reporter_ = NULL;
   NumDiffsReporter num_diffs_reporter;
-  std::vector<int32> num_diffs_list1;
+  std::vector<int32_t> num_diffs_list1;
   if (is_treated_as_smart_set) {
-    num_diffs_list1.assign(count1, kint32max);
+    num_diffs_list1.assign(count1, std::numeric_limits<int32_t>::max());
   }
 
   bool success = true;
@@ -1793,7 +1820,7 @@
           } else if (repeated_field->cpp_type() ==
                      FieldDescriptor::CPPTYPE_MESSAGE) {
             // Replace with the one with fewer diffs.
-            const int32 num_diffs = num_diffs_reporter.GetNumDiffs();
+            const int32_t num_diffs = num_diffs_reporter.GetNumDiffs();
             if (num_diffs < num_diffs_list1[i]) {
               // If j has been already matched to some element, ensure the
               // current num_diffs is smaller.
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index 61d9f9b..943a0db 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -431,7 +431,7 @@
   // + n^3) in which n^3 is the time complexity of the maximum matching
   // algorithm.
   //
-  // REQUIRES:  field->is_repeated() and field not registered with TreatAsList
+  // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
   void TreatAsSet(const FieldDescriptor* field);
   void TreatAsSmartSet(const FieldDescriptor* field);
 
@@ -439,7 +439,7 @@
   // diffing purposes, so different orderings of the same elements will NOT be
   // considered equal.
   //
-  // REQUIRED: field->is_repeated() and field not registered with TreatAsSet
+  // REQUIRES: field->is_repeated() and field not registered with TreatAsMap*
   void TreatAsList(const FieldDescriptor* field);
   // Note that the complexity is similar to treating as SET.
   void TreatAsSmartList(const FieldDescriptor* field);
@@ -708,7 +708,7 @@
   };
 
  private:
-  friend class DefaultFieldComparator;
+  friend class SimpleFieldComparator;
 
   // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator.
   // Implementation of this class needs to do field value comparison which
@@ -779,7 +779,20 @@
                             const FieldDescriptor* field,
                             std::vector<SpecificField>* parent_fields);
 
-  // Compare the map fields using map reflection instead of sync to repeated.
+  // Compares map fields, and report the error.
+  bool CompareMapField(const Message& message1, const Message& message2,
+                       const FieldDescriptor* field,
+                       std::vector<SpecificField>* parent_fields);
+
+  // Helper for CompareRepeatedField and CompareMapField: compares and reports
+  // differences element-wise. This is the implementation for non-map fields,
+  // and can also compare map fields by using the underlying representation.
+  bool CompareRepeatedRep(const Message& message1, const Message& message2,
+                          const FieldDescriptor* field,
+                          std::vector<SpecificField>* parent_fields);
+
+  // Helper for CompareMapField: compare the map fields using map reflection
+  // instead of sync to repeated.
   bool CompareMapFieldByMapReflection(const Message& message1,
                                       const Message& message2,
                                       const FieldDescriptor* field,
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index 5a333b3..fbbcd3c 100644
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -1060,6 +1060,42 @@
   EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2));
 }
 
+TEST(MessageDifferencerTest, RepeatedFieldTreatmentChangeListToSet) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  msg1.add_rv(1);
+  msg1.add_rv(2);
+  msg2.add_rv(2);
+  msg2.add_rv(1);
+
+  util::MessageDifferencer differencer;
+  differencer.TreatAsList(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+  differencer.TreatAsSet(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+
+  EXPECT_TRUE(differencer.Compare(msg1, msg2));
+}
+
+TEST(MessageDifferencerTest, RepeatedFieldTreatmentChangeSetToList) {
+  protobuf_unittest::TestDiffMessage msg1;
+  protobuf_unittest::TestDiffMessage msg2;
+
+  msg1.add_rv(1);
+  msg1.add_rv(2);
+  msg2.add_rv(2);
+  msg2.add_rv(1);
+
+  util::MessageDifferencer differencer;
+  differencer.TreatAsSet(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+  differencer.TreatAsList(
+      protobuf_unittest::TestDiffMessage::descriptor()->FindFieldByName("rv"));
+
+  EXPECT_FALSE(differencer.Compare(msg1, msg2));
+}
+
 TEST(MessageDifferencerTest, RepeatedFieldSmartListTest) {
   // Create the testing protos
   protobuf_unittest::TestDiffMessage msg1;
@@ -3339,7 +3375,11 @@
 
   util::MessageDifferencer differencer;
   differencer.set_scope(util::MessageDifferencer::PARTIAL);
-  EXPECT_TRUE(differencer.Compare(map1, map2));
+  // TODO(jieluo): Remove the round trip
+  std::string serialized_value;
+  map1.SerializeToString(&serialized_value);
+  map1.ParseFromString(serialized_value);
+  EXPECT_FALSE(differencer.Compare(map1, map2));
 }
 
 TEST_F(ComparisonTest, MapEntryMissingEmptyFieldIsOkTest) {
diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
index 08c6e9c..6b9c665 100644
--- a/src/google/protobuf/util/time_util.cc
+++ b/src/google/protobuf/util/time_util.cc
@@ -30,6 +30,8 @@
 
 #include <google/protobuf/util/time_util.h>
 
+#include <cstdint>
+
 #include <google/protobuf/stubs/stringprintf.h>
 #include <google/protobuf/stubs/strutil.h>
 #include <google/protobuf/duration.pb.h>
@@ -57,10 +59,10 @@
 static const int kSecondsPerHour = 3600;
 
 template <typename T>
-T CreateNormalized(int64 seconds, int64 nanos);
+T CreateNormalized(int64_t seconds, int64_t nanos);
 
 template <>
-Timestamp CreateNormalized(int64 seconds, int64 nanos) {
+Timestamp CreateNormalized(int64_t seconds, int64_t nanos) {
   // Make sure nanos is in the range.
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     seconds += nanos / kNanosPerSecond;
@@ -75,12 +77,12 @@
          seconds <= TimeUtil::kTimestampMaxSeconds);
   Timestamp result;
   result.set_seconds(seconds);
-  result.set_nanos(static_cast<int32>(nanos));
+  result.set_nanos(static_cast<int32_t>(nanos));
   return result;
 }
 
 template <>
-Duration CreateNormalized(int64 seconds, int64 nanos) {
+Duration CreateNormalized(int64_t seconds, int64_t nanos) {
   // Make sure nanos is in the range.
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     seconds += nanos / kNanosPerSecond;
@@ -98,13 +100,13 @@
          seconds <= TimeUtil::kDurationMaxSeconds);
   Duration result;
   result.set_seconds(seconds);
-  result.set_nanos(static_cast<int32>(nanos));
+  result.set_nanos(static_cast<int32_t>(nanos));
   return result;
 }
 
 // Format nanoseconds with either 3, 6, or 9 digits depending on the required
 // precision to represent the exact value.
-std::string FormatNanos(int32 nanos) {
+std::string FormatNanos(int32_t nanos) {
   if (nanos % kNanosPerMillisecond == 0) {
     return StringPrintf("%03d", nanos / kNanosPerMillisecond);
   } else if (nanos % kNanosPerMicrosecond == 0) {
@@ -127,9 +129,9 @@
 }
 
 // Truncates the remainder part after division.
-int64 RoundTowardZero(int64 value, int64 divider) {
-  int64 result = value / divider;
-  int64 remainder = value % divider;
+int64_t RoundTowardZero(int64_t value, int64_t divider) {
+  int64_t result = value / divider;
+  int64_t remainder = value % divider;
   // Before C++11, the sign of the remainder is implementation dependent if
   // any of the operands is negative. Here we try to enforce C++11's "rounded
   // toward zero" semantics. For example, for (-5) / 2 an implementation may
@@ -146,10 +148,10 @@
 // Actually define these static const integers. Required by C++ standard (but
 // some compilers don't like it).
 #ifndef _MSC_VER
-const int64 TimeUtil::kTimestampMinSeconds;
-const int64 TimeUtil::kTimestampMaxSeconds;
-const int64 TimeUtil::kDurationMaxSeconds;
-const int64 TimeUtil::kDurationMinSeconds;
+const int64_t TimeUtil::kTimestampMinSeconds;
+const int64_t TimeUtil::kTimestampMaxSeconds;
+const int64_t TimeUtil::kDurationMaxSeconds;
+const int64_t TimeUtil::kDurationMinSeconds;
 #endif  // !_MSC_VER
 
 std::string TimeUtil::ToString(const Timestamp& timestamp) {
@@ -157,8 +159,8 @@
 }
 
 bool TimeUtil::FromString(const std::string& value, Timestamp* timestamp) {
-  int64 seconds;
-  int32 nanos;
+  int64_t seconds;
+  int32_t nanos;
   if (!ParseTime(value, &seconds, &nanos)) {
     return false;
   }
@@ -167,8 +169,8 @@
 }
 
 Timestamp TimeUtil::GetCurrentTime() {
-  int64 seconds;
-  int32 nanos;
+  int64_t seconds;
+  int32_t nanos;
   CurrentTime(&seconds, &nanos);
   return CreateNormalized<Timestamp>(seconds, nanos);
 }
@@ -177,8 +179,8 @@
 
 std::string TimeUtil::ToString(const Duration& duration) {
   std::string result;
-  int64 seconds = duration.seconds();
-  int32 nanos = duration.nanos();
+  int64_t seconds = duration.seconds();
+  int32_t nanos = duration.nanos();
   if (seconds < 0 || nanos < 0) {
     result += "-";
     seconds = -seconds;
@@ -192,8 +194,8 @@
   return result;
 }
 
-static int64 Pow(int64 x, int y) {
-  int64 result = 1;
+static int64_t Pow(int64_t x, int y) {
+  int64_t result = 1;
   for (int i = 0; i < y; ++i) {
     result *= x;
   }
@@ -218,11 +220,11 @@
     nanos_part = value.substr(pos + 1, value.length() - pos - 2);
   }
   char* end;
-  int64 seconds = strto64(seconds_part.c_str(), &end, 10);
+  int64_t seconds = strto64(seconds_part.c_str(), &end, 10);
   if (end != seconds_part.c_str() + seconds_part.length()) {
     return false;
   }
-  int64 nanos = strto64(nanos_part.c_str(), &end, 10);
+  int64_t nanos = strto64(nanos_part.c_str(), &end, 10);
   if (end != nanos_part.c_str() + nanos_part.length()) {
     return false;
   }
@@ -233,106 +235,106 @@
     nanos = -nanos;
   }
   duration->set_seconds(seconds);
-  duration->set_nanos(static_cast<int32>(nanos));
+  duration->set_nanos(static_cast<int32_t>(nanos));
   return true;
 }
 
-Duration TimeUtil::NanosecondsToDuration(int64 nanos) {
+Duration TimeUtil::NanosecondsToDuration(int64_t nanos) {
   return CreateNormalized<Duration>(nanos / kNanosPerSecond,
                                     nanos % kNanosPerSecond);
 }
 
-Duration TimeUtil::MicrosecondsToDuration(int64 micros) {
+Duration TimeUtil::MicrosecondsToDuration(int64_t micros) {
   return CreateNormalized<Duration>(
       micros / kMicrosPerSecond,
       (micros % kMicrosPerSecond) * kNanosPerMicrosecond);
 }
 
-Duration TimeUtil::MillisecondsToDuration(int64 millis) {
+Duration TimeUtil::MillisecondsToDuration(int64_t millis) {
   return CreateNormalized<Duration>(
       millis / kMillisPerSecond,
       (millis % kMillisPerSecond) * kNanosPerMillisecond);
 }
 
-Duration TimeUtil::SecondsToDuration(int64 seconds) {
+Duration TimeUtil::SecondsToDuration(int64_t seconds) {
   return CreateNormalized<Duration>(seconds, 0);
 }
 
-Duration TimeUtil::MinutesToDuration(int64 minutes) {
+Duration TimeUtil::MinutesToDuration(int64_t minutes) {
   return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
 }
 
-Duration TimeUtil::HoursToDuration(int64 hours) {
+Duration TimeUtil::HoursToDuration(int64_t hours) {
   return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
 }
 
-int64 TimeUtil::DurationToNanoseconds(const Duration& duration) {
+int64_t TimeUtil::DurationToNanoseconds(const Duration& duration) {
   return duration.seconds() * kNanosPerSecond + duration.nanos();
 }
 
-int64 TimeUtil::DurationToMicroseconds(const Duration& duration) {
+int64_t TimeUtil::DurationToMicroseconds(const Duration& duration) {
   return duration.seconds() * kMicrosPerSecond +
          RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
 }
 
-int64 TimeUtil::DurationToMilliseconds(const Duration& duration) {
+int64_t TimeUtil::DurationToMilliseconds(const Duration& duration) {
   return duration.seconds() * kMillisPerSecond +
          RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
 }
 
-int64 TimeUtil::DurationToSeconds(const Duration& duration) {
+int64_t TimeUtil::DurationToSeconds(const Duration& duration) {
   return duration.seconds();
 }
 
-int64 TimeUtil::DurationToMinutes(const Duration& duration) {
+int64_t TimeUtil::DurationToMinutes(const Duration& duration) {
   return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
 }
 
-int64 TimeUtil::DurationToHours(const Duration& duration) {
+int64_t TimeUtil::DurationToHours(const Duration& duration) {
   return RoundTowardZero(duration.seconds(), kSecondsPerHour);
 }
 
-Timestamp TimeUtil::NanosecondsToTimestamp(int64 nanos) {
+Timestamp TimeUtil::NanosecondsToTimestamp(int64_t nanos) {
   return CreateNormalized<Timestamp>(nanos / kNanosPerSecond,
                                      nanos % kNanosPerSecond);
 }
 
-Timestamp TimeUtil::MicrosecondsToTimestamp(int64 micros) {
+Timestamp TimeUtil::MicrosecondsToTimestamp(int64_t micros) {
   return CreateNormalized<Timestamp>(
       micros / kMicrosPerSecond,
       micros % kMicrosPerSecond * kNanosPerMicrosecond);
 }
 
-Timestamp TimeUtil::MillisecondsToTimestamp(int64 millis) {
+Timestamp TimeUtil::MillisecondsToTimestamp(int64_t millis) {
   return CreateNormalized<Timestamp>(
       millis / kMillisPerSecond,
       millis % kMillisPerSecond * kNanosPerMillisecond);
 }
 
-Timestamp TimeUtil::SecondsToTimestamp(int64 seconds) {
+Timestamp TimeUtil::SecondsToTimestamp(int64_t seconds) {
   return CreateNormalized<Timestamp>(seconds, 0);
 }
 
-int64 TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
   return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
 }
 
-int64 TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
   return timestamp.seconds() * kMicrosPerSecond +
          RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
 }
 
-int64 TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
   return timestamp.seconds() * kMillisPerSecond +
          RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
 }
 
-int64 TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
+int64_t TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
   return timestamp.seconds();
 }
 
 Timestamp TimeUtil::TimeTToTimestamp(time_t value) {
-  return CreateNormalized<Timestamp>(static_cast<int64>(value), 0);
+  return CreateNormalized<Timestamp>(static_cast<int64_t>(value), 0);
 }
 
 time_t TimeUtil::TimestampToTimeT(const Timestamp& value) {
@@ -382,19 +384,20 @@
 void ToUint128(const Duration& value, uint128* result, bool* negative) {
   if (value.seconds() < 0 || value.nanos() < 0) {
     *negative = true;
-    *result = static_cast<uint64>(-value.seconds());
-    *result = *result * kNanosPerSecond + static_cast<uint32>(-value.nanos());
+    *result = static_cast<uint64_t>(-value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32_t>(-value.nanos());
   } else {
     *negative = false;
-    *result = static_cast<uint64>(value.seconds());
-    *result = *result * kNanosPerSecond + static_cast<uint32>(value.nanos());
+    *result = static_cast<uint64_t>(value.seconds());
+    *result = *result * kNanosPerSecond + static_cast<uint32_t>(value.nanos());
   }
 }
 
 void ToDuration(const uint128& value, bool negative, Duration* duration) {
-  int64 seconds =
-      static_cast<int64>(Uint128Low64(value / kNanosPerSecond));
-  int32 nanos = static_cast<int32>(Uint128Low64(value % kNanosPerSecond));
+  int64_t seconds =
+      static_cast<int64_t>(Uint128Low64(value / kNanosPerSecond));
+  int32_t nanos =
+      static_cast<int32_t>(Uint128Low64(value % kNanosPerSecond));
   if (negative) {
     seconds = -seconds;
     nanos = -nanos;
@@ -416,15 +419,15 @@
   return d1;
 }
 
-Duration& operator*=(Duration& d, int64 r) {  // NOLINT
+Duration& operator*=(Duration& d, int64_t r) {  // NOLINT
   bool negative;
   uint128 value;
   ToUint128(d, &value, &negative);
   if (r > 0) {
-    value *= static_cast<uint64>(r);
+    value *= static_cast<uint64_t>(r);
   } else {
     negative = !negative;
-    value *= static_cast<uint64>(-r);
+    value *= static_cast<uint64_t>(-r);
   }
   ToDuration(value, negative, &d);
   return d;
@@ -432,8 +435,8 @@
 
 Duration& operator*=(Duration& d, double r) {  // NOLINT
   double result = (d.seconds() * 1.0 + 1.0 * d.nanos() / kNanosPerSecond) * r;
-  int64 seconds = static_cast<int64>(result);
-  int32 nanos = static_cast<int32>((result - seconds) * kNanosPerSecond);
+  int64_t seconds = static_cast<int64_t>(result);
+  int32_t nanos = static_cast<int32_t>((result - seconds) * kNanosPerSecond);
   // Note that we normalize here not just because nanos can have a different
   // sign from seconds but also that nanos can be any arbitrary value when
   // overflow happens (i.e., the result is a much larger value than what
@@ -442,15 +445,15 @@
   return d;
 }
 
-Duration& operator/=(Duration& d, int64 r) {  // NOLINT
+Duration& operator/=(Duration& d, int64_t r) {  // NOLINT
   bool negative;
   uint128 value;
   ToUint128(d, &value, &negative);
   if (r > 0) {
-    value /= static_cast<uint64>(r);
+    value /= static_cast<uint64_t>(r);
   } else {
     negative = !negative;
-    value /= static_cast<uint64>(-r);
+    value /= static_cast<uint64_t>(-r);
   }
   ToDuration(value, negative, &d);
   return d;
@@ -476,12 +479,12 @@
   return d1;
 }
 
-int64 operator/(const Duration& d1, const Duration& d2) {
+int64_t operator/(const Duration& d1, const Duration& d2) {
   bool negative1, negative2;
   uint128 value1, value2;
   ToUint128(d1, &value1, &negative1);
   ToUint128(d2, &value2, &negative2);
-  int64 result = Uint128Low64(value1 / value2);
+  int64_t result = Uint128Low64(value1 / value2);
   if (negative1 != negative2) {
     result = -result;
   }
diff --git a/src/google/protobuf/util/time_util.h b/src/google/protobuf/util/time_util.h
index 95063fc..96b1aac 100644
--- a/src/google/protobuf/util/time_util.h
+++ b/src/google/protobuf/util/time_util.h
@@ -33,6 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
 #define GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
 
+#include <cstdint>
 #include <ctime>
 #include <ostream>
 #include <string>
@@ -67,11 +68,11 @@
   // The min/max Timestamp/Duration values we support.
   //
   // For "0001-01-01T00:00:00Z".
-  static const int64 kTimestampMinSeconds = -62135596800LL;
+  static const int64_t kTimestampMinSeconds = -62135596800LL;
   // For "9999-12-31T23:59:59.999999999Z".
-  static const int64 kTimestampMaxSeconds = 253402300799LL;
-  static const int64 kDurationMinSeconds = -315576000000LL;
-  static const int64 kDurationMaxSeconds = 315576000000LL;
+  static const int64_t kTimestampMaxSeconds = 253402300799LL;
+  static const int64_t kDurationMinSeconds = -315576000000LL;
+  static const int64_t kDurationMaxSeconds = 315576000000LL;
 
   // Converts Timestamp to/from RFC 3339 date string format.
   // Generated output will always be Z-normalized and uses 3, 6 or 9
@@ -110,12 +111,12 @@
 
   // Converts between Duration and integer types. The behavior is undefined if
   // the input value is not in the valid range of Duration.
-  static Duration NanosecondsToDuration(int64 nanos);
-  static Duration MicrosecondsToDuration(int64 micros);
-  static Duration MillisecondsToDuration(int64 millis);
-  static Duration SecondsToDuration(int64 seconds);
-  static Duration MinutesToDuration(int64 minutes);
-  static Duration HoursToDuration(int64 hours);
+  static Duration NanosecondsToDuration(int64_t nanos);
+  static Duration MicrosecondsToDuration(int64_t micros);
+  static Duration MillisecondsToDuration(int64_t millis);
+  static Duration SecondsToDuration(int64_t seconds);
+  static Duration MinutesToDuration(int64_t minutes);
+  static Duration HoursToDuration(int64_t hours);
   // Result will be truncated towards zero. For example, "-1.5s" will be
   // truncated to "-1s", and "1.5s" to "1s" when converting to seconds.
   // It's undefined behavior if the input duration is not valid or the result
@@ -123,28 +124,28 @@
   // valid range of Duration, or have an invalid nanos value (i.e., larger
   // than 999999999, less than -999999999, or have a different sign from the
   // seconds part).
-  static int64 DurationToNanoseconds(const Duration& duration);
-  static int64 DurationToMicroseconds(const Duration& duration);
-  static int64 DurationToMilliseconds(const Duration& duration);
-  static int64 DurationToSeconds(const Duration& duration);
-  static int64 DurationToMinutes(const Duration& duration);
-  static int64 DurationToHours(const Duration& duration);
+  static int64_t DurationToNanoseconds(const Duration& duration);
+  static int64_t DurationToMicroseconds(const Duration& duration);
+  static int64_t DurationToMilliseconds(const Duration& duration);
+  static int64_t DurationToSeconds(const Duration& duration);
+  static int64_t DurationToMinutes(const Duration& duration);
+  static int64_t DurationToHours(const Duration& duration);
   // Creates Timestamp from integer types. The integer value indicates the
   // time elapsed from Epoch time. The behavior is undefined if the input
   // value is not in the valid range of Timestamp.
-  static Timestamp NanosecondsToTimestamp(int64 nanos);
-  static Timestamp MicrosecondsToTimestamp(int64 micros);
-  static Timestamp MillisecondsToTimestamp(int64 millis);
-  static Timestamp SecondsToTimestamp(int64 seconds);
+  static Timestamp NanosecondsToTimestamp(int64_t nanos);
+  static Timestamp MicrosecondsToTimestamp(int64_t micros);
+  static Timestamp MillisecondsToTimestamp(int64_t millis);
+  static Timestamp SecondsToTimestamp(int64_t seconds);
   // Result will be truncated down to the nearest integer value. For example,
   // with "1969-12-31T23:59:59.9Z", TimestampToMilliseconds() returns -100
   // and TimestampToSeconds() returns -1. It's undefined behavior if the input
   // Timestamp is not valid (i.e., its seconds part or nanos part does not fall
   // in the valid range) or the return value doesn't fit into int64.
-  static int64 TimestampToNanoseconds(const Timestamp& timestamp);
-  static int64 TimestampToMicroseconds(const Timestamp& timestamp);
-  static int64 TimestampToMilliseconds(const Timestamp& timestamp);
-  static int64 TimestampToSeconds(const Timestamp& timestamp);
+  static int64_t TimestampToNanoseconds(const Timestamp& timestamp);
+  static int64_t TimestampToMicroseconds(const Timestamp& timestamp);
+  static int64_t TimestampToMilliseconds(const Timestamp& timestamp);
+  static int64_t TimestampToSeconds(const Timestamp& timestamp);
 
   // Conversion to/from other time/date types. Note that these types may
   // have a different precision and time range from Timestamp/Duration.
@@ -176,19 +177,19 @@
                                      const Duration& d2);  // NOLINT
 PROTOBUF_EXPORT Duration& operator-=(Duration& d1,
                                      const Duration& d2);     // NOLINT
-PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64 r);   // NOLINT
+PROTOBUF_EXPORT Duration& operator*=(Duration& d, int64_t r);  // NOLINT
 PROTOBUF_EXPORT Duration& operator*=(Duration& d, double r);  // NOLINT
-PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64 r);   // NOLINT
+PROTOBUF_EXPORT Duration& operator/=(Duration& d, int64_t r);  // NOLINT
 PROTOBUF_EXPORT Duration& operator/=(Duration& d, double r);  // NOLINT
 // Overload for other integer types.
 template <typename T>
 Duration& operator*=(Duration& d, T r) {  // NOLINT
-  int64 x = r;
+  int64_t x = r;
   return d *= x;
 }
 template <typename T>
 Duration& operator/=(Duration& d, T r) {  // NOLINT
-  int64 x = r;
+  int64_t x = r;
   return d /= x;
 }
 PROTOBUF_EXPORT Duration& operator%=(Duration& d1,
@@ -243,7 +244,7 @@
 inline Duration operator/(Duration d, T r) {
   return d /= r;
 }
-PROTOBUF_EXPORT int64 operator/(const Duration& d1, const Duration& d2);
+PROTOBUF_EXPORT int64_t operator/(const Duration& d1, const Duration& d2);
 
 inline Duration operator%(const Duration& d1, const Duration& d2) {
   Duration result = d1;
diff --git a/src/google/protobuf/util/time_util_test.cc b/src/google/protobuf/util/time_util_test.cc
index b6d3813..d38a27d 100644
--- a/src/google/protobuf/util/time_util_test.cc
+++ b/src/google/protobuf/util/time_util_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/time_util.h>
 
+#include <cstdint>
 #include <ctime>
 
 #include <google/protobuf/duration.pb.h>
@@ -119,10 +120,10 @@
   // Duration must support range from -315,576,000,000s to +315576000000s
   // which includes negative values.
   EXPECT_TRUE(TimeUtil::FromString("315576000000.999999999s", &d));
-  EXPECT_EQ(int64{315576000000}, d.seconds());
+  EXPECT_EQ(int64_t{315576000000}, d.seconds());
   EXPECT_EQ(999999999, d.nanos());
   EXPECT_TRUE(TimeUtil::FromString("-315576000000.999999999s", &d));
-  EXPECT_EQ(int64{-315576000000}, d.seconds());
+  EXPECT_EQ(int64_t{-315576000000}, d.seconds());
   EXPECT_EQ(-999999999, d.nanos());
 }
 
@@ -277,23 +278,24 @@
   EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b * 0.5));
   // Multiplication should not overflow if the result fits into the supported
   // range of Duration (intermediate result may be larger than int64).
-  EXPECT_EQ("315575999684.424s",
-            TimeUtil::ToString((one_second - one_nano) * int64{315576000000}));
-  EXPECT_EQ("-315575999684.424s",
-            TimeUtil::ToString((one_nano - one_second) * int64{315576000000}));
+  EXPECT_EQ("315575999684.424s", TimeUtil::ToString((one_second - one_nano) *
+                                                    int64_t{315576000000}));
+  EXPECT_EQ("-315575999684.424s", TimeUtil::ToString((one_nano - one_second) *
+                                                     int64_t{315576000000}));
   EXPECT_EQ("-315575999684.424s", TimeUtil::ToString((one_second - one_nano) *
-                                                     (int64{-315576000000})));
+                                                     (int64_t{-315576000000})));
 
   // Test / and %
   EXPECT_EQ("0.999999999s", TimeUtil::ToString(a / 2));
   EXPECT_EQ("-0.999999999s", TimeUtil::ToString(b / 2));
-  Duration large = TimeUtil::SecondsToDuration(int64{315576000000}) - one_nano;
+  Duration large =
+      TimeUtil::SecondsToDuration(int64_t{315576000000}) - one_nano;
   // We have to handle division with values beyond 64 bits.
-  EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / int64{315576000000}));
+  EXPECT_EQ("0.999999999s", TimeUtil::ToString(large / int64_t{315576000000}));
   EXPECT_EQ("-0.999999999s",
-            TimeUtil::ToString((-large) / int64{315576000000}));
+            TimeUtil::ToString((-large) / int64_t{315576000000}));
   EXPECT_EQ("-0.999999999s",
-            TimeUtil::ToString(large / (int64{-315576000000})));
+            TimeUtil::ToString(large / (int64_t{-315576000000})));
   Duration large2 = large + one_nano;
   EXPECT_EQ(large, large % large2);
   EXPECT_EQ(-large, (-large) % large2);
diff --git a/src/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h
index 698441b..2bda5c8 100644
--- a/src/google/protobuf/util/type_resolver.h
+++ b/src/google/protobuf/util/type_resolver.h
@@ -38,6 +38,7 @@
 #include <google/protobuf/stubs/common.h>
 #include <google/protobuf/type.pb.h>
 #include <google/protobuf/stubs/status.h>
+#include <google/protobuf/stubs/status.h>
 
 #include <google/protobuf/port_def.inc>
 
@@ -60,7 +61,7 @@
 
   // Resolves a type url for an enum type.
   virtual util::Status ResolveEnumType(const std::string& type_url,
-                                         google::protobuf::Enum* enum_type) = 0;
+                                       google::protobuf::Enum* enum_type) = 0;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index cf2f318..c5d4fdf 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -64,10 +64,6 @@
 using google::protobuf::UInt32Value;
 using google::protobuf::UInt64Value;
 
-using util::Status;
-using util::error::INVALID_ARGUMENT;
-using util::error::NOT_FOUND;
-
 class DescriptorPoolTypeResolver : public TypeResolver {
  public:
   DescriptorPoolTypeResolver(const std::string& url_prefix,
@@ -84,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();
@@ -101,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();
@@ -310,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/util/type_resolver_util_test.cc b/src/google/protobuf/util/type_resolver_util_test.cc
index d90fdff..f0a0a74 100644
--- a/src/google/protobuf/util/type_resolver_util_test.cc
+++ b/src/google/protobuf/util/type_resolver_util_test.cc
@@ -30,6 +30,7 @@
 
 #include <google/protobuf/util/type_resolver_util.h>
 
+#include <cstdint>
 #include <limits>
 #include <memory>
 #include <string>
@@ -135,12 +136,12 @@
   }
 
   bool HasInt32Option(const RepeatedPtrField<Option>& options,
-                      const std::string& name, int32 value) {
+                      const std::string& name, int32_t value) {
     return HasOption<Int32Value>(options, name, value);
   }
 
   bool HasUInt64Option(const RepeatedPtrField<Option>& options,
-                       const std::string& name, uint64 value) {
+                       const std::string& name, uint64_t value) {
     return HasOption<UInt64Value>(options, name, value);
   }
 
diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
index 8ffae81..f2a3cad 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -1692,7 +1692,7 @@
     int field_number, const MessageType& value, uint8* target,
     io::EpsCopyOutputStream* stream) {
   target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target);
-  target = io::CodedOutputStream::WriteVarint32ToArray(
+  target = io::CodedOutputStream::WriteVarint32ToArrayOutOfLine(
       static_cast<uint32>(value.GetCachedSize()), target);
   return value._InternalSerialize(target, stream);
 }
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index eb691be..c791d05 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -231,10 +231,8 @@
   schemas, file_default_instances, TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets,
   file_level_metadata_google_2fprotobuf_2fwrappers_2eproto, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto, file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto,
 };
-PROTOBUF_ATTRIBUTE_WEAK ::PROTOBUF_NAMESPACE_ID::Metadata
-descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(int index) {
-  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
-  return descriptor_table_google_2fprotobuf_2fwrappers_2eproto.file_level_metadata[index];
+PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter() {
+  return &descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
 }
 
 // Force running AddDescriptors() at dynamic initialization time.
@@ -299,7 +297,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // double value = 1;
       case 1:
@@ -310,7 +307,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -424,10 +422,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DoubleValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[0]);
 }
 
-
 // ===================================================================
 
 class FloatValue::_Internal {
@@ -486,7 +485,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // float value = 1;
       case 1:
@@ -497,7 +495,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -611,10 +610,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FloatValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[1]);
 }
 
-
 // ===================================================================
 
 class Int64Value::_Internal {
@@ -673,7 +673,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int64 value = 1;
       case 1:
@@ -684,7 +683,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -800,10 +800,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Int64Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[2]);
 }
 
-
 // ===================================================================
 
 class UInt64Value::_Internal {
@@ -862,7 +863,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // uint64 value = 1;
       case 1:
@@ -873,7 +873,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -989,10 +990,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UInt64Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[3]);
 }
 
-
 // ===================================================================
 
 class Int32Value::_Internal {
@@ -1051,7 +1053,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // int32 value = 1;
       case 1:
@@ -1062,7 +1063,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1178,10 +1180,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Int32Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[4]);
 }
 
-
 // ===================================================================
 
 class UInt32Value::_Internal {
@@ -1240,7 +1243,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // uint32 value = 1;
       case 1:
@@ -1251,7 +1253,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1367,10 +1370,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UInt32Value::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[5]);
 }
 
-
 // ===================================================================
 
 class BoolValue::_Internal {
@@ -1429,7 +1433,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // bool value = 1;
       case 1:
@@ -1440,7 +1443,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1554,10 +1558,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata BoolValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[6]);
 }
 
-
 // ===================================================================
 
 class StringValue::_Internal {
@@ -1621,7 +1626,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // string value = 1;
       case 1:
@@ -1634,7 +1638,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1754,10 +1759,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata StringValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[7]);
 }
 
-
 // ===================================================================
 
 class BytesValue::_Internal {
@@ -1821,7 +1827,6 @@
   while (!ctx->Done(&ptr)) {
     ::PROTOBUF_NAMESPACE_ID::uint32 tag;
     ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
-    CHK_(ptr);
     switch (tag >> 3) {
       // bytes value = 1;
       case 1:
@@ -1833,7 +1838,8 @@
         continue;
       default: {
       handle_unusual:
-        if ((tag & 7) == 4 || tag == 0) {
+        if ((tag == 0) || ((tag & 7) == 4)) {
+          CHK_(ptr);
           ctx->SetLastTag(tag);
           goto success;
         }
@@ -1949,10 +1955,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata BytesValue::GetMetadata() const {
-  return GetMetadataStatic();
+  return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(
+      &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
+      file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[8]);
 }
 
-
 // @@protoc_insertion_point(namespace_scope)
 PROTOBUF_NAMESPACE_CLOSE
 PROTOBUF_NAMESPACE_OPEN
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index bd1e1ba..0bc4949 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -53,7 +53,6 @@
   static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
 };
 extern PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
-PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Metadata descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(int index);
 PROTOBUF_NAMESPACE_OPEN
 class BoolValue;
 struct BoolValueDefaultTypeInternal;
@@ -102,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);
@@ -128,10 +127,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const DoubleValue& default_instance() {
     return *internal_default_instance();
@@ -199,12 +198,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -239,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);
@@ -265,10 +258,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const FloatValue& default_instance() {
     return *internal_default_instance();
@@ -336,12 +329,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -376,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);
@@ -402,10 +389,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Int64Value& default_instance() {
     return *internal_default_instance();
@@ -473,12 +460,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -513,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);
@@ -539,10 +520,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const UInt64Value& default_instance() {
     return *internal_default_instance();
@@ -610,12 +591,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -650,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);
@@ -676,10 +651,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const Int32Value& default_instance() {
     return *internal_default_instance();
@@ -747,12 +722,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -787,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);
@@ -813,10 +782,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const UInt32Value& default_instance() {
     return *internal_default_instance();
@@ -884,12 +853,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -924,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);
@@ -950,10 +913,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const BoolValue& default_instance() {
     return *internal_default_instance();
@@ -1021,12 +984,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1061,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);
@@ -1087,10 +1044,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const StringValue& default_instance() {
     return *internal_default_instance();
@@ -1158,12 +1115,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1175,10 +1126,8 @@
   // string value = 1;
   void clear_value();
   const std::string& value() const;
-  void set_value(const std::string& value);
-  void set_value(std::string&& value);
-  void set_value(const char* value);
-  void set_value(const char* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_value();
   std::string* release_value();
   void set_allocated_value(std::string* value);
@@ -1205,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);
@@ -1231,10 +1180,10 @@
     return GetDescriptor();
   }
   static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
-    return GetMetadataStatic().descriptor;
+    return default_instance().GetMetadata().descriptor;
   }
   static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
-    return GetMetadataStatic().reflection;
+    return default_instance().GetMetadata().reflection;
   }
   static const BytesValue& default_instance() {
     return *internal_default_instance();
@@ -1302,12 +1251,6 @@
   public:
 
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
-  private:
-  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
-    return ::descriptor_table_google_2fprotobuf_2fwrappers_2eproto_metadata_getter(kIndexInFileMessages);
-  }
-
-  public:
 
   // nested types ----------------------------------------------------
 
@@ -1319,10 +1262,8 @@
   // bytes value = 1;
   void clear_value();
   const std::string& value() const;
-  void set_value(const std::string& value);
-  void set_value(std::string&& value);
-  void set_value(const char* value);
-  void set_value(const void* value, size_t size);
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_value(ArgT0&& arg0, ArgT... args);
   std::string* mutable_value();
   std::string* release_value();
   void set_allocated_value(std::string* value);
@@ -1530,8 +1471,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.StringValue.value)
   return _internal_value();
 }
-inline void StringValue::set_value(const std::string& value) {
-  _internal_set_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void StringValue::set_value(ArgT0&& arg0, ArgT... args) {
+ 
+ value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.StringValue.value)
 }
 inline std::string* StringValue::mutable_value() {
@@ -1545,25 +1489,6 @@
   
   value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void StringValue::set_value(std::string&& value) {
-  
-  value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.StringValue.value)
-}
-inline void StringValue::set_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.StringValue.value)
-}
-inline void StringValue::set_value(const char* value,
-    size_t size) {
-  
-  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.StringValue.value)
-}
 inline std::string* StringValue::_internal_mutable_value() {
   
   return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
@@ -1595,8 +1520,11 @@
   // @@protoc_insertion_point(field_get:google.protobuf.BytesValue.value)
   return _internal_value();
 }
-inline void BytesValue::set_value(const std::string& value) {
-  _internal_set_value(value);
+template <typename ArgT0, typename... ArgT>
+PROTOBUF_ALWAYS_INLINE
+inline void BytesValue::set_value(ArgT0&& arg0, ArgT... args) {
+ 
+ value_.SetBytes(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast<ArgT0 &&>(arg0), args..., GetArena());
   // @@protoc_insertion_point(field_set:google.protobuf.BytesValue.value)
 }
 inline std::string* BytesValue::mutable_value() {
@@ -1610,25 +1538,6 @@
   
   value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
 }
-inline void BytesValue::set_value(std::string&& value) {
-  
-  value_.Set(
-    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
-  // @@protoc_insertion_point(field_set_rvalue:google.protobuf.BytesValue.value)
-}
-inline void BytesValue::set_value(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  
-  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
-  // @@protoc_insertion_point(field_set_char:google.protobuf.BytesValue.value)
-}
-inline void BytesValue::set_value(const void* value,
-    size_t size) {
-  
-  value_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
-      reinterpret_cast<const char*>(value), size), GetArena());
-  // @@protoc_insertion_point(field_set_pointer:google.protobuf.BytesValue.value)
-}
 inline std::string* BytesValue::_internal_mutable_value() {
   
   return value_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());