diff options
Diffstat (limited to 'gcc-4.9/libstdc++-v3/include/bits')
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/deque.tcc | 16 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/hashtable.h | 146 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/regex_automaton.tcc | 18 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/regex_compiler.h | 11 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/regex_compiler.tcc | 17 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/regex_executor.tcc | 6 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/stl_algo.h | 80 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/stl_bvector.h | 245 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/stl_deque.h | 56 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/stl_tree.h | 44 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/stl_vector.h | 262 | ||||
-rw-r--r-- | gcc-4.9/libstdc++-v3/include/bits/vector.tcc | 52 |
12 files changed, 820 insertions, 133 deletions
diff --git a/gcc-4.9/libstdc++-v3/include/bits/deque.tcc b/gcc-4.9/libstdc++-v3/include/bits/deque.tcc index ebf5d3a0a..972176546 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/deque.tcc +++ b/gcc-4.9/libstdc++-v3/include/bits/deque.tcc @@ -150,6 +150,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque<_Tp, _Alloc>:: emplace(const_iterator __position, _Args&&... __args) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("emplace() at invalid position")); +#endif if (__position._M_cur == this->_M_impl._M_start._M_cur) { emplace_front(std::forward<_Args>(__args)...); @@ -177,6 +181,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(iterator __position, const value_type& __x) #endif { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif if (__position._M_cur == this->_M_impl._M_start._M_cur) { push_front(__x); @@ -198,6 +206,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque<_Tp, _Alloc>:: _M_erase(iterator __position) { +#if __google_stl_debug_deque + if (__position < this->begin() || __position >= this->end()) + __throw_logic_error("erase() at invalid position"); +#endif iterator __next = __position; ++__next; const difference_type __index = __position - begin(); @@ -221,6 +233,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque<_Tp, _Alloc>:: _M_erase(iterator __first, iterator __last) { +#if __google_stl_debug_deque + if (__first < this->begin() || __first > __last || __last > this->end()) + __throw_logic_error("erase() invalid range"); +#endif if (__first == __last) return __first; else if (__first == begin() && __last == end()) diff --git a/gcc-4.9/libstdc++-v3/include/bits/hashtable.h b/gcc-4.9/libstdc++-v3/include/bits/hashtable.h index 22e17d29d..9b6394c4e 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/hashtable.h +++ b/gcc-4.9/libstdc++-v3/include/bits/hashtable.h @@ -316,14 +316,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_type _M_element_count; _RehashPolicy _M_rehash_policy; + // A single bucket used when only need for 1 bucket. Especially + // interesting in move semantic to leave hashtable with only 1 buckets + // which is not allocated so that we can have those operations noexcept + // qualified. + // Note that we can't leave hashtable with 0 bucket without adding + // numerous checks in the code to avoid 0 modulus. + __bucket_type _M_single_bucket; + + bool + _M_uses_single_bucket(__bucket_type* __bkts) const + { return __builtin_expect(_M_buckets == &_M_single_bucket, false); } + + bool + _M_uses_single_bucket() const + { return _M_uses_single_bucket(_M_buckets); } + __hashtable_alloc& _M_base_alloc() { return *this; } - using __hashtable_alloc::_M_deallocate_buckets; + __bucket_type* + _M_allocate_buckets(size_type __n) + { + if (__builtin_expect(__n == 1, false)) + { + _M_single_bucket = nullptr; + return &_M_single_bucket; + } + + return __hashtable_alloc::_M_allocate_buckets(__n); + } + + void + _M_deallocate_buckets(__bucket_type* __bkts, size_type __n) + { + if (_M_uses_single_bucket(__bkts)) + return; + + __hashtable_alloc::_M_deallocate_buckets(__bkts, __n); + } void _M_deallocate_buckets() - { this->_M_deallocate_buckets(_M_buckets, _M_bucket_count); } + { _M_deallocate_buckets(_M_buckets, _M_bucket_count); } // Gets bucket begin, deals with the fact that non-empty buckets contain // their before begin node. @@ -703,11 +738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_type erase(const key_type& __k) - { - if (__builtin_expect(_M_bucket_count == 0, false)) - return 0; - return _M_erase(__unique_keys(), __k); - } + { return _M_erase(__unique_keys(), __k); } iterator erase(const_iterator, const_iterator); @@ -768,7 +799,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_rehash_policy() { _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint); - _M_buckets = this->_M_allocate_buckets(_M_bucket_count); + _M_buckets = _M_allocate_buckets(_M_bucket_count); } template<typename _Key, typename _Value, @@ -796,7 +827,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems), __bucket_hint)); - _M_buckets = this->_M_allocate_buckets(_M_bucket_count); + _M_buckets = _M_allocate_buckets(_M_bucket_count); __try { for (; __f != __l; ++__f) @@ -833,9 +864,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // Replacement allocator cannot free existing storage. this->_M_deallocate_nodes(_M_begin()); - if (__builtin_expect(_M_bucket_count != 0, true)) - _M_deallocate_buckets(); - _M_reset(); + _M_before_begin._M_nxt = nullptr; + _M_deallocate_buckets(); + _M_buckets = nullptr; std::__alloc_on_copy(__this_alloc, __that_alloc); __hashtable_base::operator=(__ht); _M_bucket_count = __ht._M_bucket_count; @@ -867,7 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_bucket_count != __ht._M_bucket_count) { __former_buckets = _M_buckets; - _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count); + _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); _M_bucket_count = __ht._M_bucket_count; } else @@ -885,8 +916,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [&__roan](const __node_type* __n) { return __roan(__n->_M_v()); }); if (__former_buckets) - this->_M_deallocate_buckets(__former_buckets, - __former_bucket_count); + _M_deallocate_buckets(__former_buckets, __former_bucket_count); } __catch(...) { @@ -917,7 +947,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __bucket_type* __buckets = nullptr; if (!_M_buckets) - _M_buckets = __buckets = this->_M_allocate_buckets(_M_bucket_count); + _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count); __try { @@ -964,8 +994,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_reset() noexcept { _M_rehash_policy._M_reset(); - _M_bucket_count = 0; - _M_buckets = nullptr; + _M_bucket_count = 1; + _M_single_bucket = nullptr; + _M_buckets = &_M_single_bucket; _M_before_begin._M_nxt = nullptr; _M_element_count = 0; } @@ -980,12 +1011,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_move_assign(_Hashtable&& __ht, std::true_type) { this->_M_deallocate_nodes(_M_begin()); - if (__builtin_expect(_M_bucket_count != 0, true)) - _M_deallocate_buckets(); - + _M_deallocate_buckets(); __hashtable_base::operator=(std::move(__ht)); _M_rehash_policy = __ht._M_rehash_policy; - _M_buckets = __ht._M_buckets; + if (!__ht._M_uses_single_bucket()) + _M_buckets = __ht._M_buckets; + else + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } _M_bucket_count = __ht._M_bucket_count; _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; _M_element_count = __ht._M_element_count; @@ -1019,7 +1054,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_bucket_count != __ht._M_bucket_count) { __former_buckets = _M_buckets; - _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count); + _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); _M_bucket_count = __ht._M_bucket_count; } else @@ -1093,10 +1128,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_element_count(__ht._M_element_count), _M_rehash_policy(__ht._M_rehash_policy) { + // Update, if necessary, buckets if __ht is using its single bucket. + if (__ht._M_uses_single_bucket()) + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + // Update, if necessary, bucket pointing to before begin that hasn't // moved. if (_M_begin()) _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + __ht._M_reset(); } @@ -1139,7 +1182,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__ht._M_node_allocator() == this->_M_node_allocator()) { - _M_buckets = __ht._M_buckets; + if (__ht._M_uses_single_bucket()) + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + else + _M_buckets = __ht._M_buckets; + _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; // Update, if necessary, bucket pointing to before begin that hasn't // moved. @@ -1189,15 +1239,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator()); std::swap(_M_rehash_policy, __x._M_rehash_policy); - std::swap(_M_buckets, __x._M_buckets); + + // Deal properly with potentially moved instances. + if (this->_M_uses_single_bucket()) + { + if (!__x._M_uses_single_bucket()) + { + _M_buckets = __x._M_buckets; + __x._M_buckets = &__x._M_single_bucket; + } + } + else if (__x._M_uses_single_bucket()) + { + __x._M_buckets = _M_buckets; + _M_buckets = &_M_single_bucket; + } + else + std::swap(_M_buckets, __x._M_buckets); + std::swap(_M_bucket_count, __x._M_bucket_count); std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt); std::swap(_M_element_count, __x._M_element_count); + std::swap(_M_single_bucket, __x._M_single_bucket); // Fix buckets containing the _M_before_begin pointers that can't be // swapped. if (_M_begin()) _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + if (__x._M_begin()) __x._M_buckets[__x._M_bucket_index(__x._M_begin())] = &__x._M_before_begin; @@ -1230,9 +1299,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: find(const key_type& __k) { - if (__builtin_expect(_M_bucket_count == 0, false)) - return end(); - __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); @@ -1250,9 +1316,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: find(const key_type& __k) const { - if (__builtin_expect(_M_bucket_count == 0, false)) - return end(); - __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); @@ -1270,9 +1333,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: count(const key_type& __k) const { - if (__builtin_expect(_M_bucket_count == 0, false)) - return 0; - __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_bucket_begin(__n); @@ -1287,7 +1347,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (__result) // All equivalent values are next to each other, if we // found a non-equivalent value after an equivalent one it - // means that we won't find any more equivalent values. + // means that we won't find any new equivalent value. break; if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n) break; @@ -1311,9 +1371,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: equal_range(const key_type& __k) { - if (__builtin_expect(_M_bucket_count == 0, false)) - return std::make_pair(end(), end()); - __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); @@ -1347,9 +1404,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: equal_range(const key_type& __k) const { - if (__builtin_expect(_M_bucket_count == 0, false)) - return std::make_pair(end(), end()); - __hash_code __code = this->_M_hash_code(__k); std::size_t __n = _M_bucket_index(__k, __code); __node_type* __p = _M_find_node(__n, __k, __code); @@ -1944,7 +1998,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _M_rehash_aux(size_type __n, std::true_type) { - __bucket_type* __new_buckets = this->_M_allocate_buckets(__n); + __bucket_type* __new_buckets = _M_allocate_buckets(__n); __node_type* __p = _M_begin(); _M_before_begin._M_nxt = nullptr; std::size_t __bbegin_bkt = 0; @@ -1969,8 +2023,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __p = __next; } - if (__builtin_expect(_M_bucket_count != 0, true)) - _M_deallocate_buckets(); + _M_deallocate_buckets(); _M_bucket_count = __n; _M_buckets = __new_buckets; } @@ -1986,7 +2039,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _M_rehash_aux(size_type __n, std::false_type) { - __bucket_type* __new_buckets = this->_M_allocate_buckets(__n); + __bucket_type* __new_buckets = _M_allocate_buckets(__n); __node_type* __p = _M_begin(); _M_before_begin._M_nxt = nullptr; @@ -2060,8 +2113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __new_buckets[__next_bkt] = __prev_p; } - if (__builtin_expect(_M_bucket_count != 0, true)) - _M_deallocate_buckets(); + _M_deallocate_buckets(); _M_bucket_count = __n; _M_buckets = __new_buckets; } diff --git a/gcc-4.9/libstdc++-v3/include/bits/regex_automaton.tcc b/gcc-4.9/libstdc++-v3/include/bits/regex_automaton.tcc index 759b053c5..6e68fca82 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/regex_automaton.tcc +++ b/gcc-4.9/libstdc++-v3/include/bits/regex_automaton.tcc @@ -35,7 +35,7 @@ namespace __detail _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef _GLIBCXX_DEBUG - std::ostream& + inline std::ostream& _State_base::_M_print(std::ostream& ostr) const { switch (_M_opcode) @@ -66,7 +66,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // Prints graphviz dot commands for state. - std::ostream& + inline std::ostream& _State_base::_M_dot(std::ostream& __ostr, _StateIdT __id) const { switch (_M_opcode) @@ -197,20 +197,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // _M_insert_state() never return -1 auto __id = _M_nfa._M_insert_state(__dup); __m[__u] = __id; - if (__u == _M_end) - continue; - if (__dup._M_next != _S_invalid_state_id && __m[__dup._M_next] == -1) - __stack.push(__dup._M_next); if (__dup._M_opcode == _S_opcode_alternative || __dup._M_opcode == _S_opcode_subexpr_lookahead) if (__dup._M_alt != _S_invalid_state_id && __m[__dup._M_alt] == -1) __stack.push(__dup._M_alt); + if (__u == _M_end) + continue; + if (__dup._M_next != _S_invalid_state_id && __m[__dup._M_next] == -1) + __stack.push(__dup._M_next); } - long __size = static_cast<long>(__m.size()); - for (long __k = 0; __k < __size; __k++) + for (auto __v : __m) { - long __v; - if ((__v = __m[__k]) == -1) + if (__v == -1) continue; auto& __ref = _M_nfa[__v]; if (__ref._M_next != _S_invalid_state_id) diff --git a/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.h b/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.h index f5a198f65..af76f5505 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.h +++ b/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.h @@ -369,15 +369,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif } + // __neg should be true for \D, \S and \W only. void - _M_add_character_class(const _StringT& __s) + _M_add_character_class(const _StringT& __s, bool __neg) { auto __mask = _M_traits.lookup_classname(__s.data(), __s.data() + __s.size(), __icase); if (__mask == 0) __throw_regex_error(regex_constants::error_ctype); - _M_class_set |= __mask; + if (!__neg) + _M_class_set |= __mask; + else + _M_neg_class_set.push_back(__mask); #ifdef _GLIBCXX_DEBUG _M_is_ready = false; #endif @@ -387,7 +391,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_make_range(_CharT __l, _CharT __r) { _M_range_set.push_back(make_pair(_M_translator._M_transform(__l), - _M_translator._M_transform(__r))); + _M_translator._M_transform(__r))); #ifdef _GLIBCXX_DEBUG _M_is_ready = false; #endif @@ -435,6 +439,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::vector<_CharT> _M_char_set; std::vector<_StringT> _M_equiv_set; std::vector<pair<_StrTransT, _StrTransT>> _M_range_set; + std::vector<_CharClassT> _M_neg_class_set; _CharClassT _M_class_set; _TransT _M_translator; const _TraitsT& _M_traits; diff --git a/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.tcc b/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.tcc index 128dac12b..14e40c0cd 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.tcc +++ b/gcc-4.9/libstdc++-v3/include/bits/regex_compiler.tcc @@ -397,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_DEBUG_ASSERT(_M_value.size() == 1); _BracketMatcher<_TraitsT, __icase, __collate> __matcher (_M_ctype.is(_CtypeT::upper, _M_value[0]), _M_traits); - __matcher._M_add_character_class(_M_value); + __matcher._M_add_character_class(_M_value, false); __matcher._M_ready(); _M_stack.push(_StateSeqT(_M_nfa, _M_nfa._M_insert_matcher(std::move(__matcher)))); @@ -428,7 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (_M_match_token(_ScannerT::_S_token_equiv_class_name)) __matcher._M_add_equivalence_class(_M_value); else if (_M_match_token(_ScannerT::_S_token_char_class_name)) - __matcher._M_add_character_class(_M_value); + __matcher._M_add_character_class(_M_value, false); else if (_M_try_char()) // [a { auto __ch = _M_value[0]; @@ -451,6 +451,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } __matcher._M_add_char(__ch); } + else if (_M_match_token(_ScannerT::_S_token_quoted_class)) + __matcher._M_add_character_class(_M_value, + _M_ctype.is(_CtypeT::upper, + _M_value[0])); else __throw_regex_error(regex_constants::error_brack); } @@ -527,6 +531,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_traits.transform_primary(&__ch, &__ch+1)) != _M_equiv_set.end()) __ret = true; + else + { + for (auto& __it : _M_neg_class_set) + if (!_M_traits.isctype(__ch, __it)) + { + __ret = true; + break; + } + } } if (_M_is_non_matching) return !__ret; diff --git a/gcc-4.9/libstdc++-v3/include/bits/regex_executor.tcc b/gcc-4.9/libstdc++-v3/include/bits/regex_executor.tcc index 68a5e0490..052302b91 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/regex_executor.tcc +++ b/gcc-4.9/libstdc++-v3/include/bits/regex_executor.tcc @@ -120,10 +120,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (_M_match_queue->empty()) break; _M_visited->assign(_M_visited->size(), false); - auto _M_old_queue = std::move(*_M_match_queue); - for (auto __task : _M_old_queue) + auto __old_queue = std::move(*_M_match_queue); + for (auto& __task : __old_queue) { - _M_cur_results = __task.second; + _M_cur_results = std::move(__task.second); _M_dfs<__match_mode>(__task.first); } if (!__match_mode) diff --git a/gcc-4.9/libstdc++-v3/include/bits/stl_algo.h b/gcc-4.9/libstdc++-v3/include/bits/stl_algo.h index 4c6ca8a72..104ab8685 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/stl_algo.h +++ b/gcc-4.9/libstdc++-v3/include/bits/stl_algo.h @@ -199,6 +199,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // count_if // search +// Local modification: if __google_stl_debug_compare is defined to +// non-zero value, check sort predicate for strict weak ordering. +// Google ref b/1731200. +#if __google_stl_debug_compare + template<typename _Compare> + struct _CheckedCompare { + _Compare _M_compare; + + _CheckedCompare(const _Compare & __comp): _M_compare(__comp) { } + + template <typename _Tp> + bool operator()(const _Tp& __x, const _Tp& __y) { + if (_M_compare(__x, __x)) + __throw_runtime_error("strict weak ordering: (__x LT __x) != false"); + if (_M_compare(__y, __y)) + __throw_runtime_error("strict weak ordering: (__y LT __y) != false"); + bool lt = _M_compare(__x, __y); + if (lt && _M_compare(__y, __x)) + __throw_runtime_error("strict weak ordering: ((__x LT __y) && (__y LT __x)) != false"); + return lt; + } + + // Different types; can't perform any checks. + template <typename _Tp1, typename _Tp2> + bool operator()(const _Tp1& __x, const _Tp2& __y) { + return _M_compare(__x, __y); + } + }; +# define __CheckedCompare(__comp) _CheckedCompare<__typeof__(__comp)>(__comp) +#else +# define __CheckedCompare(__comp) __comp +#endif + + template<typename _ForwardIterator1, typename _ForwardIterator2, typename _BinaryPredicate> _ForwardIterator1 @@ -1811,7 +1845,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::__partial_sort_copy(__first, __last, __result_first, __result_last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } /// This is a helper function for the sort routine. @@ -2033,7 +2067,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __val, __comp); return std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp)); + __gnu_cxx::__ops::__iter_comp_val(__CheckedCompare(__comp))); } template<typename _ForwardIterator, typename _Tp, typename _Compare> @@ -2122,7 +2156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __val, __comp); return std::__upper_bound(__first, __last, __val, - __gnu_cxx::__ops::__val_comp_iter(__comp)); + __gnu_cxx::__ops::__val_comp_iter(__CheckedCompare(__comp))); } template<typename _ForwardIterator, typename _Tp, @@ -2237,8 +2271,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __val, __comp); return std::__equal_range(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp), - __gnu_cxx::__ops::__val_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_val(__CheckedCompare(__comp)), + __gnu_cxx::__ops::__val_comp_iter(__CheckedCompare(__comp))); } /** @@ -2307,7 +2341,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __i = std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp)); + __gnu_cxx::__ops::__iter_comp_val(__CheckedCompare(__comp))); return __i != __last && !bool(__comp(__val, *__i)); } @@ -2638,7 +2672,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_sorted_pred(__middle, __last, __comp); std::__inplace_merge(__first, __middle, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } @@ -2890,7 +2924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); return std::__includes(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } // nth_element @@ -2997,7 +3031,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); return std::__next_permutation - (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _BidirectionalIterator, typename _Compare> @@ -3095,7 +3129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); return std::__prev_permutation(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } // replace @@ -3282,7 +3316,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); return std::__is_sorted_until(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } /** @@ -3430,7 +3464,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); return std::__minmax_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__comp)); } // N2722 + DR 915. @@ -4570,7 +4604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__middle, __last); std::__partial_sort(__first, __middle, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } /** @@ -4645,7 +4679,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO std::__introselect(__first, __nth, __last, std::__lg(__last - __first) * 2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } /** @@ -4704,7 +4738,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO typename iterator_traits<_RandomAccessIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _InputIterator1, typename _InputIterator2, @@ -4821,7 +4855,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return _GLIBCXX_STD_A::__merge(__first1, __last1, __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _RandomAccessIterator, typename _Compare> @@ -4908,7 +4942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); _GLIBCXX_STD_A::__stable_sort(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _InputIterator1, typename _InputIterator2, @@ -5033,7 +5067,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return _GLIBCXX_STD_A::__set_union(__first1, __last1, __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _InputIterator1, typename _InputIterator2, @@ -5145,7 +5179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _InputIterator1, typename _InputIterator2, @@ -5263,7 +5297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return _GLIBCXX_STD_A::__set_difference(__first1, __last1, __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _InputIterator1, typename _InputIterator2, @@ -5390,7 +5424,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__CheckedCompare(__comp))); } template<typename _ForwardIterator, typename _Compare> @@ -5450,7 +5484,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); return _GLIBCXX_STD_A::__min_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__comp)); } template<typename _ForwardIterator, typename _Compare> @@ -5509,7 +5543,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); return _GLIBCXX_STD_A::__max_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __gnu_cxx::__ops::__iter_comp_iter(__comp)); } _GLIBCXX_END_NAMESPACE_ALGO diff --git a/gcc-4.9/libstdc++-v3/include/bits/stl_bvector.h b/gcc-4.9/libstdc++-v3/include/bits/stl_bvector.h index 996eb1a8d..86375cb9b 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/stl_bvector.h +++ b/gcc-4.9/libstdc++-v3/include/bits/stl_bvector.h @@ -471,11 +471,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif ~_Bvector_base() - { this->_M_deallocate(); } + { + this->_M_deallocate(); +#if __google_stl_debug_bvector + __builtin_memset(this, 0xcd, sizeof(*this)); +#endif + } protected: _Bvector_impl _M_impl; +#if __google_stl_debug_bvector + bool _M_is_valid() const + { + return (this->_M_impl._M_start._M_p == 0 + && this->_M_impl._M_finish._M_p == 0 + && this->_M_impl._M_end_of_storage == 0) + || (this->_M_impl._M_start._M_p <= this->_M_impl._M_finish._M_p + && this->_M_impl._M_finish._M_p <= this->_M_impl._M_end_of_storage + && (this->_M_impl._M_start._M_p < this->_M_impl._M_end_of_storage + || (this->_M_impl._M_start._M_p == this->_M_impl._M_end_of_storage + && this->_M_impl._M_start._M_offset == 0 + && this->_M_impl._M_finish._M_offset == 0))); + } +#endif + _Bit_type* _M_allocate(size_t __n) { return _M_impl.allocate(_S_nword(__n)); } @@ -631,6 +651,10 @@ template<typename _Alloc> vector& operator=(const vector& __x) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("op=() on corrupt (dangling?) vector"); +#endif if (&__x == this) return *this; if (__x.size() > capacity()) @@ -647,6 +671,10 @@ template<typename _Alloc> vector& operator=(vector&& __x) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("op=() on corrupt (dangling?) vector"); +#endif // NB: DR 1204. // NB: DR 675. this->clear(); @@ -668,19 +696,35 @@ template<typename _Alloc> // or not the type is an integer. void assign(size_type __n, const bool& __x) - { _M_fill_assign(__n, __x); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("assign() on corrupt (dangling?) vector"); +#endif + _M_fill_assign(__n, __x); + } #if __cplusplus >= 201103L template<typename _InputIterator, typename = std::_RequireInputIter<_InputIterator>> void assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("assign() on corrupt (dangling?) vector"); +#endif + _M_assign_dispatch(__first, __last, __false_type()); + } #else template<typename _InputIterator> void assign(_InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("assign() on corrupt (dangling?) vector"); +#endif typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_assign_dispatch(__first, __last, _Integral()); } @@ -694,19 +738,43 @@ template<typename _Alloc> iterator begin() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("begin() on corrupt (dangling?) vector"); +#endif + return this->_M_impl._M_start; + } const_iterator begin() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("begin() on corrupt (dangling?) vector"); +#endif + return this->_M_impl._M_start; + } iterator end() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("end() on corrupt (dangling?) vector"); +#endif + return this->_M_impl._M_finish; + } const_iterator end() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("end() on corrupt (dangling?) vector"); +#endif + return this->_M_impl._M_finish; + } reverse_iterator rbegin() _GLIBCXX_NOEXCEPT @@ -727,11 +795,23 @@ template<typename _Alloc> #if __cplusplus >= 201103L const_iterator cbegin() const noexcept - { return this->_M_impl._M_start; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("cbegin() on corrupt (dangling?) vector"); +#endif + return this->_M_impl._M_start; + } const_iterator cend() const noexcept - { return this->_M_impl._M_finish; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("cend() on corrupt (dangling?) vector"); +#endif + return this->_M_impl._M_finish; + } const_reverse_iterator crbegin() const noexcept @@ -749,6 +829,10 @@ template<typename _Alloc> size_type max_size() const _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("max_size() on corrupt (dangling?) vector"); +#endif const size_type __isize = __gnu_cxx::__numeric_traits<difference_type>::__max - int(_S_word_bit) + 1; @@ -769,6 +853,11 @@ template<typename _Alloc> reference operator[](size_type __n) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("operator[] on corrupt (dangling?) vector"); + _M_range_check(__n); +#endif return *iterator(this->_M_impl._M_start._M_p + __n / int(_S_word_bit), __n % int(_S_word_bit)); } @@ -776,6 +865,11 @@ template<typename _Alloc> const_reference operator[](size_type __n) const { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("operator[] on corrupt (dangling?) vector"); + _M_range_check(__n); +#endif return *const_iterator(this->_M_impl._M_start._M_p + __n / int(_S_word_bit), __n % int(_S_word_bit)); } @@ -794,11 +888,21 @@ template<typename _Alloc> public: reference at(size_type __n) - { _M_range_check(__n); return (*this)[__n]; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("at() on corrupt (dangling?) vector"); +#endif + _M_range_check(__n); return (*this)[__n]; } const_reference at(size_type __n) const - { _M_range_check(__n); return (*this)[__n]; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("at() on corrupt (dangling?) vector"); +#endif + _M_range_check(__n); return (*this)[__n]; } void reserve(size_type __n) @@ -811,19 +915,47 @@ template<typename _Alloc> reference front() - { return *begin(); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("front() on corrupt (dangling?) vector"); + _M_range_check(0); +#endif + return *begin(); + } const_reference front() const - { return *begin(); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("front() on corrupt (dangling?) vector"); + _M_range_check(0); +#endif + return *begin(); + } reference back() - { return *(end() - 1); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("back() on corrupt (dangling?) vector"); + _M_range_check(0); +#endif + return *(end() - 1); + } const_reference back() const - { return *(end() - 1); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("back() on corrupt (dangling?) vector"); + _M_range_check(0); +#endif + return *(end() - 1); + } // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 464. Suggestion for new member functions in standard containers. @@ -836,6 +968,10 @@ template<typename _Alloc> void push_back(bool __x) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("push_back() on corrupt (dangling?) vector"); +#endif if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) *this->_M_impl._M_finish++ = __x; else @@ -845,6 +981,10 @@ template<typename _Alloc> void swap(vector& __x) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid() || !__x._M_is_valid()) + __throw_logic_error("swap() on corrupt (dangling?) vector"); +#endif std::swap(this->_M_impl._M_start, __x._M_impl._M_start); std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish); std::swap(this->_M_impl._M_end_of_storage, @@ -872,6 +1012,12 @@ template<typename _Alloc> insert(iterator __position, const bool& __x = bool()) #endif { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif const difference_type __n = __position - begin(); if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage && __position == end()) @@ -888,6 +1034,12 @@ template<typename _Alloc> insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif difference_type __offset = __position - cbegin(); _M_insert_dispatch(__position._M_const_cast(), __first, __last, __false_type()); @@ -899,6 +1051,12 @@ template<typename _Alloc> insert(iterator __position, _InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_insert_dispatch(__position, __first, __last, _Integral()); } @@ -908,6 +1066,12 @@ template<typename _Alloc> iterator insert(const_iterator __position, size_type __n, const bool& __x) { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif difference_type __offset = __position - cbegin(); _M_fill_insert(__position._M_const_cast(), __n, __x); return begin() + __offset; @@ -915,7 +1079,15 @@ template<typename _Alloc> #else void insert(iterator __position, size_type __n, const bool& __x) - { _M_fill_insert(__position, __n, __x); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("insert() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif + _M_fill_insert(__position, __n, __x); + } #endif #if __cplusplus >= 201103L @@ -926,7 +1098,14 @@ template<typename _Alloc> void pop_back() - { --this->_M_impl._M_finish; } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("pop_back() on corrupt (dangling?) vector"); + _M_range_check(0); +#endif + --this->_M_impl._M_finish; + } iterator #if __cplusplus >= 201103L @@ -934,7 +1113,15 @@ template<typename _Alloc> #else erase(iterator __position) #endif - { return _M_erase(__position._M_const_cast()); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("erase() on corrupt (dangling?) vector"); + if (__position < this->begin() || __position >= this->end()) + __throw_logic_error("erase() at invalid position"); +#endif + return _M_erase(__position._M_const_cast()); + } iterator #if __cplusplus >= 201103L @@ -942,7 +1129,15 @@ template<typename _Alloc> #else erase(iterator __first, iterator __last) #endif - { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("erase() on corrupt (dangling?) vector"); + if (__first < this->begin() || __first > __last || __last > this->end()) + __throw_logic_error("erase() invalid range"); +#endif + return _M_erase(__first._M_const_cast(), __last._M_const_cast()); + } void resize(size_type __new_size, bool __x = bool()) @@ -956,12 +1151,22 @@ template<typename _Alloc> #if __cplusplus >= 201103L void shrink_to_fit() - { _M_shrink_to_fit(); } + { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("shrink_to_fit() on corrupt (dangling?) vector"); +#endif + _M_shrink_to_fit(); + } #endif void flip() _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_bvector + if (!this->_M_is_valid()) + __throw_logic_error("flip() on corrupt (dangling?) vector"); +#endif for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != this->_M_impl._M_end_of_storage; ++__p) *__p = ~*__p; diff --git a/gcc-4.9/libstdc++-v3/include/bits/stl_deque.h b/gcc-4.9/libstdc++-v3/include/bits/stl_deque.h index add8742a1..40ff8d692 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/stl_deque.h +++ b/gcc-4.9/libstdc++-v3/include/bits/stl_deque.h @@ -1247,7 +1247,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference operator[](size_type __n) _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start[difference_type(__n)]; } + { +#if __google_stl_debug_deque + _M_range_check(__n); +#endif + return this->_M_impl._M_start[difference_type(__n)]; + } /** * @brief Subscript access to the data contained in the %deque. @@ -1262,7 +1267,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference operator[](size_type __n) const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start[difference_type(__n)]; } + { +#if __google_stl_debug_deque + _M_range_check(__n); +#endif + return this->_M_impl._M_start[difference_type(__n)]; + } protected: /// Safety check used only from at(). @@ -1319,7 +1329,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference front() _GLIBCXX_NOEXCEPT - { return *begin(); } + { +#if __google_stl_debug_deque + if (empty()) __throw_logic_error("front() on empty deque"); +#endif + return *begin(); + } /** * Returns a read-only (constant) reference to the data at the first @@ -1327,7 +1342,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference front() const _GLIBCXX_NOEXCEPT - { return *begin(); } + { +#if __google_stl_debug_deque + if (empty()) __throw_logic_error("front() on empty deque"); +#endif + return *begin(); + } /** * Returns a read/write reference to the data at the last element of the @@ -1336,6 +1356,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference back() _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_deque + if (empty()) __throw_logic_error("back() on empty deque"); +#endif iterator __tmp = end(); --__tmp; return *__tmp; @@ -1348,6 +1371,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const_reference back() const _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_deque + if (empty()) __throw_logic_error("back() on empty deque"); +#endif const_iterator __tmp = end(); --__tmp; return *__tmp; @@ -1428,6 +1454,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void pop_front() _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_deque + if (empty()) __throw_logic_error("pop_front() on empty deque"); +#endif if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_last - 1) { @@ -1449,6 +1478,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void pop_back() _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_deque + if (empty()) __throw_logic_error("pop_back() on empty deque"); +#endif if (this->_M_impl._M_finish._M_cur != this->_M_impl._M_finish._M_first) { @@ -1540,6 +1572,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator insert(const_iterator __position, size_type __n, const value_type& __x) { +#if __google_stl_debug_deque + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif difference_type __offset = __position - cbegin(); _M_fill_insert(__position._M_const_cast(), __n, __x); return begin() + __offset; @@ -1556,7 +1592,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } + { +#if __google_stl_debug_deque + if (__position < this->begin() || __position > this->end()) + __throw_logic_error("insert() at invalid position"); +#endif + _M_fill_insert(__position, __n, __x); + } #endif #if __cplusplus >= 201103L @@ -1577,6 +1619,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif difference_type __offset = __position - cbegin(); _M_insert_dispatch(__position._M_const_cast(), __first, __last, __false_type()); diff --git a/gcc-4.9/libstdc++-v3/include/bits/stl_tree.h b/gcc-4.9/libstdc++-v3/include/bits/stl_tree.h index cac917ea3..61156dbf7 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/stl_tree.h +++ b/gcc-4.9/libstdc++-v3/include/bits/stl_tree.h @@ -486,7 +486,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } }; + // Local modification: if __google_stl_debug_rbtree is defined to + // non-zero value, check sort predicate for strict weak ordering. + // Google ref b/1731200. +#if __google_stl_debug_rbtree + template<typename _KeyCompare> + struct _CheckedCompare { + _KeyCompare _M_key_compare; + + _CheckedCompare(): _M_key_compare() { } + _CheckedCompare(const _KeyCompare & __comp): _M_key_compare(__comp) { } + + // Template arg required to avoid duplicating code in the two op() + // operators below. User-provided _M_key_compare may not be const, + // but needs to be callable from our const op(). + // Google ref. b/1731200. + template <typename _KeyCompareT> + static bool _M_compare_with(_KeyCompareT& __comp, const _Key& __x, const _Key& __y) { + if (__comp(__x, __x)) + __throw_runtime_error("strict weak ordering: (__x LT __x) != false"); + if (__comp(__y, __y)) + __throw_runtime_error("strict weak ordering: (__y LT __y) != false"); + bool lt = __comp(__x, __y); + if (lt && __comp(__y, __x)) + __throw_runtime_error("strict weak ordering: ((__x LT __y) && (__y LT __x)) != false"); + return lt; + } + bool operator()(const _Key& __x, const _Key& __y) const { + return _M_compare_with(_M_key_compare, __x, __y); + } + + bool operator()(const _Key& __x, const _Key& __y) { + return _M_compare_with(_M_key_compare, __x, __y); + } + + operator _KeyCompare() const { return _M_key_compare; } + }; + + _Rb_tree_impl<_CheckedCompare<_Compare> > _M_impl; +#else _Rb_tree_impl<_Compare> _M_impl; +#endif protected: _Base_ptr& @@ -526,11 +566,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Link_type _M_end() _GLIBCXX_NOEXCEPT - { return static_cast<_Link_type>(&this->_M_impl._M_header); } + { return reinterpret_cast<_Link_type>(&this->_M_impl._M_header); } _Const_Link_type _M_end() const _GLIBCXX_NOEXCEPT - { return static_cast<_Const_Link_type>(&this->_M_impl._M_header); } + { return reinterpret_cast<_Const_Link_type>(&this->_M_impl._M_header); } static const_reference _S_value(_Const_Link_type __x) diff --git a/gcc-4.9/libstdc++-v3/include/bits/stl_vector.h b/gcc-4.9/libstdc++-v3/include/bits/stl_vector.h index c33e2c6ae..f7c735993 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/stl_vector.h +++ b/gcc-4.9/libstdc++-v3/include/bits/stl_vector.h @@ -63,6 +63,20 @@ #include <initializer_list> #endif +#ifdef _GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS +extern "C" void +__sanitizer_annotate_contiguous_container(const void *, const void *, + const void *, const void *); +#else +// When sanitizer annotataions are off, avoid bazillion of no-op +// functions that blow up debug binary size. +#define __sanitizer_vector_annotate_new() +#define __sanitizer_vector_annotate_delete() +#define __sanitizer_vector_annotate_increase(a) +#define __sanitizer_vector_annotate_shrink(a) +#endif // _GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS + + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_CONTAINER @@ -158,7 +172,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ~_Vector_base() _GLIBCXX_NOEXCEPT { _M_deallocate(this->_M_impl._M_start, this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); } + - this->_M_impl._M_start); +#if __google_stl_debug_dangling_vector + this->_M_impl._M_start = 0; + this->_M_impl._M_finish = reinterpret_cast<_Tp*>(~0UL); +#endif + } public: _Vector_impl _M_impl; @@ -243,6 +262,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER using _Base::_M_impl; using _Base::_M_get_Tp_allocator; + bool _M_is_valid() const + { + if (this->_M_impl._M_end_of_storage == 0 + && this->_M_impl._M_start == 0 + && this->_M_impl._M_finish == 0) + return true; + + if (this->_M_impl._M_start <= this->_M_impl._M_finish + && this->_M_impl._M_finish <= this->_M_impl._M_end_of_storage) + { + if (this->_M_impl._M_start < this->_M_impl._M_end_of_storage) + return true; + else if (this->_M_impl._M_start == this->_M_impl._M_end_of_storage + && this->_M_impl._M_start == this->_M_impl._M_finish) + { + pointer _0xcdcd; + + __builtin_memset(&_0xcdcd, 0xcd, sizeof(_0xcdcd)); + return this->_M_impl._M_finish != _0xcdcd; + } + } + + return false; + } + public: // [23.2.4.1] construct/copy/destroy // (assign() and get_allocator() are also listed in this section) @@ -545,7 +589,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator begin() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_start); } + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("begin() on corrupt (dangling?) vector"); +#endif + return iterator(this->_M_impl._M_start); + } /** * Returns a read-only (constant) iterator that points to the @@ -554,7 +604,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_iterator begin() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_start); } + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("begin() on corrupt (dangling?) vector"); +#endif + return const_iterator(this->_M_impl._M_start); + } /** * Returns a read/write iterator that points one past the last @@ -563,7 +619,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ iterator end() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_finish); } + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("end() on corrupt (dangling?) vector"); +#endif + return iterator(this->_M_impl._M_finish); + } /** * Returns a read-only (constant) iterator that points one past @@ -572,7 +634,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_iterator end() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_finish); } + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("end() on corrupt (dangling?) vector"); +#endif + return const_iterator(this->_M_impl._M_finish); + } /** * Returns a read/write reverse iterator that points to the @@ -652,7 +720,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** Returns the number of elements in the %vector. */ size_type size() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("size() on corrupt (dangling?) vector"); +#endif + return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); + } /** Returns the size() of the largest possible %vector. */ size_type @@ -732,7 +806,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ size_type capacity() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_end_of_storage + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("capacity() on corrupt (dangling?) vector"); +#endif + return size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_start); } /** @@ -774,10 +853,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) + * + * Local modification: range checks are performed if + * __google_stl_debug_vector is defined to non-zero. */ reference operator[](size_type __n) _GLIBCXX_NOEXCEPT - { return *(this->_M_impl._M_start + __n); } + { +#if __google_stl_debug_vector + _M_range_check(__n); +#endif + return *(this->_M_impl._M_start + __n); + } /** * @brief Subscript access to the data contained in the %vector. @@ -789,10 +876,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) + * + * Local modification: range checks are performed if + * __google_stl_debug_vector is defined to non-zero. */ const_reference operator[](size_type __n) const _GLIBCXX_NOEXCEPT - { return *(this->_M_impl._M_start + __n); } + { +#if __google_stl_debug_vector + _M_range_check(__n); +#endif + return *(this->_M_impl._M_start + __n); + } protected: /// Safety check used only from at(). @@ -849,7 +944,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference front() _GLIBCXX_NOEXCEPT - { return *begin(); } + { +#if __google_stl_debug_vector + if (empty()) __throw_logic_error("front() on empty vector"); +#endif + return *begin(); + } /** * Returns a read-only (constant) reference to the data at the first @@ -857,7 +957,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference front() const _GLIBCXX_NOEXCEPT - { return *begin(); } + { +#if __google_stl_debug_vector + if (empty()) __throw_logic_error("front() on empty vector"); +#endif + return *begin(); + } /** * Returns a read/write reference to the data at the last @@ -865,7 +970,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ reference back() _GLIBCXX_NOEXCEPT - { return *(end() - 1); } + { +#if __google_stl_debug_vector + if (empty()) __throw_logic_error("back() on empty vector"); +#endif + return *(end() - 1); + } /** * Returns a read-only (constant) reference to the data at the @@ -873,7 +983,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ const_reference back() const _GLIBCXX_NOEXCEPT - { return *(end() - 1); } + { +#if __google_stl_debug_vector + if (empty()) __throw_logic_error("back() on empty vector"); +#endif + return *(end() - 1); + } // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 464. Suggestion for new member functions in standard containers. @@ -888,7 +1003,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER pointer #endif data() _GLIBCXX_NOEXCEPT - { return _M_data_ptr(this->_M_impl._M_start); } + { +#if __google_stl_debug_vector + if (empty()) return 0; +#endif + return _M_data_ptr(this->_M_impl._M_start); + } #if __cplusplus >= 201103L const _Tp* @@ -896,7 +1016,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const_pointer #endif data() const _GLIBCXX_NOEXCEPT - { return _M_data_ptr(this->_M_impl._M_start); } + { +#if __google_stl_debug_vector + if (empty()) return 0; +#endif + return _M_data_ptr(this->_M_impl._M_start); + } // [23.2.4.3] modifiers /** @@ -914,6 +1039,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) { + __sanitizer_vector_annotate_increase(1); _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); ++this->_M_impl._M_finish; @@ -948,8 +1074,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void pop_back() _GLIBCXX_NOEXCEPT { +#if __google_stl_debug_vector + if (this->empty()) + __throw_logic_error(__N("pop_back() on empty vector")); +#endif + size_type __old_size = size(); --this->_M_impl._M_finish; _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + __sanitizer_vector_annotate_shrink(__old_size); } #if __cplusplus >= 201103L @@ -1050,6 +1182,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator insert(const_iterator __position, size_type __n, const value_type& __x) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif difference_type __offset = __position - cbegin(); _M_fill_insert(begin() + __offset, __n, __x); return begin() + __offset; @@ -1070,7 +1206,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } + { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif + _M_fill_insert(__position, __n, __x); + } #endif #if __cplusplus >= 201103L @@ -1095,6 +1237,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(const_iterator __position, _InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif difference_type __offset = __position - cbegin(); _M_insert_dispatch(begin() + __offset, __first, __last, __false_type()); @@ -1120,6 +1266,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(iterator __position, _InputIterator __first, _InputIterator __last) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif // Check whether it's an integral type. If so, it's not an iterator. typedef typename std::__is_integer<_InputIterator>::__type _Integral; _M_insert_dispatch(__position, __first, __last, _Integral()); @@ -1196,6 +1346,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept(_Alloc_traits::_S_nothrow_swap()) #endif { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid() || !__x._M_is_valid()) + __throw_logic_error("swap() on corrupt (dangling?) vector"); +#endif this->_M_impl._M_swap_data(__x._M_impl); _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); @@ -1209,7 +1363,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void clear() _GLIBCXX_NOEXCEPT - { _M_erase_at_end(this->_M_impl._M_start); } + { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid()) + __throw_logic_error("clear() on corrupt (dangling?) vector"); +#endif + _M_erase_at_end(this->_M_impl._M_start); + } protected: /** @@ -1435,8 +1595,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT { + size_type __old_size = size(); std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator()); this->_M_impl._M_finish = __pos; + __sanitizer_vector_annotate_shrink(__old_size); } iterator @@ -1493,6 +1655,72 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_data_ptr(_Ptr __ptr) const { return __ptr; } #endif + +#ifdef _GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS + private: + template<class T, class U> + struct __is_same_allocator { + static void __annotate_contiguous_container(pointer __beg, + pointer __end, + pointer __old_mid, + pointer __new_mid) { } + }; + // The following functions are no-ops outside of AddressSanitizer mode. + // We call annotatations only for the default Allocator because + // other allocators may not meet the AddressSanitizer alignment + // constraints. + // See the documentation for __sanitizer_annotate_contiguous_container + // for more details. + template <class T> struct __is_same_allocator<T, T> { + static void __annotate_contiguous_container(pointer __beg, + pointer __end, + pointer __old_mid, + pointer __new_mid) { + if (__beg) + __sanitizer_annotate_contiguous_container(__beg, + __end, + __old_mid, + __new_mid); + } + }; + + void __annotate_contiguous_container(pointer __beg, + pointer __end, + pointer __old_mid, + pointer __new_mid) + { + __is_same_allocator<_Alloc, std::allocator<_Tp> >:: + __annotate_contiguous_container(__beg, __end, __old_mid, __new_mid); + } + void __sanitizer_vector_annotate_new() + { + __annotate_contiguous_container(_M_impl._M_start, + _M_impl._M_end_of_storage, + _M_impl._M_end_of_storage, + _M_impl._M_finish); + } + void __sanitizer_vector_annotate_delete() + { + __annotate_contiguous_container(_M_impl._M_start, + _M_impl._M_end_of_storage, + _M_impl._M_finish, + _M_impl._M_end_of_storage); + } + void __sanitizer_vector_annotate_increase(size_type __n) + { + __annotate_contiguous_container(_M_impl._M_start, + _M_impl._M_end_of_storage, + _M_impl._M_finish, + _M_impl._M_finish + __n); + } + void __sanitizer_vector_annotate_shrink(size_type __old_size) + { + __annotate_contiguous_container(_M_impl._M_start, + _M_impl._M_end_of_storage, + _M_impl._M_start + __old_size, + _M_impl._M_finish); + } +#endif // _GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS }; diff --git a/gcc-4.9/libstdc++-v3/include/bits/vector.tcc b/gcc-4.9/libstdc++-v3/include/bits/vector.tcc index c937b3887..015ccd60a 100644 --- a/gcc-4.9/libstdc++-v3/include/bits/vector.tcc +++ b/gcc-4.9/libstdc++-v3/include/bits/vector.tcc @@ -73,6 +73,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER pointer __tmp = _M_allocate_and_copy(__n, _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start), _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish)); + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -81,6 +82,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __tmp; this->_M_impl._M_finish = __tmp + __old_size; this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + __sanitizer_vector_annotate_new(); } } @@ -93,6 +95,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) { + __sanitizer_vector_annotate_increase(1); _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, std::forward<_Args>(__args)...); ++this->_M_impl._M_finish; @@ -111,10 +114,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(iterator __position, const value_type& __x) #endif { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("insert() at invalid position")); +#endif const size_type __n = __position - begin(); if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage && __position == end()) { + __sanitizer_vector_annotate_increase(1); _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, __x); ++this->_M_impl._M_finish; } @@ -141,10 +149,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector<_Tp, _Alloc>:: _M_erase(iterator __position) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position >= this->end()) + __throw_out_of_range(__N("erase() at invalid position")); +#endif if (__position + 1 != end()) _GLIBCXX_MOVE3(__position + 1, end(), __position); --this->_M_impl._M_finish; _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + __sanitizer_vector_annotate_shrink(size() + 1); return __position; } @@ -153,6 +166,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector<_Tp, _Alloc>:: _M_erase(iterator __first, iterator __last) { +#if __google_stl_debug_vector + if (__first < this->begin() || __first > __last || __last > this->end()) + __throw_out_of_range("erase() invalid range"); +#endif if (__first != __last) { if (__last != end()) @@ -167,8 +184,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector<_Tp, _Alloc>:: operator=(const vector<_Tp, _Alloc>& __x) { +#if __google_stl_debug_dangling_vector + if (!this->_M_is_valid() || !__x._M_is_valid()) + __throw_logic_error("operator=() on corrupt (dangling?) vector"); +#endif if (&__x != this) { + __sanitizer_vector_annotate_delete(); #if __cplusplus >= 201103L if (_Alloc_traits::_S_propagate_on_copy_assign()) { @@ -216,6 +238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Tp_allocator()); } this->_M_impl._M_finish = this->_M_impl._M_start + __xlen; + __sanitizer_vector_annotate_new(); } return *this; } @@ -227,11 +250,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if (__n > capacity()) { + __sanitizer_vector_annotate_delete(); vector __tmp(__n, __val, _M_get_Tp_allocator()); __tmp.swap(*this); } else if (__n > size()) { + __sanitizer_vector_annotate_increase(__n - size()); std::fill(begin(), end(), __val); std::__uninitialized_fill_n_a(this->_M_impl._M_finish, __n - size(), __val, @@ -271,6 +296,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (__len > capacity()) { pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -279,11 +305,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __tmp; this->_M_impl._M_finish = this->_M_impl._M_start + __len; this->_M_impl._M_end_of_storage = this->_M_impl._M_finish; + __sanitizer_vector_annotate_new(); } else if (size() >= __len) _M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start)); else { + __sanitizer_vector_annotate_increase(__len - size()); _ForwardIterator __mid = __first; std::advance(__mid, size()); std::copy(__first, __mid, this->_M_impl._M_start); @@ -301,10 +329,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector<_Tp, _Alloc>:: emplace(const_iterator __position, _Args&&... __args) { +#if __google_stl_debug_vector + if (__position < this->begin() || __position > this->end()) + __throw_out_of_range(__N("emplace() at invalid position")); +#endif const size_type __n = __position - begin(); if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage && __position == end()) { + __sanitizer_vector_annotate_increase(1); _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, std::forward<_Args>(__args)...); ++this->_M_impl._M_finish; @@ -329,6 +362,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) { + __sanitizer_vector_annotate_increase(1); _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, _GLIBCXX_MOVE(*(this->_M_impl._M_finish - 1))); @@ -389,6 +423,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -397,6 +432,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; + __sanitizer_vector_annotate_new(); } } @@ -433,6 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -441,6 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; + __sanitizer_vector_annotate_new(); } #endif @@ -454,6 +492,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_finish) >= __n) { + __sanitizer_vector_annotate_increase(__n); value_type __x_copy = __x; const size_type __elems_after = end() - __position; pointer __old_finish(this->_M_impl._M_finish); @@ -522,6 +561,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -530,6 +570,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; + __sanitizer_vector_annotate_new(); } } } @@ -545,6 +586,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_finish) >= __n) { + __sanitizer_vector_annotate_increase(__n); std::__uninitialized_default_n_a(this->_M_impl._M_finish, __n, _M_get_Tp_allocator()); this->_M_impl._M_finish += __n; @@ -573,6 +615,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -581,6 +624,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; + __sanitizer_vector_annotate_new(); } } } @@ -592,7 +636,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if (capacity() == size()) return false; - return std::__shrink_to_fit_aux<vector>::_S_do_it(*this); + __sanitizer_vector_annotate_delete(); + bool __res = std::__shrink_to_fit_aux<vector>::_S_do_it(*this); + __sanitizer_vector_annotate_new(); + return __res; } #endif @@ -623,6 +670,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (size_type(this->_M_impl._M_end_of_storage - this->_M_impl._M_finish) >= __n) { + __sanitizer_vector_annotate_increase(__n); const size_type __elems_after = end() - __position; pointer __old_finish(this->_M_impl._M_finish); if (__elems_after > __n) @@ -680,6 +728,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_deallocate(__new_start, __len); __throw_exception_again; } + __sanitizer_vector_annotate_delete(); std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, _M_get_Tp_allocator()); _M_deallocate(this->_M_impl._M_start, @@ -688,6 +737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_start = __new_start; this->_M_impl._M_finish = __new_finish; this->_M_impl._M_end_of_storage = __new_start + __len; + __sanitizer_vector_annotate_new(); } } } |