about summary refs log tree commit diff
path: root/absl
diff options
context:
space:
mode:
Diffstat (limited to 'absl')
-rw-r--r--absl/algorithm/container.h10
-rw-r--r--absl/algorithm/container_test.cc13
-rw-r--r--absl/base/attributes.h6
-rw-r--r--absl/container/inlined_vector.h29
-rw-r--r--absl/container/internal/inlined_vector.h16
5 files changed, 49 insertions, 25 deletions
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 752e47b23939..c84de461ac28 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -510,6 +510,16 @@ OutputIterator c_move(C&& src, OutputIterator dest) {
                    container_algorithm_internal::c_end(src), dest);
 }
 
+// c_move_backward()
+//
+// Container-based version of the <algorithm> `std::move_backward()` function to
+// move a container's elements into an iterator in reverse order.
+template <typename C, typename BidirectionalIterator>
+BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) {
+  return std::move_backward(container_algorithm_internal::c_begin(src),
+                            container_algorithm_internal::c_end(src), dest);
+}
+
 // c_swap_ranges()
 //
 // Container-based version of the <algorithm> `std::swap_ranges()` function to
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 04282b8947a0..86bf9d3ea327 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -636,6 +636,19 @@ TEST(MutatingTest, Move) {
                                 Pointee(5)));
 }
 
+TEST(MutatingTest, MoveBackward) {
+  std::vector<std::unique_ptr<int>> actual;
+  actual.emplace_back(absl::make_unique<int>(1));
+  actual.emplace_back(absl::make_unique<int>(2));
+  actual.emplace_back(absl::make_unique<int>(3));
+  actual.emplace_back(absl::make_unique<int>(4));
+  actual.emplace_back(absl::make_unique<int>(5));
+  auto subrange = absl::MakeSpan(actual.data(), 3);
+  absl::c_move_backward(subrange, actual.end());
+  EXPECT_THAT(actual, ElementsAre(IsNull(), IsNull(), Pointee(1), Pointee(2),
+                                  Pointee(3)));
+}
+
 TEST(MutatingTest, MoveWithRvalue) {
   auto MakeRValueSrc = [] {
     std::vector<std::unique_ptr<int>> src;
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 48195d6170d0..a7da62af73e5 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -232,7 +232,7 @@
 // out of bounds or does other scary things with memory.
 // NOTE: GCC supports AddressSanitizer(asan) since 4.8.
 // https://gcc.gnu.org/gcc-4.8/changes.html
-#if defined(__GNUC__) && defined(ADDRESS_SANITIZER)
+#if defined(__GNUC__)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
@@ -246,7 +246,7 @@
 // This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals
 // with initialized-ness rather than addressability issues.
 // NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
-#if defined(__GNUC__) && defined(MEMORY_SANITIZER)
+#if defined(__clang__)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
@@ -257,7 +257,7 @@
 // Tells the ThreadSanitizer to not instrument a given function.
 // NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.
 // https://gcc.gnu.org/gcc-4.8/changes.html
-#if defined(__GNUC__) && defined(THREAD_SANITIZER)
+#if defined(__GNUC__)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 784b07f446a5..e67885c2fc5d 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -507,12 +507,13 @@ class InlinedVector {
   template <typename InputIterator,
             DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
   void assign(InputIterator first, InputIterator last) {
-    size_type assign_index = 0;
-    for (; (assign_index < size()) && (first != last);
-         static_cast<void>(++assign_index), static_cast<void>(++first)) {
-      *(data() + assign_index) = *first;
+    size_type i = 0;
+    for (; i < size() && first != last; ++i, static_cast<void>(++first)) {
+      at(i) = *first;
     }
-    erase(data() + assign_index, data() + size());
+
+    erase(data() + i, data() + size());
+
     std::copy(first, last, std::back_inserter(*this));
   }
 
@@ -595,12 +596,15 @@ class InlinedVector {
   template <typename InputIterator,
             DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
   iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
-    size_type initial_insert_index = std::distance(cbegin(), pos);
-    for (size_type insert_index = initial_insert_index; first != last;
-         static_cast<void>(++insert_index), static_cast<void>(++first)) {
-      insert(data() + insert_index, *first);
+    assert(pos >= begin());
+    assert(pos <= end());
+
+    size_type index = std::distance(cbegin(), pos);
+    for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
+      insert(data() + i, *first);
     }
-    return iterator(data() + initial_insert_index);
+
+    return iterator(data() + index);
   }
 
   // `InlinedVector::emplace()`
@@ -677,6 +681,7 @@ class InlinedVector {
   // by `1` (unless the inlined vector is empty, in which case this is a no-op).
   void pop_back() noexcept {
     assert(!empty());
+
     AllocatorTraits::destroy(*storage_.GetAllocPtr(), data() + (size() - 1));
     storage_.SubtractSize(1);
   }
@@ -731,7 +736,9 @@ class InlinedVector {
   // Destroys all elements in the inlined vector, sets the size of `0` and
   // deallocates the heap allocation if the inlined vector was allocated.
   void clear() noexcept {
-    storage_.DestroyAndDeallocate();
+    inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), data(),
+                                             size());
+    storage_.DeallocateIfAllocated();
     storage_.SetInlinedSize(0);
   }
 
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index a84b5255a82e..c2802c823a8d 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -275,7 +275,11 @@ class Storage {
   explicit Storage(const allocator_type& alloc)
       : metadata_(alloc, /* empty and inlined */ 0) {}
 
-  ~Storage() { DestroyAndDeallocate(); }
+  ~Storage() {
+    pointer data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();
+    inlined_vector_internal::DestroyElements(GetAllocPtr(), data, GetSize());
+    DeallocateIfAllocated();
+  }
 
   size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; }
 
@@ -377,8 +381,6 @@ class Storage {
     data_ = other_storage.data_;
   }
 
-  void DestroyAndDeallocate();
-
   template <typename ValueAdapter>
   void Initialize(ValueAdapter values, size_type new_size);
 
@@ -433,14 +435,6 @@ class Storage {
 };
 
 template <typename T, size_t N, typename A>
-void Storage<T, N, A>::DestroyAndDeallocate() {
-  inlined_vector_internal::DestroyElements(
-      GetAllocPtr(), (GetIsAllocated() ? GetAllocatedData() : GetInlinedData()),
-      GetSize());
-  DeallocateIfAllocated();
-}
-
-template <typename T, size_t N, typename A>
 template <typename ValueAdapter>
 auto Storage<T, N, A>::Initialize(ValueAdapter values, size_type new_size)
     -> void {