Skip to content

Commit 71a6743

Browse files
committed
[libc++] Refactor vector's ASan annotations to only ever delete and add the annotations
1 parent 04518e7 commit 71a6743

File tree

2 files changed

+46
-60
lines changed

2 files changed

+46
-60
lines changed

libcxx/include/__utility/scope_guard.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ class __scope_guard {
3737
// C++14 doesn't have mandatory RVO, so we have to provide a declaration even though no compiler will ever generate
3838
// a call to the move constructor.
3939
#if _LIBCPP_STD_VER <= 14
40+
_LIBCPP_DIAGNOSTIC_PUSH
41+
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wundefined-internal")
4042
__scope_guard(__scope_guard&&);
43+
_LIBCPP_DIAGNOSTIC_POP
4144
#else
4245
__scope_guard(__scope_guard&&) = delete;
4346
#endif

libcxx/include/__vector/vector.h

Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include <__utility/is_pointer_in_range.h>
6666
#include <__utility/move.h>
6767
#include <__utility/pair.h>
68+
#include <__utility/scope_guard.h>
6869
#include <__utility/swap.h>
6970
#include <initializer_list>
7071
#include <limits>
@@ -479,9 +480,10 @@ class vector {
479480
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __emplace_back_assume_capacity(_Args&&... __args) {
480481
_LIBCPP_ASSERT_INTERNAL(
481482
size() < capacity(), "We assume that we have enough space to insert an element at the end of the vector");
482-
_ConstructTransaction __tx(*this, 1);
483-
__alloc_traits::construct(this->__alloc_, std::__to_address(__tx.__pos_), std::forward<_Args>(__args)...);
484-
++__tx.__pos_;
483+
__annotate_delete();
484+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
485+
__alloc_traits::construct(this->__alloc_, std::__to_address(__end_), std::forward<_Args>(__args)...);
486+
++__end_;
485487
}
486488

487489
#if _LIBCPP_STD_VER >= 23
@@ -548,9 +550,9 @@ class vector {
548550
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last);
549551

550552
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
551-
size_type __old_size = size();
553+
__annotate_delete();
554+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
552555
__base_destruct_at_end(this->__begin_);
553-
__annotate_shrink(__old_size);
554556
}
555557

556558
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz);
@@ -599,7 +601,7 @@ class vector {
599601

600602
if (__n > 0) {
601603
__vallocate(__n);
602-
__construct_at_end(std::move(__first), std::move(__last), __n);
604+
__construct_at_end(std::move(__first), std::move(__last));
603605
}
604606

605607
__guard.__complete();
@@ -659,8 +661,7 @@ class vector {
659661
__insert_with_size(const_iterator __position, _Iterator __first, _Sentinel __last, difference_type __n);
660662

661663
template <class _InputIterator, class _Sentinel>
662-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void
663-
__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n);
664+
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __construct_at_end(_InputIterator __first, _Sentinel __last);
664665

665666
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n);
666667
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __append(size_type __n, const_reference __x);
@@ -708,9 +709,9 @@ class vector {
708709
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __move_assign(vector& __c, false_type)
709710
_NOEXCEPT_(__alloc_traits::is_always_equal::value);
710711
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __destruct_at_end(pointer __new_last) _NOEXCEPT {
711-
size_type __old_size = size();
712+
__annotate_delete();
713+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
712714
__base_destruct_at_end(__new_last);
713-
__annotate_shrink(__old_size);
714715
}
715716

716717
template <class... _Args>
@@ -737,33 +738,11 @@ class vector {
737738
__annotate_contiguous_container(data() + size(), data() + capacity());
738739
}
739740

740-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_increase(size_type __n) const _NOEXCEPT {
741-
__annotate_contiguous_container(data() + size(), data() + size() + __n);
742-
}
743-
744-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_shrink(size_type __old_size) const _NOEXCEPT {
745-
__annotate_contiguous_container(data() + __old_size, data() + size());
746-
}
747-
748-
struct _ConstructTransaction {
749-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI explicit _ConstructTransaction(vector& __v, size_type __n)
750-
: __v_(__v), __pos_(__v.__end_), __new_end_(__v.__end_ + __n) {
751-
__v_.__annotate_increase(__n);
752-
}
753-
754-
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI ~_ConstructTransaction() {
755-
__v_.__end_ = __pos_;
756-
if (__pos_ != __new_end_) {
757-
__v_.__annotate_shrink(__new_end_ - __v_.__begin_);
758-
}
759-
}
760-
761-
vector& __v_;
762-
pointer __pos_;
763-
const_pointer const __new_end_;
741+
struct __annotate_new_size {
742+
vector& __vec_;
764743

765-
_ConstructTransaction(_ConstructTransaction const&) = delete;
766-
_ConstructTransaction& operator=(_ConstructTransaction const&) = delete;
744+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __annotate_new_size(vector& __vec) : __vec_(__vec) {}
745+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void operator()() { __vec_.__annotate_new(__vec_.size()); }
767746
};
768747

769748
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __base_destruct_at_end(pointer __new_last) _NOEXCEPT {
@@ -850,6 +829,7 @@ template <class _Tp, class _Allocator>
850829
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
851830
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v) {
852831
__annotate_delete();
832+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
853833
auto __new_begin = __v.__begin_ - (__end_ - __begin_);
854834
std::__uninitialized_allocator_relocate(
855835
this->__alloc_, std::__to_address(__begin_), std::__to_address(__end_), std::__to_address(__new_begin));
@@ -859,7 +839,6 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
859839
std::swap(this->__end_, __v.__end_);
860840
std::swap(this->__cap_, __v.__cap_);
861841
__v.__first_ = __v.__begin_;
862-
__annotate_new(size());
863842
}
864843

865844
// __swap_out_circular_buffer relocates the objects in [__begin_, __p) into the front of __v, the objects in
@@ -870,6 +849,7 @@ template <class _Tp, class _Allocator>
870849
_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::pointer
871850
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p) {
872851
__annotate_delete();
852+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
873853
pointer __ret = __v.__begin_;
874854

875855
// Relocate [__p, __end_) first to avoid having a hole in [__begin_, __end_)
@@ -889,7 +869,6 @@ vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, a
889869
std::swap(this->__end_, __v.__end_);
890870
std::swap(this->__cap_, __v.__cap_);
891871
__v.__first_ = __v.__begin_;
892-
__annotate_new(size());
893872
return __ret;
894873
}
895874

@@ -923,10 +902,12 @@ vector<_Tp, _Allocator>::__recommend(size_type __new_size) const {
923902
// Postcondition: size() == size() + __n
924903
template <class _Tp, class _Allocator>
925904
_LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(size_type __n) {
926-
_ConstructTransaction __tx(*this, __n);
927-
const_pointer __new_end = __tx.__new_end_;
928-
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
929-
__alloc_traits::construct(this->__alloc_, std::__to_address(__pos));
905+
__annotate_delete();
906+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
907+
908+
for (size_t __i = 0; __i != __n; ++__i) {
909+
__alloc_traits::construct(this->__alloc_, std::__to_address(__end_));
910+
++__end_;
930911
}
931912
}
932913

@@ -939,19 +920,21 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void vector<_Tp, _Allocator>::__construct_at_end(s
939920
template <class _Tp, class _Allocator>
940921
_LIBCPP_CONSTEXPR_SINCE_CXX20 inline void
941922
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x) {
942-
_ConstructTransaction __tx(*this, __n);
943-
const_pointer __new_end = __tx.__new_end_;
944-
for (pointer __pos = __tx.__pos_; __pos != __new_end; __tx.__pos_ = ++__pos) {
945-
__alloc_traits::construct(this->__alloc_, std::__to_address(__pos), __x);
923+
__annotate_delete();
924+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
925+
926+
for (size_t __i = 0; __i != __n; ++__i) {
927+
__alloc_traits::construct(this->__alloc_, std::__to_address(__end_), __x);
928+
++__end_;
946929
}
947930
}
948931

949932
template <class _Tp, class _Allocator>
950933
template <class _InputIterator, class _Sentinel>
951934
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
952-
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last, size_type __n) {
953-
_ConstructTransaction __tx(*this, __n);
954-
__tx.__pos_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __tx.__pos_);
935+
vector<_Tp, _Allocator>::__construct_at_end(_InputIterator __first, _Sentinel __last) {
936+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
937+
__end_ = std::__uninitialized_allocator_copy(this->__alloc_, std::move(__first), std::move(__last), __end_);
955938
}
956939

957940
// Default constructs __n objects starting at __end_
@@ -1068,20 +1051,19 @@ vector<_Tp, _Allocator>::__assign_with_size(_Iterator __first, _Sentinel __last,
10681051
if (__new_size > size()) {
10691052
#if _LIBCPP_STD_VER >= 23
10701053
auto __mid = ranges::copy_n(std::move(__first), size(), this->__begin_).in;
1071-
__construct_at_end(std::move(__mid), std::move(__last), __new_size - size());
10721054
#else
10731055
_Iterator __mid = std::next(__first, size());
10741056
std::copy(__first, __mid, this->__begin_);
1075-
__construct_at_end(__mid, __last, __new_size - size());
10761057
#endif
1058+
__construct_at_end(std::move(__mid), std::move(__last));
10771059
} else {
10781060
pointer __m = std::__copy(std::move(__first), __last, this->__begin_).second;
10791061
this->__destruct_at_end(__m);
10801062
}
10811063
} else {
10821064
__vdeallocate();
10831065
__vallocate(__recommend(__new_size));
1084-
__construct_at_end(std::move(__first), std::move(__last), __new_size);
1066+
__construct_at_end(std::move(__first), std::move(__last));
10851067
}
10861068
}
10871069

@@ -1189,15 +1171,16 @@ vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) {
11891171
template <class _Tp, class _Allocator>
11901172
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
11911173
vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
1174+
__annotate_delete();
1175+
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
11921176
pointer __old_last = this->__end_;
11931177
difference_type __n = __old_last - __to;
1194-
{
1195-
pointer __i = __from_s + __n;
1196-
_ConstructTransaction __tx(*this, __from_e - __i);
1197-
for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
1198-
__alloc_traits::construct(this->__alloc_, std::__to_address(__pos), std::move(*__i));
1199-
}
1178+
1179+
for (pointer __i = __from_s + __n; __i != __from_e; ++__i) {
1180+
__alloc_traits::construct(this->__alloc_, std::__to_address(__end_), std::move(*__i));
1181+
++__end_;
12001182
}
1183+
12011184
std::move_backward(__from_s, __from_s + __n, __old_last);
12021185
}
12031186

@@ -1338,13 +1321,13 @@ vector<_Tp, _Allocator>::__insert_with_size(
13381321
if (__n > __dx) {
13391322
#if _LIBCPP_STD_VER >= 23
13401323
if constexpr (!forward_iterator<_Iterator>) {
1341-
__construct_at_end(std::move(__first), std::move(__last), __n);
1324+
__construct_at_end(std::move(__first), std::move(__last));
13421325
std::rotate(__p, __old_last, this->__end_);
13431326
} else
13441327
#endif
13451328
{
13461329
_Iterator __m = std::next(__first, __dx);
1347-
__construct_at_end(__m, __last, __n - __dx);
1330+
__construct_at_end(__m, __last);
13481331
if (__dx > 0) {
13491332
__move_range(__p, __old_last, __p + __n);
13501333
__insert_assign_n_unchecked(__first, __dx, __p);

0 commit comments

Comments
 (0)