Merge tag 'refs/tags/sync-piper' into sync-stage
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/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 2dfcc9b..86aecb1 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 110ccdc..20b61f7 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -31,9 +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>
 
@@ -64,8 +66,6 @@
 #endif
 };
 
-class StringPiece;
-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/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/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 dc265f0..a569502 100644
--- a/src/google/protobuf/stubs/statusor.h
+++ b/src/google/protobuf/stubs/statusor.h
@@ -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();
@@ -93,17 +83,21 @@
 namespace google {
 namespace protobuf {
 namespace util {
+namespace statusor_internal {
 
 template<typename T>
 class StatusOr {
   template<typename U> friend class StatusOr;
 
  public:
+  using value_type = T;
+
+  // Construct a new StatusOr with Status::UNKNOWN status.
   // Construct a new StatusOr with UnknownError() status.
-  StatusOr();
+  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
@@ -116,7 +110,7 @@
 
   // 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()'
@@ -149,9 +143,6 @@
   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:
@@ -162,8 +153,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Implementation details for StatusOr<T>
 
-namespace internal {
-
 class PROTOBUF_EXPORT StatusOrHelper {
  public:
   // Move type-agnostic error handling to the .cc.
@@ -185,8 +174,6 @@
   static inline bool IsValueNull(const T* t) { return t == nullptr; }
 };
 
-}  // namespace internal
-
 template <typename T>
 inline StatusOr<T>::StatusOr() : status_(util::UnknownError("")) {}
 
@@ -201,7 +188,7 @@
 
 template<typename T>
 inline StatusOr<T>::StatusOr(const T& value) {
-  if (internal::StatusOrHelper::Specialize<T>::IsValueNull(value)) {
+  if (StatusOrHelper::Specialize<T>::IsValueNull(value)) {
     status_ = util::InternalError("nullptr is not a valid argument.");
   } else {
     status_ = util::OkStatus();
@@ -246,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 c51945f..403adcc 100644
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ b/src/google/protobuf/stubs/statusor_test.cc
@@ -84,7 +84,7 @@
   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,7 +92,7 @@
   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) {
@@ -106,7 +106,7 @@
   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) {
@@ -121,7 +121,7 @@
   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) {
@@ -137,7 +137,7 @@
   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) {
@@ -158,13 +158,13 @@
 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) {
@@ -183,7 +183,7 @@
   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,7 +191,7 @@
   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) {
@@ -205,8 +205,7 @@
   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) {
@@ -221,7 +220,7 @@
   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) {
@@ -237,8 +236,7 @@
   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) {
@@ -259,13 +257,13 @@
 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 0a426fe..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,6 +350,10 @@
 // allow StringPiece to be logged
 extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
 
+}  // namespace stringpiece_internal
+
+using ::google::protobuf::stringpiece_internal::StringPiece;
+
 }  // 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 31c5489..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);
 }
 
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/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
index ff4fe54..717cee4 100644
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -253,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();
 }
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
index f82c414..9878826 100644
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc
@@ -436,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());
   }