Fix "unsafe narrowing" warnings in absl, 4/n.

Addresses failures with the following, in some files:
-Wshorten-64-to-32
-Wimplicit-int-conversion
-Wsign-compare
-Wsign-conversion
-Wtautological-unsigned-zero-compare

(This specific CL focuses on .cc files in strings/, except /internal/.)

Bug: chromium:1292951
PiperOrigin-RevId: 465285043
Change-Id: I37e9d1b4c4e9aa655b720da1467927af2aba995e
diff --git a/absl/numeric/bits.h b/absl/numeric/bits.h
index 628cdf5..df81b9a 100644
--- a/absl/numeric/bits.h
+++ b/absl/numeric/bits.h
@@ -131,10 +131,9 @@
 // fractional part discarded.
 template <class T>
 ABSL_INTERNAL_CONSTEXPR_CLZ inline
-    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    typename std::enable_if<std::is_unsigned<T>::value, int>::type
     bit_width(T x) noexcept {
-  return std::numeric_limits<T>::digits -
-         static_cast<unsigned int>(countl_zero(x));
+  return std::numeric_limits<T>::digits - countl_zero(x);
 }
 
 // Returns: If x == 0, 0; otherwise the maximal value y such that
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc
index 93bb03e..868df2d 100644
--- a/absl/strings/ascii.cc
+++ b/absl/strings/ascii.cc
@@ -157,13 +157,13 @@
 
 void AsciiStrToLower(std::string* s) {
   for (auto& ch : *s) {
-    ch = absl::ascii_tolower(ch);
+    ch = absl::ascii_tolower(static_cast<unsigned char>(ch));
   }
 }
 
 void AsciiStrToUpper(std::string* s) {
   for (auto& ch : *s) {
-    ch = absl::ascii_toupper(ch);
+    ch = absl::ascii_toupper(static_cast<unsigned char>(ch));
   }
 }
 
@@ -183,17 +183,17 @@
   for (; input_it < input_end; ++input_it) {
     if (is_ws) {
       // Consecutive whitespace?  Keep only the last.
-      is_ws = absl::ascii_isspace(*input_it);
+      is_ws = absl::ascii_isspace(static_cast<unsigned char>(*input_it));
       if (is_ws) --output_it;
     } else {
-      is_ws = absl::ascii_isspace(*input_it);
+      is_ws = absl::ascii_isspace(static_cast<unsigned char>(*input_it));
     }
 
     *output_it = *input_it;
     ++output_it;
   }
 
-  str->erase(output_it - &(*str)[0]);
+  str->erase(static_cast<size_t>(output_it - &(*str)[0]));
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/strings/charconv.cc b/absl/strings/charconv.cc
index fefcfc9..65d1beb 100644
--- a/absl/strings/charconv.cc
+++ b/absl/strings/charconv.cc
@@ -65,6 +65,8 @@
 
 template <>
 struct FloatTraits<double> {
+  using mantissa_t = uint64_t;
+
   // The number of mantissa bits in the given float type.  This includes the
   // implied high bit.
   static constexpr int kTargetMantissaBits = 53;
@@ -103,7 +105,7 @@
   // a normal value is made, or it must be less narrow than that, in which case
   // `exponent` must be exactly kMinNormalExponent, and a subnormal value is
   // made.
-  static double Make(uint64_t mantissa, int exponent, bool sign) {
+  static double Make(mantissa_t mantissa, int exponent, bool sign) {
 #ifndef ABSL_BIT_PACK_FLOATS
     // Support ldexp no matter which namespace it's in.  Some platforms
     // incorrectly don't put it in namespace std.
@@ -116,8 +118,10 @@
     if (mantissa > kMantissaMask) {
       // Normal value.
       // Adjust by 1023 for the exponent representation bias, and an additional
-      // 52 due to the implied decimal point in the IEEE mantissa represenation.
-      dbl += uint64_t{exponent + 1023u + kTargetMantissaBits - 1} << 52;
+      // 52 due to the implied decimal point in the IEEE mantissa
+      // representation.
+      dbl += static_cast<uint64_t>(exponent + 1023 + kTargetMantissaBits - 1)
+             << 52;
       mantissa &= kMantissaMask;
     } else {
       // subnormal value
@@ -134,16 +138,20 @@
 // members and methods.
 template <>
 struct FloatTraits<float> {
+  using mantissa_t = uint32_t;
+
   static constexpr int kTargetMantissaBits = 24;
   static constexpr int kMaxExponent = 104;
   static constexpr int kMinNormalExponent = -149;
+
   static float MakeNan(const char* tagp) {
     // Support nanf no matter which namespace it's in.  Some platforms
     // incorrectly don't put it in namespace std.
     using namespace std;  // NOLINT
     return nanf(tagp);
   }
-  static float Make(uint32_t mantissa, int exponent, bool sign) {
+
+  static float Make(mantissa_t mantissa, int exponent, bool sign) {
 #ifndef ABSL_BIT_PACK_FLOATS
     // Support ldexpf no matter which namespace it's in.  Some platforms
     // incorrectly don't put it in namespace std.
@@ -157,7 +165,8 @@
       // Normal value.
       // Adjust by 127 for the exponent representation bias, and an additional
       // 23 due to the implied decimal point in the IEEE mantissa represenation.
-      flt += uint32_t{exponent + 127u + kTargetMantissaBits - 1} << 23;
+      flt += static_cast<uint32_t>(exponent + 127 + kTargetMantissaBits - 1)
+             << 23;
       mantissa &= kMantissaMask;
     } else {
       // subnormal value
@@ -242,9 +251,9 @@
 
 // Returns the bit width of the given uint128.  (Equivalently, returns 128
 // minus the number of leading zero bits.)
-unsigned BitWidth(uint128 value) {
+int BitWidth(uint128 value) {
   if (Uint128High64(value) == 0) {
-    return static_cast<unsigned>(bit_width(Uint128Low64(value)));
+    return bit_width(Uint128Low64(value));
   }
   return 128 - countl_zero(Uint128High64(value));
 }
@@ -337,8 +346,10 @@
     *value = negative ? -0.0 : 0.0;
     return;
   }
-  *value = FloatTraits<FloatType>::Make(calculated.mantissa,
-                                        calculated.exponent, negative);
+  *value = FloatTraits<FloatType>::Make(
+      static_cast<typename FloatTraits<FloatType>::mantissa_t>(
+          calculated.mantissa),
+      calculated.exponent, negative);
 }
 
 // Returns the given uint128 shifted to the right by `shift` bits, and rounds
@@ -519,7 +530,7 @@
     const strings_internal::ParsedFloat& parsed_hex) {
   uint64_t mantissa = parsed_hex.mantissa;
   int exponent = parsed_hex.exponent;
-  auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
+  int mantissa_width = bit_width(mantissa);
   const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
   bool result_exact;
   exponent += shift;
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index b34c03a..523379e 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -20,6 +20,7 @@
 #include <cstdio>
 #include <cstdlib>
 #include <iomanip>
+#include <ios>
 #include <iostream>
 #include <limits>
 #include <ostream>
@@ -184,7 +185,7 @@
   assert(tag >= n);
   tag -= n;
   memset(data_.as_chars() + tag, 0, n);
-  set_inline_size(static_cast<char>(tag));
+  set_inline_size(tag);
 }
 
 inline void Cord::InlineRep::remove_prefix(size_t n) {
@@ -1098,7 +1099,7 @@
                          : current_leaf_;
   const char* data = payload->IsExternal() ? payload->external()->base
                                            : payload->flat()->Data();
-  const size_t offset = current_chunk_.data() - data;
+  const size_t offset = static_cast<size_t>(current_chunk_.data() - data);
 
   auto* tree = CordRepSubstring::Substring(payload, offset, n);
   subcord.contents_.EmplaceTree(VerifyTree(tree), method);
@@ -1308,7 +1309,7 @@
 
 std::ostream& operator<<(std::ostream& out, const Cord& cord) {
   for (absl::string_view chunk : cord.Chunks()) {
-    out.write(chunk.data(), chunk.size());
+    out.write(chunk.data(), static_cast<std::streamsize>(chunk.size()));
   }
   return out;
 }
diff --git a/absl/strings/cord_buffer.h b/absl/strings/cord_buffer.h
index 09a74ad..15494b3 100644
--- a/absl/strings/cord_buffer.h
+++ b/absl/strings/cord_buffer.h
@@ -411,8 +411,12 @@
 
   // Power2 functions
   static bool IsPow2(size_t size) { return absl::has_single_bit(size); }
-  static size_t Log2Floor(size_t size) { return absl::bit_width(size) - 1; }
-  static size_t Log2Ceil(size_t size) { return absl::bit_width(size - 1); }
+  static size_t Log2Floor(size_t size) {
+    return static_cast<size_t>(absl::bit_width(size) - 1);
+  }
+  static size_t Log2Ceil(size_t size) {
+    return static_cast<size_t>(absl::bit_width(size - 1));
+  }
 
   // Implementation of `CreateWithCustomLimit()`.
   // This implementation allows for future memory allocation hints to
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc
index 4dc6970..7d97944 100644
--- a/absl/strings/escaping.cc
+++ b/absl/strings/escaping.cc
@@ -42,11 +42,11 @@
 
 inline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); }
 
-inline int hex_digit_to_int(char c) {
+inline unsigned int hex_digit_to_int(char c) {
   static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61,
                 "Character set must be ASCII.");
-  assert(absl::ascii_isxdigit(c));
-  int x = static_cast<unsigned char>(c);
+  assert(absl::ascii_isxdigit(static_cast<unsigned char>(c)));
+  unsigned int x = static_cast<unsigned char>(c);
   if (x > '9') {
     x += 9;
   }
@@ -121,27 +121,29 @@
         case '7': {
           // octal digit: 1 to 3 digits
           const char* octal_start = p;
-          unsigned int ch = *p - '0';
-          if (p < last_byte && is_octal_digit(p[1])) ch = ch * 8 + *++p - '0';
+          unsigned int ch = static_cast<unsigned int>(*p - '0');  // digit 1
           if (p < last_byte && is_octal_digit(p[1]))
-            ch = ch * 8 + *++p - '0';      // now points at last digit
+            ch = ch * 8 + static_cast<unsigned int>(*++p - '0');  // digit 2
+          if (p < last_byte && is_octal_digit(p[1]))
+            ch = ch * 8 + static_cast<unsigned int>(*++p - '0');  // digit 3
           if (ch > 0xff) {
             if (error) {
               *error = "Value of \\" +
-                       std::string(octal_start, p + 1 - octal_start) +
+                       std::string(octal_start,
+                                   static_cast<size_t>(p + 1 - octal_start)) +
                        " exceeds 0xff";
             }
             return false;
           }
           if ((ch == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
-            const ptrdiff_t octal_size = p + 1 - octal_start;
+            const size_t octal_size = static_cast<size_t>(p + 1 - octal_start);
             *d++ = '\\';
             memmove(d, octal_start, octal_size);
             d += octal_size;
             break;
           }
-          *d++ = ch;
+          *d++ = static_cast<char>(ch);
           break;
         }
         case 'x':
@@ -149,32 +151,34 @@
           if (p >= last_byte) {
             if (error) *error = "String cannot end with \\x";
             return false;
-          } else if (!absl::ascii_isxdigit(p[1])) {
+          } else if (!absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
             if (error) *error = "\\x cannot be followed by a non-hex digit";
             return false;
           }
           unsigned int ch = 0;
           const char* hex_start = p;
-          while (p < last_byte && absl::ascii_isxdigit(p[1]))
+          while (p < last_byte &&
+                 absl::ascii_isxdigit(static_cast<unsigned char>(p[1])))
             // Arbitrarily many hex digits
             ch = (ch << 4) + hex_digit_to_int(*++p);
           if (ch > 0xFF) {
             if (error) {
               *error = "Value of \\" +
-                       std::string(hex_start, p + 1 - hex_start) +
+                       std::string(hex_start,
+                                   static_cast<size_t>(p + 1 - hex_start)) +
                        " exceeds 0xff";
             }
             return false;
           }
           if ((ch == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
-            const ptrdiff_t hex_size = p + 1 - hex_start;
+            const size_t hex_size = static_cast<size_t>(p + 1 - hex_start);
             *d++ = '\\';
             memmove(d, hex_start, hex_size);
             d += hex_size;
             break;
           }
-          *d++ = ch;
+          *d++ = static_cast<char>(ch);
           break;
         }
         case 'u': {
@@ -184,18 +188,20 @@
           if (p + 4 >= end) {
             if (error) {
               *error = "\\u must be followed by 4 hex digits: \\" +
-                       std::string(hex_start, p + 1 - hex_start);
+                       std::string(hex_start,
+                                   static_cast<size_t>(p + 1 - hex_start));
             }
             return false;
           }
           for (int i = 0; i < 4; ++i) {
             // Look one char ahead.
-            if (absl::ascii_isxdigit(p[1])) {
+            if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
               rune = (rune << 4) + hex_digit_to_int(*++p);  // Advance p.
             } else {
               if (error) {
                 *error = "\\u must be followed by 4 hex digits: \\" +
-                         std::string(hex_start, p + 1 - hex_start);
+                         std::string(hex_start,
+                                     static_cast<size_t>(p + 1 - hex_start));
               }
               return false;
             }
@@ -220,20 +226,22 @@
           if (p + 8 >= end) {
             if (error) {
               *error = "\\U must be followed by 8 hex digits: \\" +
-                       std::string(hex_start, p + 1 - hex_start);
+                       std::string(hex_start,
+                                   static_cast<size_t>(p + 1 - hex_start));
             }
             return false;
           }
           for (int i = 0; i < 8; ++i) {
             // Look one char ahead.
-            if (absl::ascii_isxdigit(p[1])) {
+            if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
               // Don't change rune until we're sure this
               // is within the Unicode limit, but do advance p.
               uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p);
               if (newrune > 0x10FFFF) {
                 if (error) {
                   *error = "Value of \\" +
-                           std::string(hex_start, p + 1 - hex_start) +
+                           std::string(hex_start,
+                                       static_cast<size_t>(p + 1 - hex_start)) +
                            " exceeds Unicode limit (0x10FFFF)";
                 }
                 return false;
@@ -243,7 +251,8 @@
             } else {
               if (error) {
                 *error = "\\U must be followed by 8 hex digits: \\" +
-                         std::string(hex_start, p + 1 - hex_start);
+                         std::string(hex_start,
+                                     static_cast<size_t>(p + 1 - hex_start));
               }
               return false;
             }
@@ -291,7 +300,7 @@
                          error)) {
     return false;
   }
-  dest->erase(dest_size);
+  dest->erase(static_cast<size_t>(dest_size));
   return true;
 }
 
@@ -311,7 +320,7 @@
   std::string dest;
   bool last_hex_escape = false;  // true if last output char was \xNN.
 
-  for (unsigned char c : src) {
+  for (char c : src) {
     bool is_hex_escape = false;
     switch (c) {
       case '\n': dest.append("\\" "n"); break;
@@ -320,28 +329,30 @@
       case '\"': dest.append("\\" "\""); break;
       case '\'': dest.append("\\" "'"); break;
       case '\\': dest.append("\\" "\\"); break;
-      default:
+      default: {
         // Note that if we emit \xNN and the src character after that is a hex
         // digit then that digit must be escaped too to prevent it being
         // interpreted as part of the character code by C.
-        if ((!utf8_safe || c < 0x80) &&
-            (!absl::ascii_isprint(c) ||
-             (last_hex_escape && absl::ascii_isxdigit(c)))) {
+        const unsigned char uc = static_cast<unsigned char>(c);
+        if ((!utf8_safe || uc < 0x80) &&
+            (!absl::ascii_isprint(uc) ||
+             (last_hex_escape && absl::ascii_isxdigit(uc)))) {
           if (use_hex) {
             dest.append("\\" "x");
-            dest.push_back(numbers_internal::kHexChar[c / 16]);
-            dest.push_back(numbers_internal::kHexChar[c % 16]);
+            dest.push_back(numbers_internal::kHexChar[uc / 16]);
+            dest.push_back(numbers_internal::kHexChar[uc % 16]);
             is_hex_escape = true;
           } else {
             dest.append("\\");
-            dest.push_back(numbers_internal::kHexChar[c / 64]);
-            dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]);
-            dest.push_back(numbers_internal::kHexChar[c % 8]);
+            dest.push_back(numbers_internal::kHexChar[uc / 64]);
+            dest.push_back(numbers_internal::kHexChar[(uc % 64) / 8]);
+            dest.push_back(numbers_internal::kHexChar[uc % 8]);
           }
         } else {
           dest.push_back(c);
           break;
         }
+      }
     }
     last_hex_escape = is_hex_escape;
   }
@@ -350,7 +361,7 @@
 }
 
 /* clang-format off */
-constexpr char c_escaped_len[256] = {
+constexpr unsigned char c_escaped_len[256] = {
     4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \t, \n, \r
     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
     1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,  // ", '
@@ -375,7 +386,8 @@
 // that UTF-8 bytes are not handled specially.
 inline size_t CEscapedLength(absl::string_view src) {
   size_t escaped_len = 0;
-  for (unsigned char c : src) escaped_len += c_escaped_len[c];
+  for (char c : src)
+    escaped_len += c_escaped_len[static_cast<unsigned char>(c)];
   return escaped_len;
 }
 
@@ -391,8 +403,8 @@
                                                  cur_dest_len + escaped_len);
   char* append_ptr = &(*dest)[cur_dest_len];
 
-  for (unsigned char c : src) {
-    int char_len = c_escaped_len[c];
+  for (char c : src) {
+    size_t char_len = c_escaped_len[static_cast<unsigned char>(c)];
     if (char_len == 1) {
       *append_ptr++ = c;
     } else if (char_len == 2) {
@@ -424,9 +436,9 @@
       }
     } else {
       *append_ptr++ = '\\';
-      *append_ptr++ = '0' + c / 64;
-      *append_ptr++ = '0' + (c % 64) / 8;
-      *append_ptr++ = '0' + c % 8;
+      *append_ptr++ = '0' + static_cast<unsigned char>(c) / 64;
+      *append_ptr++ = '0' + (static_cast<unsigned char>(c) % 64) / 8;
+      *append_ptr++ = '0' + static_cast<unsigned char>(c) % 8;
     }
   }
 }
@@ -440,7 +452,7 @@
   size_t destidx = 0;
   int decode = 0;
   int state = 0;
-  unsigned int ch = 0;
+  unsigned char ch = 0;
   unsigned int temp = 0;
 
   // If "char" is signed by default, using *src as an array index results in
@@ -500,13 +512,13 @@
         // how to handle those cases.
 
         GET_INPUT(first, 4);
-        temp = decode;
+        temp = static_cast<unsigned char>(decode);
         GET_INPUT(second, 3);
-        temp = (temp << 6) | decode;
+        temp = (temp << 6) | static_cast<unsigned char>(decode);
         GET_INPUT(third, 2);
-        temp = (temp << 6) | decode;
+        temp = (temp << 6) | static_cast<unsigned char>(decode);
         GET_INPUT(fourth, 1);
-        temp = (temp << 6) | decode;
+        temp = (temp << 6) | static_cast<unsigned char>(decode);
       } else {
         // We really did have four good data bytes, so advance four
         // characters in the string.
@@ -518,11 +530,11 @@
       // temp has 24 bits of input, so write that out as three bytes.
 
       if (destidx + 3 > szdest) return false;
-      dest[destidx + 2] = temp;
+      dest[destidx + 2] = static_cast<char>(temp);
       temp >>= 8;
-      dest[destidx + 1] = temp;
+      dest[destidx + 1] = static_cast<char>(temp);
       temp >>= 8;
-      dest[destidx] = temp;
+      dest[destidx] = static_cast<char>(temp);
       destidx += 3;
     }
   } else {
@@ -583,18 +595,18 @@
       }
 
       // Each input character gives us six bits of output.
-      temp = (temp << 6) | decode;
+      temp = (temp << 6) | static_cast<unsigned char>(decode);
       ++state;
       if (state == 4) {
         // If we've accumulated 24 bits of output, write that out as
         // three bytes.
         if (dest) {
           if (destidx + 3 > szdest) return false;
-          dest[destidx + 2] = temp;
+          dest[destidx + 2] = static_cast<char>(temp);
           temp >>= 8;
-          dest[destidx + 1] = temp;
+          dest[destidx + 1] = static_cast<char>(temp);
           temp >>= 8;
-          dest[destidx] = temp;
+          dest[destidx] = static_cast<char>(temp);
         }
         destidx += 3;
         state = 0;
@@ -619,7 +631,7 @@
       if (dest) {
         if (destidx + 1 > szdest) return false;
         temp >>= 4;
-        dest[destidx] = temp;
+        dest[destidx] = static_cast<char>(temp);
       }
       ++destidx;
       expected_equals = 2;
@@ -630,9 +642,9 @@
       if (dest) {
         if (destidx + 2 > szdest) return false;
         temp >>= 2;
-        dest[destidx + 1] = temp;
+        dest[destidx + 1] = static_cast<char>(temp);
         temp >>= 8;
-        dest[destidx] = temp;
+        dest[destidx] = static_cast<char>(temp);
       }
       destidx += 2;
       expected_equals = 1;
@@ -822,9 +834,9 @@
 // or a string.  This works because we use the [] operator to access
 // individual characters at a time.
 template <typename T>
-void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
-  for (int i = 0; i < num; i++) {
-    to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
+void HexStringToBytesInternal(const char* from, T to, size_t num) {
+  for (size_t i = 0; i < num; i++) {
+    to[i] = static_cast<char>(kHexValueLenient[from[i * 2] & 0xFF] << 4) +
             (kHexValueLenient[from[i * 2 + 1] & 0xFF]);
   }
 }
@@ -832,7 +844,7 @@
 // This is a templated function so that T can be either a char* or a
 // std::string.
 template <typename T>
-void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
+void BytesToHexStringInternal(const unsigned char* src, T dest, size_t num) {
   auto dest_ptr = &dest[0];
   for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
     const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index e798fc6..2987158 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -190,32 +190,32 @@
     if (i >= 1000) goto lt10_000;
     digits = i / 100;
     i -= digits * 100;
-    *buffer++ = '0' + digits;
+    *buffer++ = '0' + static_cast<char>(digits);
     goto lt100;
   }
   if (i < 1000000) {  //    1,000,000
     if (i >= 100000) goto lt1_000_000;
     digits = i / 10000;  //    10,000
     i -= digits * 10000;
-    *buffer++ = '0' + digits;
+    *buffer++ = '0' + static_cast<char>(digits);
     goto lt10_000;
   }
   if (i < 100000000) {  //    100,000,000
     if (i >= 10000000) goto lt100_000_000;
     digits = i / 1000000;  //   1,000,000
     i -= digits * 1000000;
-    *buffer++ = '0' + digits;
+    *buffer++ = '0' + static_cast<char>(digits);
     goto lt1_000_000;
   }
   // we already know that i < 1,000,000,000
   digits = i / 100000000;  //   100,000,000
   i -= digits * 100000000;
-  *buffer++ = '0' + digits;
+  *buffer++ = '0' + static_cast<char>(digits);
   goto lt100_000_000;
 }
 
 char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) {
-  uint32_t u = i;
+  uint32_t u = static_cast<uint32_t>(i);
   if (i < 0) {
     *buffer++ = '-';
     // We need to do the negation in modular (i.e., "unsigned")
@@ -268,7 +268,7 @@
 }
 
 char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) {
-  uint64_t u = i;
+  uint64_t u = static_cast<uint64_t>(i);
   if (i < 0) {
     *buffer++ = '-';
     u = 0 - u;
@@ -329,7 +329,7 @@
     result = Mul32(result, 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5);
     expfive -= 13;
   }
-  constexpr int powers_of_five[13] = {
+  constexpr uint32_t powers_of_five[13] = {
       1,
       5,
       5 * 5,
@@ -404,14 +404,14 @@
   // we multiply it by 65536 and see if the fractional part is close to 32768.
   // (The number doesn't have to be a power of two,but powers of two are faster)
   uint64_t d64k = d * 65536;
-  int dddddd;  // A 6-digit decimal integer.
+  uint32_t dddddd;  // A 6-digit decimal integer.
   if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) {
     // OK, it's fairly likely that precision was lost above, which is
     // not a surprise given only 52 mantissa bits are available.  Therefore
     // redo the calculation using 128-bit numbers.  (64 bits are not enough).
 
     // Start out with digits rounded down; maybe add one below.
-    dddddd = static_cast<int>(d64k / 65536);
+    dddddd = static_cast<uint32_t>(d64k / 65536);
 
     // mantissa is a 64-bit integer representing M.mmm... * 2^63.  The actual
     // value we're representing, of course, is M.mmm... * 2^exp2.
@@ -461,7 +461,7 @@
     }
   } else {
     // Here, we are not close to the edge.
-    dddddd = static_cast<int>((d64k + 32768) / 65536);
+    dddddd = static_cast<uint32_t>((d64k + 32768) / 65536);
   }
   if (dddddd == 1000000) {
     dddddd = 100000;
@@ -469,7 +469,7 @@
   }
   exp_dig.exponent = exp;
 
-  int two_digits = dddddd / 10000;
+  uint32_t two_digits = dddddd / 10000;
   dddddd -= two_digits * 10000;
   numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
 
@@ -499,7 +499,7 @@
     if (std::signbit(d)) *out++ = '-';
     *out++ = '0';
     *out = 0;
-    return out - buffer;
+    return static_cast<size_t>(out - buffer);
   }
   if (d < 0) {
     *out++ = '-';
@@ -507,7 +507,7 @@
   }
   if (d > std::numeric_limits<double>::max()) {
     strcpy(out, "inf");  // NOLINT(runtime/printf)
-    return out + 3 - buffer;
+    return static_cast<size_t>(out + 3 - buffer);
   }
 
   auto exp_dig = SplitToSix(d);
@@ -519,7 +519,7 @@
     case 5:
       memcpy(out, &digits[0], 6), out += 6;
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
     case 4:
       memcpy(out, &digits[0], 5), out += 5;
       if (digits[5] != '0') {
@@ -527,7 +527,7 @@
         *out++ = digits[5];
       }
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
     case 3:
       memcpy(out, &digits[0], 4), out += 4;
       if ((digits[5] | digits[4]) != '0') {
@@ -536,7 +536,7 @@
         if (digits[5] != '0') *out++ = digits[5];
       }
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
     case 2:
       memcpy(out, &digits[0], 3), out += 3;
       *out++ = '.';
@@ -545,7 +545,7 @@
       while (out[-1] == '0') --out;
       if (out[-1] == '.') --out;
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
     case 1:
       memcpy(out, &digits[0], 2), out += 2;
       *out++ = '.';
@@ -554,7 +554,7 @@
       while (out[-1] == '0') --out;
       if (out[-1] == '.') --out;
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
     case 0:
       memcpy(out, &digits[0], 1), out += 1;
       *out++ = '.';
@@ -563,7 +563,7 @@
       while (out[-1] == '0') --out;
       if (out[-1] == '.') --out;
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
     case -4:
       out[2] = '0';
       ++out;
@@ -582,7 +582,7 @@
       out += 6;
       while (out[-1] == '0') --out;
       *out = 0;
-      return out - buffer;
+      return static_cast<size_t>(out - buffer);
   }
   assert(exp < -4 || exp >= 6);
   out[0] = digits[0];
@@ -601,12 +601,12 @@
   if (exp > 99) {
     int dig1 = exp / 100;
     exp -= dig1 * 100;
-    *out++ = '0' + dig1;
+    *out++ = '0' + static_cast<char>(dig1);
   }
-  PutTwoDigits(exp, out);
+  PutTwoDigits(static_cast<uint32_t>(exp), out);
   out += 2;
   *out = 0;
-  return out - buffer;
+  return static_cast<size_t>(out - buffer);
 }
 
 namespace {
@@ -642,10 +642,12 @@
   int base = *base_ptr;
 
   // Consume whitespace.
-  while (start < end && absl::ascii_isspace(start[0])) {
+  while (start < end &&
+         absl::ascii_isspace(static_cast<unsigned char>(start[0]))) {
     ++start;
   }
-  while (start < end && absl::ascii_isspace(end[-1])) {
+  while (start < end &&
+         absl::ascii_isspace(static_cast<unsigned char>(end[-1]))) {
     --end;
   }
   if (start >= end) {
@@ -694,7 +696,7 @@
   } else {
     return false;
   }
-  *text = absl::string_view(start, end - start);
+  *text = absl::string_view(start, static_cast<size_t>(end - start));
   *base_ptr = base;
   return true;
 }
@@ -920,17 +922,18 @@
   const IntType vmax = std::numeric_limits<IntType>::max();
   assert(vmax > 0);
   assert(base >= 0);
-  assert(vmax >= static_cast<IntType>(base));
+  const IntType base_inttype = static_cast<IntType>(base);
+  assert(vmax >= base_inttype);
   const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
   assert(base < 2 ||
-         std::numeric_limits<IntType>::max() / base == vmax_over_base);
+         std::numeric_limits<IntType>::max() / base_inttype == vmax_over_base);
   const char* start = text.data();
   const char* end = start + text.size();
   // loop over digits
   for (; start < end; ++start) {
     unsigned char c = static_cast<unsigned char>(start[0]);
-    int digit = kAsciiToInt[c];
-    if (digit >= base) {
+    IntType digit = static_cast<IntType>(kAsciiToInt[c]);
+    if (digit >= base_inttype) {
       *value_p = value;
       return false;
     }
@@ -938,7 +941,7 @@
       *value_p = vmax;
       return false;
     }
-    value *= base;
+    value *= base_inttype;
     if (value > vmax - digit) {
       *value_p = vmax;
       return false;
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc
index f4a7749..2f9df67 100644
--- a/absl/strings/str_cat.cc
+++ b/absl/strings/str_cat.cc
@@ -56,7 +56,7 @@
     *--writer = '0' + (value % 10);
     value /= 10;
   }
-  *--writer = '0' + value;
+  *--writer = '0' + static_cast<char>(value);
   if (neg) *--writer = '-';
 
   ptrdiff_t fillers = writer - minfill;
@@ -73,7 +73,7 @@
     if (add_sign_again) *--writer = '-';
   }
 
-  piece_ = absl::string_view(writer, end - writer);
+  piece_ = absl::string_view(writer, static_cast<size_t>(end - writer));
 }
 
 // ----------------------------------------------------------------------
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
index adce3be..e226162 100644
--- a/absl/strings/string_view.cc
+++ b/absl/strings/string_view.cc
@@ -32,7 +32,7 @@
   memset(fill_buf, o.fill(), sizeof(fill_buf));
   while (pad) {
     size_t n = std::min(pad, sizeof(fill_buf));
-    o.write(fill_buf, n);
+    o.write(fill_buf, static_cast<std::streamsize>(n));
     pad -= n;
   }
 }
@@ -63,7 +63,7 @@
     size_t lpad = 0;
     size_t rpad = 0;
     if (static_cast<size_t>(o.width()) > piece.size()) {
-      size_t pad = o.width() - piece.size();
+      size_t pad = static_cast<size_t>(o.width()) - piece.size();
       if ((o.flags() & o.adjustfield) == o.left) {
         rpad = pad;
       } else {
@@ -71,7 +71,7 @@
       }
     }
     if (lpad) WritePadding(o, lpad);
-    o.write(piece.data(), piece.size());
+    o.write(piece.data(), static_cast<std::streamsize>(piece.size()));
     if (rpad) WritePadding(o, rpad);
     o.width(0);
   }
@@ -86,7 +86,7 @@
   }
   const char* result =
       strings_internal::memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_);
-  return result ? result - ptr_ : npos;
+  return result ? static_cast<size_type>(result - ptr_) : npos;
 }
 
 string_view::size_type string_view::find(char c, size_type pos) const noexcept {
@@ -95,7 +95,7 @@
   }
   const char* result =
       static_cast<const char*>(memchr(ptr_ + pos, c, length_ - pos));
-  return result != nullptr ? result - ptr_ : npos;
+  return result != nullptr ? static_cast<size_type>(result - ptr_) : npos;
 }
 
 string_view::size_type string_view::rfind(string_view s,
@@ -104,7 +104,7 @@
   if (s.empty()) return std::min(length_, pos);
   const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
   const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
-  return result != last ? result - ptr_ : npos;
+  return result != last ? static_cast<size_type>(result - ptr_) : npos;
 }
 
 // Search range is [0..pos] inclusive.  If pos == npos, search everything.
diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc
index 8980b19..33a3930 100644
--- a/absl/strings/substitute.cc
+++ b/absl/strings/substitute.cc
@@ -40,7 +40,8 @@
                      absl::CEscape(format).c_str());
 #endif
         return;
-      } else if (absl::ascii_isdigit(format[i + 1])) {
+      } else if (absl::ascii_isdigit(
+                     static_cast<unsigned char>(format[i + 1]))) {
         int index = format[i + 1] - '0';
         if (static_cast<size_t>(index) >= num_args) {
 #ifndef NDEBUG
@@ -80,7 +81,7 @@
   char* target = &(*output)[original_size];
   for (size_t i = 0; i < format.size(); i++) {
     if (format[i] == '$') {
-      if (absl::ascii_isdigit(format[i + 1])) {
+      if (absl::ascii_isdigit(static_cast<unsigned char>(format[i + 1]))) {
         const absl::string_view src = args_array[format[i + 1] - '0'];
         target = std::copy(src.begin(), src.end(), target);
         ++i;  // Skip next char.
@@ -110,7 +111,8 @@
     } while (num != 0);
     *--ptr = 'x';
     *--ptr = '0';
-    piece_ = absl::string_view(ptr, scratch_ + sizeof(scratch_) - ptr);
+    piece_ = absl::string_view(
+        ptr, static_cast<size_t>(scratch_ + sizeof(scratch_) - ptr));
   }
 }
 
@@ -132,7 +134,7 @@
     beg = writer;
   }
 
-  piece_ = absl::string_view(beg, end - beg);
+  piece_ = absl::string_view(beg, static_cast<size_t>(end - beg));
 }
 
 // TODO(jorg): Don't duplicate so much code between here and str_cat.cc
@@ -147,7 +149,7 @@
     *--writer = '0' + (value % 10);
     value /= 10;
   }
-  *--writer = '0' + value;
+  *--writer = '0' + static_cast<char>(value);
   if (neg) *--writer = '-';
 
   ptrdiff_t fillers = writer - minfill;
@@ -164,7 +166,7 @@
     if (add_sign_again) *--writer = '-';
   }
 
-  piece_ = absl::string_view(writer, end - writer);
+  piece_ = absl::string_view(writer, static_cast<size_t>(end - writer));
 }
 
 }  // namespace substitute_internal