Export of internal Abseil changes

--
6b5be2524a088d0f4e8475794dc71232a24e94d8 by Abseil Team <absl-team@google.com>:

Enable ABSL_HAVE_ATTRIBUTE_WEAK for Windows with Clang >= 9.0.0

The bug (https://bugs.llvm.org/show_bug.cgi?id=37598) motivated the workaround
was fixed in 9.0.0.

PiperOrigin-RevId: 365682074

--
c16b7784978a370658dce6d82cb7055316a79bcc by Abseil Team <absl-team@google.com>:

Add IsFlat() evaluation to GetFlatAux for RingBuffer

PiperOrigin-RevId: 365666501

--
c064eb686a3c036e093e71126c45f97d3a921569 by Abseil Team <absl-team@google.com>:

Implement C++11 compatible std::remove_cvref added in C++20

PiperOrigin-RevId: 365606639

--
af2e7e055172da914e63c05308aedb68e197661e by Abseil Team <absl-team@google.com>:

Add IsFlat() support to CordRepRing

PiperOrigin-RevId: 365562090

--
2cfeff9280f4967c4f828812bfe153b4e9cbabb7 by Abseil Team <absl-team@google.com>:

Make unit test for TryFlat on 'substring of rep' explicit

PiperOrigin-RevId: 365081382
GitOrigin-RevId: 6b5be2524a088d0f4e8475794dc71232a24e94d8
Change-Id: Ibb577748176217ce237614a6fe77c05375a97003
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 4a8581e..325e2f8 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -131,14 +131,14 @@
 // ABSL_ATTRIBUTE_WEAK
 //
 // Tags a function as weak for the purposes of compilation and linking.
-// Weak attributes currently do not work properly in LLVM's Windows backend,
-// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
+// Weak attributes did not work properly in LLVM's Windows backend before
+// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
 // for further information.
 // The MinGW compiler doesn't complain about the weak attribute until the link
 // step, presumably because Windows doesn't use ELF binaries.
 #if (ABSL_HAVE_ATTRIBUTE(weak) ||                   \
      (defined(__GNUC__) && !defined(__clang__))) && \
-    !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
+    (!defined(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__)
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
 #define ABSL_HAVE_ATTRIBUTE_WEAK 1
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index d5cb5f3..b5427a4 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -499,6 +499,27 @@
 #endif  // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
 };
 
+#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
+template <typename T>
+using remove_cvref = std::remove_cvref<T>;
+
+template <typename T>
+using remove_cvref_t = typename std::remove_cvref<T>::type;
+#else
+// remove_cvref()
+//
+// C++11 compatible implementation of std::remove_cvref which was added in
+// C++20.
+template <typename T>
+struct remove_cvref {
+  using type =
+      typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+};
+
+template <typename T>
+using remove_cvref_t = typename remove_cvref<T>::type;
+#endif
+
 namespace type_traits_internal {
 // is_trivially_copyable()
 //
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 1aafd0d..0ef5b66 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -942,6 +942,34 @@
       absl::type_traits_internal::is_trivially_copyable<Trivial&>::value);
 }
 
+TEST(TypeTraitsTest, TestRemoveCVRef) {
+  EXPECT_TRUE(
+      (std::is_same<typename absl::remove_cvref<int>::type, int>::value));
+  EXPECT_TRUE(
+      (std::is_same<typename absl::remove_cvref<int&>::type, int>::value));
+  EXPECT_TRUE(
+      (std::is_same<typename absl::remove_cvref<int&&>::type, int>::value));
+  EXPECT_TRUE((
+      std::is_same<typename absl::remove_cvref<const int&>::type, int>::value));
+  EXPECT_TRUE(
+      (std::is_same<typename absl::remove_cvref<int*>::type, int*>::value));
+  // Does not remove const in this case.
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int*>::type,
+                            const int*>::value));
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int[2]>::type,
+                            int[2]>::value));
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int(&)[2]>::type,
+                            int[2]>::value));
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int(&&)[2]>::type,
+                            int[2]>::value));
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int[2]>::type,
+                            int[2]>::value));
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int(&)[2]>::type,
+                            int[2]>::value));
+  EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int(&&)[2]>::type,
+                            int[2]>::value));
+}
+
 #define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...)          \
   EXPECT_TRUE((std::is_same<typename std::trait_name<__VA_ARGS__>::type, \
                             absl::trait_name##_t<__VA_ARGS__>>::value))
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 9353375..1c03a61 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -1688,6 +1688,8 @@
   } else if (rep->tag == EXTERNAL) {
     *fragment = absl::string_view(rep->external()->base, rep->length);
     return true;
+  } else if (rep->tag == RING) {
+    return rep->ring()->IsFlat(fragment);
   } else if (rep->tag == SUBSTRING) {
     CordRep* child = rep->substring()->child;
     if (child->tag >= FLAT) {
@@ -1698,6 +1700,9 @@
       *fragment = absl::string_view(
           child->external()->base + rep->substring()->start, rep->length);
       return true;
+    } else if (child->tag == RING) {
+      return child->ring()->IsFlat(rep->substring()->start, rep->length,
+                                   fragment);
     }
   }
   return false;
diff --git a/absl/strings/cord_ring_test.cc b/absl/strings/cord_ring_test.cc
index 7d75e10..3838dfe 100644
--- a/absl/strings/cord_ring_test.cc
+++ b/absl/strings/cord_ring_test.cc
@@ -1559,6 +1559,71 @@
   Unref(result);
 }
 
+TEST_F(CordRingTest, IsFlatSingleFlat) {
+  for (bool external : {false, true}) {
+    SCOPED_TRACE(external ? "With External" : "With Flat");
+    absl::string_view str = "Hello world";
+    CordRep* rep = external ? MakeExternal(str) : MakeFlat(str);
+    CordRepRing* ring = NeedsUnref(CordRepRing::Create(rep));
+
+    // The ring is a single non-fragmented flat:
+    absl::string_view fragment;
+    EXPECT_TRUE(ring->IsFlat(nullptr));
+    EXPECT_TRUE(ring->IsFlat(&fragment));
+    EXPECT_THAT(fragment, Eq("Hello world"));
+    fragment = "";
+    EXPECT_TRUE(ring->IsFlat(0, 11, nullptr));
+    EXPECT_TRUE(ring->IsFlat(0, 11, &fragment));
+    EXPECT_THAT(fragment, Eq("Hello world"));
+
+    // Arbitrary ranges must check true as well.
+    EXPECT_TRUE(ring->IsFlat(1, 4, &fragment));
+    EXPECT_THAT(fragment, Eq("ello"));
+    EXPECT_TRUE(ring->IsFlat(6, 5, &fragment));
+    EXPECT_THAT(fragment, Eq("world"));
+
+    Unref(ring);
+  }
+}
+
+TEST_F(CordRingTest, IsFlatMultiFlat) {
+  for (bool external : {false, true}) {
+    SCOPED_TRACE(external ? "With External" : "With Flat");
+    absl::string_view str1 = "Hello world";
+    absl::string_view str2 = "Halt and catch fire";
+    CordRep* rep1 = external ? MakeExternal(str1) : MakeFlat(str1);
+    CordRep* rep2 = external ? MakeExternal(str2) : MakeFlat(str2);
+    CordRepRing* ring = CordRepRing::Append(CordRepRing::Create(rep1), rep2);
+    NeedsUnref(ring);
+
+    // The ring is fragmented, IsFlat() on the entire cord must be false.
+    EXPECT_FALSE(ring->IsFlat(nullptr));
+    absl::string_view fragment = "Don't touch this";
+    EXPECT_FALSE(ring->IsFlat(&fragment));
+    EXPECT_THAT(fragment, Eq("Don't touch this"));
+
+    // Check for ranges exactly within both flats.
+    EXPECT_TRUE(ring->IsFlat(0, 11, &fragment));
+    EXPECT_THAT(fragment, Eq("Hello world"));
+    EXPECT_TRUE(ring->IsFlat(11, 19, &fragment));
+    EXPECT_THAT(fragment, Eq("Halt and catch fire"));
+
+    // Check for arbitrary partial range inside each flat.
+    EXPECT_TRUE(ring->IsFlat(1, 4, &fragment));
+    EXPECT_THAT(fragment, "ello");
+    EXPECT_TRUE(ring->IsFlat(26, 4, &fragment));
+    EXPECT_THAT(fragment, "fire");
+
+    // Check ranges spanning across both flats
+    fragment = "Don't touch this";
+    EXPECT_FALSE(ring->IsFlat(1, 18, &fragment));
+    EXPECT_FALSE(ring->IsFlat(10, 2, &fragment));
+    EXPECT_THAT(fragment, Eq("Don't touch this"));
+
+    Unref(ring);
+  }
+}
+
 TEST_F(CordRingTest, Dump) {
   std::stringstream ss;
   auto flats = MakeSpan(kFoxFlats);
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index f998242..fb67341 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -187,6 +187,18 @@
   static cord_internal::CordzInfo* GetCordzInfo(const Cord& c) {
     return c.contents_.cordz_info();
   }
+
+  static Cord MakeSubstring(Cord src, size_t offset, size_t length) {
+    Cord cord = src;
+    ABSL_RAW_CHECK(cord.contents_.is_tree(), "Can not be inlined");
+    auto* rep = new cord_internal::CordRepSubstring;
+    rep->tag = cord_internal::SUBSTRING;
+    rep->child = cord.contents_.tree();
+    rep->start = offset;
+    rep->length = length;
+    cord.contents_.replace_tree(rep);
+    return cord;
+  }
 };
 
 ABSL_NAMESPACE_END
@@ -466,8 +478,8 @@
 
 TEST(TryFlat, SubstrFlat) {
   absl::Cord c("longer than 15 bytes");
-  c.RemovePrefix(1);
-  EXPECT_EQ(c.TryFlat(), "onger than 15 bytes");
+  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
+  EXPECT_EQ(sub.TryFlat(), "onger than 15 bytes");
 }
 
 TEST(TryFlat, Concat) {
@@ -482,16 +494,46 @@
 
 TEST(TryFlat, SubstrExternal) {
   absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
-  c.RemovePrefix(1);
-  EXPECT_EQ(c.TryFlat(), "ell");
+  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
+  EXPECT_EQ(sub.TryFlat(), "ell");
 }
 
 TEST(TryFlat, SubstrConcat) {
   absl::Cord c = absl::MakeFragmentedCord({"hello", " world"});
+  absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
+  EXPECT_EQ(sub.TryFlat(), absl::nullopt);
   c.RemovePrefix(1);
   EXPECT_EQ(c.TryFlat(), absl::nullopt);
 }
 
+TEST(TryFlat, CommonlyAssumedInvariants) {
+  // The behavior tested below is not part of the API contract of Cord, but it's
+  // something we intend to be true in our current implementation.  This test
+  // exists to detect and prevent accidental breakage of the implementation.
+  absl::string_view fragments[] = {"A fragmented test",
+                                   " cord",
+                                   " to test subcords",
+                                   " of ",
+                                   "a",
+                                   " cord for",
+                                   " each chunk "
+                                   "returned by the ",
+                                   "iterator"};
+  absl::Cord c = absl::MakeFragmentedCord(fragments);
+  int fragment = 0;
+  int offset = 0;
+  absl::Cord::CharIterator itc = c.char_begin();
+  for (absl::string_view sv : c.Chunks()) {
+    absl::string_view expected = fragments[fragment];
+    absl::Cord subcord1 = c.Subcord(offset, sv.length());
+    absl::Cord subcord2 = absl::Cord::AdvanceAndRead(&itc, sv.size());
+    EXPECT_EQ(subcord1.TryFlat(), expected);
+    EXPECT_EQ(subcord2.TryFlat(), expected);
+    ++fragment;
+    offset += sv.length();
+  }
+}
+
 static bool IsFlat(const absl::Cord& c) {
   return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
 }
diff --git a/absl/strings/internal/cord_rep_ring.h b/absl/strings/internal/cord_rep_ring.h
index c74d335..830f2b2 100644
--- a/absl/strings/internal/cord_rep_ring.h
+++ b/absl/strings/internal/cord_rep_ring.h
@@ -237,6 +237,18 @@
   // Returns the character at `offset`. Requires that `offset < length`.
   char GetCharacter(size_t offset) const;
 
+  // Returns true if this instance manages a single contiguous buffer, in which
+  // case the (optional) output parameter `fragment` is set. Otherwise, the
+  // function returns false, and `fragment` is left unchanged.
+  bool IsFlat(absl::string_view* fragment) const;
+
+  // Returns true if the data starting at `offset` with length `length` is
+  // managed by this instance inside a single contiguous buffer, in which case
+  // the (optional) output parameter `fragment` is set to the contiguous memory
+  // starting at offset `offset` with length `length`. Otherwise, the function
+  // returns false, and `fragment` is left unchanged.
+  bool IsFlat(size_t offset, size_t length, absl::string_view* fragment) const;
+
   // Testing only: set capacity to requested capacity.
   void SetCapacityForTesting(size_t capacity);
 
@@ -576,6 +588,25 @@
   return static_cast<const CordRepRing*>(this);
 }
 
+inline bool CordRepRing::IsFlat(absl::string_view* fragment) const {
+  if (entries() == 1) {
+    if (fragment) *fragment = entry_data(head());
+    return true;
+  }
+  return false;
+}
+
+inline bool CordRepRing::IsFlat(size_t offset, size_t length,
+                                absl::string_view* fragment) const {
+  const Position pos = Find(offset);
+  const absl::string_view data = entry_data(pos.index);
+  if (data.length() >= length && data.length() - length >= pos.offset) {
+    if (fragment) *fragment = data.substr(pos.offset, length);
+    return true;
+  }
+  return false;
+}
+
 std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
 
 #ifdef __clang__