Merge remote-tracking branch 'remotes/upstream/master' into kotlinProtos
diff --git a/.github/mergeable.yml b/.github/mergeable.yml
index 4027cf5..ade6c67 100644
--- a/.github/mergeable.yml
+++ b/.github/mergeable.yml
@@ -11,7 +11,7 @@
                 regex: 'release notes: yes'
                 message: 'Please include release notes: yes'
             - must_include:
-                regex: '^(autotools|bazel|c#|c\+\+|cleanup|cmake|conformance tests|integration|go|java|javascript|objective-c|php|protoc|python|ruby)'
+                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'
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/CHANGES.txt b/CHANGES.txt
index 99d9ad7..05a15ed 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,6 +1,7 @@
 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
diff --git a/benchmarks/download_data.sh b/benchmarks/download_data.sh
deleted file mode 100755
index fa0729e..0000000
--- a/benchmarks/download_data.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#! /bin/sh
-
-curl -O https://storage.googleapis.com/protobuf_opensource_benchmark_data/datasets.tar.gz
-tar -zvxf datasets.tar.gz
-
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/CodedInputStream.java b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
index 00be6f0..6098a9a 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -3523,9 +3523,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/test/java/com/google/protobuf/CodedInputStreamTest.java b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
index 532052c..4de5f5b 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);
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index 021eac0..e6efbab 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/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/benchmark/run.sh b/kokoro/linux/benchmark/run.sh
index 1b1032b..ee80db3 100755
--- a/kokoro/linux/benchmark/run.sh
+++ b/kokoro/linux/benchmark/run.sh
@@ -18,7 +18,6 @@
 
 # download datasets for benchmark
 cd benchmarks
-./download_data.sh
 datasets=$(for file in $(find . -type f -name "dataset.*.pb" -not -path "./tmp/*"); do echo "$(pwd)/$file"; done | xargs)
 echo $datasets
 cd $oldpwd
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/protoc-artifacts/README.md b/protoc-artifacts/README.md
index 1706ddc..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
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 3218d7d..eeb844c 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -250,8 +250,9 @@
                  message_type->full_name().c_str());
     return NULL;
   }
+  ScopedPyObjectPtr args(PyTuple_New(0));
   ScopedPyObjectPtr value(
-      PyObject_Call(message_class->AsPyObject(), NULL, NULL));
+      PyObject_Call(message_class->AsPyObject(), args.get(), NULL));
   Py_DECREF(message_class);
   if (value == NULL) {
     return NULL;
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index a24d45d..d330e0d 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -178,7 +178,8 @@
                      PyObject* args, PyObject* kwargs) {
   static const char* kwlist[] = {"descriptor_db", 0};
   PyObject* py_database = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", const_cast<char**>(kwlist), &py_database)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
+                                   const_cast<char**>(kwlist), &py_database)) {
     return NULL;
   }
   DescriptorDatabase* database = NULL;
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index 346a5f5..1c2c526 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -466,7 +466,8 @@
   static const char* kwlist[] = {"key", "default", nullptr};
   PyObject* key;
   PyObject* default_value = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", const_cast<char**>(kwlist), &key,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
+                                   const_cast<char**>(kwlist), &key,
                                    &default_value)) {
     return NULL;
   }
@@ -761,7 +762,8 @@
   static const char* kwlist[] = {"key", "default", nullptr};
   PyObject* key;
   PyObject* default_value = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", const_cast<char**>(kwlist), &key,
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
+                                   const_cast<char**>(kwlist), &key,
                                    &default_value)) {
     return NULL;
   }
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 0921af7..f30c6ba 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -197,15 +197,14 @@
 }
 
 static PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
-  static const 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", const_cast<char**>(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;
   }
 
@@ -1680,10 +1679,10 @@
     CMessage* self, PyObject* args, PyObject* kwargs,
     bool require_initialized) {
   // Parse the "deterministic" kwarg; defaults to False.
-  static const char* kwlist[] = { "deterministic", 0 };
+  static const char* kwlist[] = {"deterministic", 0};
   PyObject* deterministic_obj = Py_None;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", const_cast<char**>(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
diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc
index 5a10c3d..7905be0 100644
--- a/python/google/protobuf/pyext/message_factory.cc
+++ b/python/google/protobuf/pyext/message_factory.cc
@@ -79,7 +79,8 @@
 PyObject* New(PyTypeObject* type, PyObject* args, PyObject* kwargs) {
   static const char* kwlist[] = {"pool", 0};
   PyObject* pool = NULL;
-  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", const_cast<char**>(kwlist), &pool)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
+                                   const_cast<char**>(kwlist), &pool)) {
     return NULL;
   }
   ScopedPyObjectPtr owned_pool;
diff --git a/python/setup.py b/python/setup.py
index aab240a..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):
@@ -291,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/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index de8dc44..57e81f8 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -290,7 +290,10 @@
       public DescriptorPool::ErrorCollector {
  public:
   ErrorPrinter(ErrorFormat format, DiskSourceTree* tree = NULL)
-      : format_(format), tree_(tree), found_errors_(false), found_warnings_(false) {}
+      : format_(format),
+        tree_(tree),
+        found_errors_(false),
+        found_warnings_(false) {}
   ~ErrorPrinter() {}
 
   // implements MultiFileErrorCollector ------------------------------
@@ -1639,8 +1642,7 @@
       *name == "--version" || *name == "--decode_raw" ||
       *name == "--print_free_field_numbers" ||
       *name == "--experimental_allow_proto3_optional" ||
-      *name == "--deterministic_output" ||
-      *name == "--fatal_warnings") {
+      *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.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index 5fc111e..9cc8cf9 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -525,8 +525,7 @@
 void CommandLineInterfaceTest::ExpectCapturedStderrSubstringWithZeroReturnCode(
     const std::string& expected_substring) {
   EXPECT_EQ(0, return_code_);
-  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring,
-                      error_text_);
+  EXPECT_PRED_FORMAT2(testing::IsSubstring, expected_substring, error_text_);
 }
 
 void CommandLineInterfaceTest::ExpectFileContent(const std::string& filename,
@@ -2333,20 +2332,18 @@
   // Test --fatal_warnings.
 
   CreateTempFile("foo.proto",
-    "syntax = \"proto2\";\n"
-    "import \"bar.proto\";\n");
-  CreateTempFile("bar.proto",
-    "syntax = \"proto2\";\n");
+                 "syntax = \"proto2\";\n"
+                 "import \"bar.proto\";\n");
+  CreateTempFile("bar.proto", "syntax = \"proto2\";\n");
 
   Run("protocol_compiler --test_out=$tmpdir "
-    "--proto_path=$tmpdir foo.proto");
+      "--proto_path=$tmpdir foo.proto");
   ExpectCapturedStderrSubstringWithZeroReturnCode(
-    "foo.proto:2:1: warning: Import bar.proto is unused.");
+      "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.");
+      "--proto_path=$tmpdir foo.proto");
+  ExpectErrorSubstring("foo.proto:2:1: warning: Import bar.proto is unused.");
 }
 
 // -------------------------------------------------------------------
diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h
index aa2cfc1..4c09eb1 100644
--- a/src/google/protobuf/port.h
+++ b/src/google/protobuf/port.h
@@ -37,11 +37,4 @@
 #define GOOGLE_PROTOBUF_PORT_H__
 
 
-#include <google/protobuf/stubs/port.h>
-
-// Protobuf intends to move into the pb:: namespace.
-namespace protobuf_future_namespace_placeholder {}
-namespace pb = ::protobuf_future_namespace_placeholder;
-
-
 #endif  // GOOGLE_PROTOBUF_PORT_H__
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 8ecc2fa..20b61f7 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -31,6 +31,7 @@
 #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>
@@ -65,7 +66,6 @@
 #endif
 };
 
-class uint128;
 namespace internal {
 
 class LogFinisher;
diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
index e071852..f5c0fa4 100644
--- a/src/google/protobuf/stubs/status.cc
+++ b/src/google/protobuf/stubs/status.cc
@@ -85,8 +85,7 @@
 
 }  // namespace
 
-Status::Status() : error_code_(StatusCode::kOk) {
-}
+Status::Status() : error_code_(StatusCode::kOk) {}
 
 Status::Status(StatusCode error_code, StringPiece error_message)
     : error_code_(error_code) {
@@ -117,15 +116,12 @@
     if (error_message_.empty()) {
       return StatusCodeToString(error_code_);
     } else {
-      return StatusCodeToString(error_code_) + ":" +
-          error_message_;
+      return StatusCodeToString(error_code_) + ":" + error_message_;
     }
   }
 }
 
-Status OkStatus() {
-  return Status();
-}
+Status OkStatus() { return Status(); }
 
 std::ostream& operator<<(std::ostream& os, const Status& x) {
   os << x.ToString();
diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h
index 187bc27..c858cf6 100644
--- a/src/google/protobuf/stubs/status.h
+++ b/src/google/protobuf/stubs/status.h
@@ -78,12 +78,8 @@
   ~Status() {}
 
   // Accessor
-  bool ok() const {
-    return error_code_ == StatusCode::kOk;
-  }
-  StatusCode code() const {
-    return error_code_;
-  }
+  bool ok() const { return error_code_ == StatusCode::kOk; }
+  StatusCode code() const { return error_code_; }
   StringPiece message() const {
     return error_message_;
   }
@@ -173,7 +169,6 @@
 using ::google::protobuf::util::status_internal::IsUnimplemented;
 using ::google::protobuf::util::status_internal::IsUnknown;
 
-using ::google::protobuf::util::status_internal::OkStatus;
 using ::google::protobuf::util::status_internal::AbortedError;
 using ::google::protobuf::util::status_internal::AlreadyExistsError;
 using ::google::protobuf::util::status_internal::CancelledError;
@@ -183,6 +178,7 @@
 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;
diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
index cca6c2b..9e9edf7 100644
--- a/src/google/protobuf/stubs/status_test.cc
+++ b/src/google/protobuf/stubs/status_test.cc
@@ -247,9 +247,7 @@
   ASSERT_TRUE(a.ok());
 }
 
-TEST(Status, EqualsOK) {
-  ASSERT_EQ(util::OkStatus(), util::Status());
-}
+TEST(Status, EqualsOK) { ASSERT_EQ(util::OkStatus(), util::Status()); }
 
 TEST(Status, EqualsSame) {
   const util::Status a = util::CancelledError("message");
diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
index 0f48377..a569502 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -174,10 +174,8 @@
   static inline bool IsValueNull(const T* t) { return t == nullptr; }
 };
 
-template<typename T>
-inline StatusOr<T>::StatusOr()
-    : status_(util::UnknownError("")) {
-}
+template <typename T>
+inline StatusOr<T>::StatusOr() : status_(util::UnknownError("")) {}
 
 template<typename T>
 inline StatusOr<T>::StatusOr(const Status& status) {
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
index 27f8ac8..403adcc 100644
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -110,7 +110,7 @@
 }
 
 TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
-  StatusOr<int>    original(util::CancelledError(""));
+  StatusOr<int> original(util::CancelledError(""));
   StatusOr<double> copy(original);
   EXPECT_EQ(original.status(), copy.status());
 }
@@ -141,7 +141,7 @@
 }
 
 TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
-  StatusOr<int>    source(util::CancelledError(""));
+  StatusOr<int> source(util::CancelledError(""));
   StatusOr<double> target;
   target = source;
   EXPECT_EQ(source.status(), target.status());
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index 7ad715b..4bd5395 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -173,6 +173,10 @@
                               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).
   struct Tolerance {
@@ -239,10 +243,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
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
index 4384b79..52c335d 100644
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -57,11 +57,10 @@
       MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
     return after;
   } else {
-    return util::InvalidArgumentError(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));
   }
 }
 
@@ -260,7 +259,8 @@
   if (type_ == TYPE_STRING) {
     std::string decoded;
     if (!DecodeBase64(str_, &decoded)) {
-      return util::InvalidArgumentError(ValueAsStringOrDefault("Invalid data in input."));
+      return util::InvalidArgumentError(
+          ValueAsStringOrDefault("Invalid data in input."));
     }
     return decoded;
   } else {
@@ -358,7 +358,8 @@
   }
   To result;
   if (func(str_, &result)) return result;
-  return util::InvalidArgumentError(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/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
index cd194e8..f211a54 100644
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ b/src/google/protobuf/util/internal/field_mask_utility.cc
@@ -134,10 +134,9 @@
         }
         // Un-escaped '"' must be followed with a ']'.
         if (i >= length - 1 || paths[i + 1] != ']') {
-          return util::InvalidArgumentError(
-              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;
@@ -146,10 +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::InvalidArgumentError(
-              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;
@@ -158,10 +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::InvalidArgumentError(
-              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;
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
index f38b68a..c3030b5 100644
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -302,7 +302,8 @@
         break;
 
       default:
-        result = util::InternalError(StrCat("Unknown parse type: ", type));
+        result =
+            util::InternalError(StrCat("Unknown parse type: ", type));
         break;
     }
     if (!result.ok()) {
@@ -872,8 +873,9 @@
   StringPiece segment(begin, end - begin);
   std::string location(p_start - begin, ' ');
   location.push_back('^');
-  return util::InvalidArgumentError(
+  auto status = util::InvalidArgumentError(
       StrCat(message, "\n", segment, "\n", location));
+  return status;
 }
 
 util::Status JsonStreamParser::ReportUnknown(StringPiece message,
@@ -892,9 +894,8 @@
 util::Status JsonStreamParser::IncrementRecursionDepth(
     StringPiece key) const {
   if (++recursion_depth_ > max_recursion_depth_) {
-    return util::InvalidArgumentError(
-        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();
 }
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
index b98a14c..3a37d9c 100644
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -317,8 +317,8 @@
   int64_t seconds = p.first;
   int32_t nanos = p.second;
   if (seconds > kTimestampMaxSeconds || seconds < kTimestampMinSeconds) {
-    return util::InternalError(
-        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) {
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index f9690fe..9878826 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -1025,9 +1025,8 @@
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
     return util::InvalidArgumentError(
-        StrCat(
-            "Invalid data type for timestamp, value is ",
-            data.ValueAsStringOrDefault("")));
+        StrCat("Invalid data type for timestamp, value is ",
+                     data.ValueAsStringOrDefault("")));
   }
 
   StringPiece value(data.str());
@@ -1057,9 +1056,8 @@
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
     return util::InvalidArgumentError(
-        StrCat(
-            "Invalid data type for field mask, value is ",
-            data.ValueAsStringOrDefault("")));
+        StrCat("Invalid data type for field mask, value is ",
+                     data.ValueAsStringOrDefault("")));
   }
 
   // TODO(tsun): figure out how to do proto descriptor based snake case
@@ -1074,9 +1072,8 @@
   if (data.type() == DataPiece::TYPE_NULL) return Status();
   if (data.type() != DataPiece::TYPE_STRING) {
     return util::InvalidArgumentError(
-        StrCat(
-            "Invalid data type for duration, value is ",
-            data.ValueAsStringOrDefault("")));
+        StrCat("Invalid data type for duration, value is ",
+                     data.ValueAsStringOrDefault("")));
   }
 
   StringPiece value(data.str());
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
index 2e7b78d..3597f9e 100644
--- a/src/google/protobuf/util/json_util.cc
+++ b/src/google/protobuf/util/json_util.cc
@@ -154,9 +154,8 @@
 
   void MissingField(const converter::LocationTrackerInterface& loc,
                     StringPiece missing_name) override {
-    status_ = util::InvalidArgumentError(
-        StrCat(
-            GetLocString(loc), ": missing field ", std::string(missing_name)));
+    status_ = util::InvalidArgumentError(StrCat(
+        GetLocString(loc), ": missing field ", std::string(missing_name)));
   }
 
  private:
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index 80fe341..c5d4fdf 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -80,8 +80,8 @@
 
     const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
     if (descriptor == NULL) {
-      return util::NotFoundError(
-          "Invalid type URL, unknown type: " + type_name);
+      return util::NotFoundError("Invalid type URL, unknown type: " +
+                                 type_name);
     }
     ConvertDescriptor(descriptor, type);
     return util::Status();
@@ -97,8 +97,8 @@
 
     const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
     if (descriptor == NULL) {
-      return util::InvalidArgumentError(
-          "Invalid type URL, unknown type: " + type_name);
+      return util::InvalidArgumentError("Invalid type URL, unknown type: " +
+                                        type_name);
     }
     ConvertEnumDescriptor(descriptor, enum_type);
     return util::Status();