aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libstdc++-v3/include/bits/stl_vector.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libstdc++-v3/include/bits/stl_vector.h')
-rw-r--r--gcc-4.9/libstdc++-v3/include/bits/stl_vector.h262
1 files changed, 245 insertions, 17 deletions
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
};