diff --git a/include/__config b/include/__config index 54ef541c..92e53191 100644 --- a/include/__config +++ b/include/__config @@ -525,10 +525,25 @@ template struct __static_assert_check {}; #define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) #endif // _LIBCPP_HAS_NO_STRONG_ENUMS +#ifdef _LIBCPP_DEBUG2 +# if _LIBCPP_DEBUG2 == 0 +# define _LIBCPP_DEBUG_LEVEL 1 +# elif _LIBCPP_DEBUG2 == 1 +# define _LIBCPP_DEBUG_LEVEL 2 +# else +# error Supported values for _LIBCPP_DEBUG2 are 0 and 1 +# endif +# define _LIBCPP_EXTERN_TEMPLATE(...) +#endif + #ifndef _LIBCPP_EXTERN_TEMPLATE #define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__; #endif +#ifndef _LIBCPP_EXTERN_TEMPLATE2 +#define _LIBCPP_EXTERN_TEMPLATE2(...) extern template __VA_ARGS__; +#endif + #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || defined(__sun__) || defined(__NetBSD__) #define _LIBCPP_LOCALE__L_EXTENSIONS 1 #endif @@ -544,16 +559,6 @@ template struct __static_assert_check {}; #define _LIBCPP_WCTYPE_IS_MASK #endif -#ifdef _LIBCPP_DEBUG2 -# if _LIBCPP_DEBUG2 == 0 -# define _LIBCPP_DEBUG_LEVEL 1 -# elif _LIBCPP_DEBUG2 == 1 -# define _LIBCPP_DEBUG_LEVEL 2 -# else -# error Supported values for _LIBCPP_DEBUG2 are 0 and 1 -# endif -#endif - #ifndef _LIBCPP_STD_VER # if __cplusplus <= 201103L # define _LIBCPP_STD_VER 11 diff --git a/include/__debug b/include/__debug index bac580cf..f1805adc 100644 --- a/include/__debug +++ b/include/__debug @@ -11,6 +11,10 @@ #ifndef _LIBCPP_DEBUG_H #define _LIBCPP_DEBUG_H +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + #if _LIBCPP_DEBUG_LEVEL >= 1 # include @@ -24,10 +28,6 @@ #if _LIBCPP_DEBUG_LEVEL >= 2 -#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) -#pragma GCC system_header -#endif - _LIBCPP_BEGIN_NAMESPACE_STD struct _LIBCPP_TYPE_VIS __c_node; @@ -38,8 +38,15 @@ struct _LIBCPP_TYPE_VIS __i_node __i_node* __next_; __c_node* __c_; +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS __i_node(const __i_node&) = delete; __i_node& operator=(const __i_node&) = delete; +#else +private: + __i_node(const __i_node&); + __i_node& operator=(const __i_node&); +public: +#endif _LIBCPP_INLINE_VISIBILITY __i_node(void* __i, __i_node* __next, __c_node* __c) : __i_(__i), __next_(__next), __c_(__c) {} @@ -54,8 +61,15 @@ struct _LIBCPP_TYPE_VIS __c_node __i_node** end_; __i_node** cap_; +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS __c_node(const __c_node&) = delete; __c_node& operator=(const __c_node&) = delete; +#else +private: + __c_node(const __c_node&); + __c_node& operator=(const __c_node&); +public: +#endif _LIBCPP_INLINE_VISIBILITY __c_node(void* __c, __c_node* __next) : __c_(__c), __next_(__next), beg_(nullptr), end_(nullptr), cap_(nullptr) {} @@ -134,8 +148,15 @@ class _LIBCPP_TYPE_VIS __libcpp_db __libcpp_db(); public: +#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS __libcpp_db(const __libcpp_db&) = delete; __libcpp_db& operator=(const __libcpp_db&) = delete; +#else +private: + __libcpp_db(const __libcpp_db&); + __libcpp_db& operator=(const __libcpp_db&); +public: +#endif ~__libcpp_db(); class __db_c_iterator; diff --git a/include/__locale b/include/__locale index 9c51f9ef..2c144d20 100644 --- a/include/__locale +++ b/include/__locale @@ -256,8 +256,8 @@ collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) const return static_cast(__h); } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS collate) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS collate) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS collate) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS collate) // template class collate_byname; @@ -1147,10 +1147,10 @@ codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname() { } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS codecvt_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS codecvt_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS codecvt_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname) _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*); diff --git a/include/algorithm b/include/algorithm index 03b872a7..442e100f 100644 --- a/include/algorithm +++ b/include/algorithm @@ -1692,6 +1692,8 @@ __unwrap_iter(move_iterator<_Tp*> __i) return __i.base(); } +#if _LIBCPP_DEBUG_LEVEL < 2 + template inline _LIBCPP_INLINE_VISIBILITY typename enable_if @@ -1704,6 +1706,8 @@ __unwrap_iter(__wrap_iter<_Tp*> __i) return __i.base(); } +#endif // _LIBCPP_DEBUG_LEVEL < 2 + template inline _LIBCPP_INLINE_VISIBILITY _OutputIterator diff --git a/include/iterator b/include/iterator index 87d6d1d2..8e92e6fe 100644 --- a/include/iterator +++ b/include/iterator @@ -1197,12 +1197,13 @@ public: _LIBCPP_INLINE_VISIBILITY iterator_type base() const _NOEXCEPT {return __i;} private: - _LIBCPP_INLINE_VISIBILITY __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {} #if _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY __wrap_iter(const void* __p, iterator_type __x) : __i(__x) { __get_db()->__insert_ic(this, __p); } +#else + _LIBCPP_INLINE_VISIBILITY __wrap_iter(iterator_type __x) _NOEXCEPT : __i(__x) {} #endif template friend class __wrap_iter; diff --git a/include/locale b/include/locale index 8877192e..768bb39b 100644 --- a/include/locale +++ b/include/locale @@ -687,8 +687,8 @@ __num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __ex return 0; } -_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_TYPE_VIS __num_get) -_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_TYPE_VIS __num_get) +_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get) +_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_get) template > class _LIBCPP_TYPE_VIS_ONLY num_get @@ -1436,8 +1436,8 @@ num_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, return __b; } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS num_get) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS num_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_get) struct _LIBCPP_TYPE_VIS __num_put_base { @@ -1586,8 +1586,8 @@ __num_put<_CharT>::__widen_and_group_float(char* __nb, char* __np, char* __ne, __op = __ob + (__np - __nb); } -_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_TYPE_VIS __num_put) -_LIBCPP_EXTERN_TEMPLATE(struct _LIBCPP_TYPE_VIS __num_put) +_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put) +_LIBCPP_EXTERN_TEMPLATE2(struct _LIBCPP_TYPE_VIS __num_put) template > class _LIBCPP_TYPE_VIS_ONLY num_put @@ -1770,7 +1770,12 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, return do_put(__s, __iob, __fl, (unsigned long)__v); const numpunct& __np = use_facet >(__iob.getloc()); typedef typename numpunct::string_type string_type; +#if _LIBCPP_DEBUG_LEVEL >= 2 + string_type __tmp(__v ? __np.truename() : __np.falsename()); + string_type __nm = _VSTD::move(__tmp); +#else string_type __nm = __v ? __np.truename() : __np.falsename(); +#endif for (typename string_type::iterator __i = __nm.begin(); __i != __nm.end(); ++__i, ++__s) *__s = *__i; return __s; @@ -2066,8 +2071,8 @@ num_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base& __iob, return __pad_and_output(__s, __o, __op, __oe, __iob, __fl); } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS num_put) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS num_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS num_put) template _LIBCPP_HIDDEN @@ -2733,8 +2738,8 @@ time_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, return __b; } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_get) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get) class _LIBCPP_TYPE_VIS __time_get { @@ -2816,8 +2821,8 @@ private: virtual const string_type& __X() const {return this->__X_;} }; -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_get_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_get_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_get_byname) class _LIBCPP_TYPE_VIS __time_put { @@ -2929,8 +2934,8 @@ time_put<_CharT, _OutputIterator>::do_put(iter_type __s, ios_base&, return _VSTD::copy(__nb, __ne, __s); } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_put) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put) template > class _LIBCPP_TYPE_VIS_ONLY time_put_byname @@ -2950,8 +2955,8 @@ protected: ~time_put_byname() {} }; -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_put_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS time_put_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS time_put_byname) // money_base @@ -3017,10 +3022,10 @@ template const bool moneypunct<_CharT, _International>::intl; -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct) // moneypunct_byname @@ -3074,10 +3079,10 @@ template<> void moneypunct_byname::init(const char*); template<> void moneypunct_byname::init(const char*); template<> void moneypunct_byname::init(const char*); -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS moneypunct_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS moneypunct_byname) // money_get @@ -3133,8 +3138,8 @@ __money_get<_CharT>::__gather_info(bool __intl, const locale& __loc, } } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS __money_get) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS __money_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_get) template > class _LIBCPP_TYPE_VIS_ONLY money_get @@ -3514,8 +3519,8 @@ money_get<_CharT, _InputIterator>::do_get(iter_type __b, iter_type __e, return __b; } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS money_get) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS money_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_get) // money_put @@ -3689,8 +3694,8 @@ __money_put<_CharT>::__format(char_type* __mb, char_type*& __mi, char_type*& __m __mi = __mb; } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS __money_put) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS __money_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS __money_put) template > class _LIBCPP_TYPE_VIS_ONLY money_put @@ -3846,8 +3851,8 @@ money_put<_CharT, _OutputIterator>::do_put(iter_type __s, bool __intl, return __pad_and_output(__s, __mb, __mi, __me, __iob, __fl); } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS money_put) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS money_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS money_put) // messages @@ -3956,8 +3961,8 @@ messages<_CharT>::do_close(catalog __c) const #endif // !_WIN32 } -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS messages) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS messages) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages) template class _LIBCPP_TYPE_VIS_ONLY messages_byname @@ -3980,8 +3985,8 @@ protected: ~messages_byname() {} }; -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS messages_byname) -_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS messages_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname) +_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS messages_byname) template, diff --git a/include/regex b/include/regex index 776bc653..cc06e0b3 100644 --- a/include/regex +++ b/include/regex @@ -3785,7 +3785,7 @@ basic_regex<_CharT, _Traits>::__parse_expression_term(_ForwardIterator __first, } __ml->__add_range(_VSTD::move(__start_range), _VSTD::move(__end_range)); } - else + else if (!__start_range.empty()) { if (__start_range.size() == 1) __ml->__add_char(__start_range[0]); @@ -3793,7 +3793,7 @@ basic_regex<_CharT, _Traits>::__parse_expression_term(_ForwardIterator __first, __ml->__add_digraph(__start_range[0], __start_range[1]); } } - else + else if (!__start_range.empty()) { if (__start_range.size() == 1) __ml->__add_char(__start_range[0]); diff --git a/include/string b/include/string index 7439b561..761ff523 100644 --- a/include/string +++ b/include/string @@ -447,7 +447,7 @@ basic_string operator "" s( const char32_t *str, size_t len ); // C++1 #ifndef _LIBCPP_HAS_NO_UNICODE_CHARS #include #endif -#if defined(_LIBCPP_NO_EXCEPTIONS) || defined(_LIBCPP_DEBUG) +#if defined(_LIBCPP_NO_EXCEPTIONS) #include #endif @@ -605,6 +605,7 @@ inline _LIBCPP_INLINE_VISIBILITY _CharT* char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n) { + _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); char_type* __r = __s1; for (; __n; --__n, ++__s1, ++__s2) assign(*__s1, *__s2); @@ -656,7 +657,10 @@ struct _LIBCPP_TYPE_VIS_ONLY char_traits {return (char_type*)memmove(__s1, __s2, __n);} _LIBCPP_INLINE_VISIBILITY static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) - {return (char_type*)memcpy(__s1, __s2, __n);} + { + _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + return (char_type*)memcpy(__s1, __s2, __n); + } _LIBCPP_INLINE_VISIBILITY static char_type* assign(char_type* __s, size_t __n, char_type __a) {return (char_type*)memset(__s, to_int_type(__a), __n);} @@ -713,7 +717,10 @@ struct _LIBCPP_TYPE_VIS_ONLY char_traits {return (char_type*)wmemmove(__s1, __s2, __n);} _LIBCPP_INLINE_VISIBILITY static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) - {return (char_type*)wmemcpy(__s1, __s2, __n);} + { + _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); + return (char_type*)wmemcpy(__s1, __s2, __n); + } _LIBCPP_INLINE_VISIBILITY static char_type* assign(char_type* __s, size_t __n, char_type __a) {return (char_type*)wmemset(__s, __a, __n);} @@ -841,6 +848,7 @@ inline _LIBCPP_INLINE_VISIBILITY char16_t* char_traits::copy(char_type* __s1, const char_type* __s2, size_t __n) { + _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); char_type* __r = __s1; for (; __n; --__n, ++__s1, ++__s2) assign(*__s1, *__s2); @@ -961,6 +969,7 @@ inline _LIBCPP_INLINE_VISIBILITY char32_t* char_traits::copy(char_type* __s1, const char_type* __s2, size_t __n) { + _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range"); char_type* __r = __s1; for (; __n; --__n, ++__s1, ++__s2) assign(*__s1, *__s2); @@ -1072,13 +1081,13 @@ public: typedef const value_type& const_reference; typedef typename __alloc_traits::pointer pointer; typedef typename __alloc_traits::const_pointer const_pointer; -#ifdef _LIBCPP_DEBUG - typedef __debug_iter iterator; - typedef __debug_iter const_iterator; - friend class __debug_iter; - friend class __debug_iter; -#elif defined(_LIBCPP_RAW_ITERATORS) + static_assert(is_pod::value, "Character type of basic_string must be a POD"); + static_assert((is_same<_CharT, value_type>::value), + "traits_type::char_type must be the same type as CharT"); + static_assert((is_same::value), + "Allocator::value_type must be same type as value_type"); +#if defined(_LIBCPP_RAW_ITERATORS) typedef pointer iterator; typedef const_pointer const_iterator; #else // defined(_LIBCPP_RAW_ITERATORS) @@ -1152,9 +1161,9 @@ private: #endif // _LIBCPP_ALTERNATE_STRING_LAYOUT - union __lx{__long __lx; __short __lxx;}; + union __ulx{__long __lx; __short __lxx;}; - enum {__n_words = sizeof(__lx) / sizeof(size_type)}; + enum {__n_words = sizeof(__ulx) / sizeof(size_type)}; struct __raw { @@ -1173,15 +1182,6 @@ private: __compressed_pair<__rep, allocator_type> __r_; -#ifdef _LIBCPP_DEBUG - - pair __iterator_list_; - - _LIBCPP_INLINE_VISIBILITY iterator*& __get_iterator_list(iterator*) {return __iterator_list_.first;} - _LIBCPP_INLINE_VISIBILITY const_iterator*& __get_iterator_list(const_iterator*) {return __iterator_list_.second;} - -#endif // _LIBCPP_DEBUG - public: static const size_type npos = -1; @@ -1239,7 +1239,20 @@ public: basic_string& operator=(initializer_list __il) {return assign(__il.begin(), __il.size());} #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS -#ifndef _LIBCPP_DEBUG +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_INLINE_VISIBILITY + iterator begin() _NOEXCEPT + {return iterator(this, __get_pointer());} + _LIBCPP_INLINE_VISIBILITY + const_iterator begin() const _NOEXCEPT + {return const_iterator(this, __get_pointer());} + _LIBCPP_INLINE_VISIBILITY + iterator end() _NOEXCEPT + {return iterator(this, __get_pointer() + size());} + _LIBCPP_INLINE_VISIBILITY + const_iterator end() const _NOEXCEPT + {return const_iterator(this, __get_pointer() + size());} +#else _LIBCPP_INLINE_VISIBILITY iterator begin() _NOEXCEPT {return iterator(__get_pointer());} @@ -1252,12 +1265,7 @@ public: _LIBCPP_INLINE_VISIBILITY const_iterator end() const _NOEXCEPT {return const_iterator(__get_pointer() + size());} -#else // _LIBCPP_DEBUG - _LIBCPP_INLINE_VISIBILITY iterator begin() {return iterator(this, __get_pointer());} - _LIBCPP_INLINE_VISIBILITY const_iterator begin() const {return const_iterator(this, data());} - _LIBCPP_INLINE_VISIBILITY iterator end() {return iterator(this, __get_pointer() + size());} - _LIBCPP_INLINE_VISIBILITY const_iterator end() const {return const_iterator(this, data() + size());} -#endif // _LIBCPP_DEBUG +#endif // _LIBCPP_DEBUG_LEVEL >= 2 _LIBCPP_INLINE_VISIBILITY reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());} @@ -1520,6 +1528,15 @@ public: bool __is_long() const _NOEXCEPT {return bool(__r_.first().__s.__size_ & __short_mask);} +#if _LIBCPP_DEBUG_LEVEL >= 2 + + bool __dereferenceable(const const_iterator* __i) const; + bool __decrementable(const const_iterator* __i) const; + bool __addable(const const_iterator* __i, ptrdiff_t __n) const; + bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + private: _LIBCPP_INLINE_VISIBILITY allocator_type& __alloc() _NOEXCEPT @@ -1732,60 +1749,43 @@ private: }; template -#ifndef _LIBCPP_DEBUG _LIBCPP_INLINE_VISIBILITY inline -#endif void basic_string<_CharT, _Traits, _Allocator>::__invalidate_all_iterators() { -#ifdef _LIBCPP_DEBUG - iterator::__remove_all(this); - const_iterator::__remove_all(this); -#endif // _LIBCPP_DEBUG +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__invalidate_all(this); +#endif // _LIBCPP_DEBUG_LEVEL >= 2 } template -#ifndef _LIBCPP_DEBUG _LIBCPP_INLINE_VISIBILITY inline -#endif void basic_string<_CharT, _Traits, _Allocator>::__invalidate_iterators_past(size_type -#ifdef _LIBCPP_DEBUG +#if _LIBCPP_DEBUG_LEVEL >= 2 __pos #endif ) { -#ifdef _LIBCPP_DEBUG - const_iterator __beg = begin(); - if (__iterator_list_.first) +#if _LIBCPP_DEBUG_LEVEL >= 2 + __c_node* __c = __get_db()->__find_c_and_lock(this); + if (__c) { - for (iterator* __p = __iterator_list_.first; __p;) + const_pointer __new_last = __get_pointer() + __pos; + for (__i_node** __p = __c->end_; __p != __c->beg_; ) { - if (*__p - __beg > static_cast(__pos)) + --__p; + const_iterator* __i = static_cast((*__p)->__i_); + if (__i->base() > __new_last) { - iterator* __n = __p; - __p = __p->__next; - __n->__remove_owner(); + (*__p)->__c_ = nullptr; + if (--__c->end_ != __p) + memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); } - else - __p = __p->__next; } + __get_db()->unlock(); } - if (__iterator_list_.second) - { - for (const_iterator* __p = __iterator_list_.second; __p;) - { - if (*__p - __beg > static_cast(__pos)) - { - const_iterator* __n = __p; - __p = __p->__next; - __n->__remove_owner(); - } - else - __p = __p->__next; - } - } -#endif // _LIBCPP_DEBUG +#endif // _LIBCPP_DEBUG_LEVEL >= 2 } template @@ -1793,6 +1793,9 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string() _NOEXCEPT_(is_nothrow_default_constructible::value) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif __zero(); } @@ -1801,6 +1804,9 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const allocator_type& __a) : __r_(__a) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif __zero(); } @@ -1856,10 +1862,11 @@ template _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*) detected nullptr"); __init(__s, traits_type::length(__s)); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -1867,20 +1874,22 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, const allocator_type& __a) : __r_(__a) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "basic_string(const char*, allocator) detected nullptr"); __init(__s, traits_type::length(__s)); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, size_type __n) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n) detected nullptr"); __init(__s, __n); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -1888,10 +1897,11 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(const value_type* __s, size_type __n, const allocator_type& __a) : __r_(__a) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "basic_string(const char*, n, allocator) detected nullptr"); __init(__s, __n); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -1902,6 +1912,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st __r_.first().__r = __str.__r_.first().__r; else __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -1912,6 +1925,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st __r_.first().__r = __str.__r_.first().__r; else __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -1923,8 +1939,10 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str) : __r_(_VSTD::move(__str.__r_)) { __str.__zero(); -#ifdef _LIBCPP_DEBUG - __str.__invalidate_all_iterators(); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); + if (__is_long()) + __get_db()->swap(this, &__str); #endif } @@ -1938,8 +1956,10 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(basic_string&& __str, co else __init(_VSTD::__to_raw_pointer(__str.__get_long_pointer()), __str.__get_long_size()); __str.__zero(); -#ifdef _LIBCPP_DEBUG - __str.__invalidate_all_iterators(); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); + if (__is_long()) + __get_db()->swap(this, &__str); #endif } @@ -1974,6 +1994,9 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, value_type __c) { __init(__n, __c); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -1982,6 +2005,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(size_type __n, value_typ : __r_(__a) { __init(__n, __c); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -1993,6 +2019,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(const basic_string& __st if (__pos > __str_sz) this->__throw_out_of_range(); __init(__str.data() + __pos, _VSTD::min(__n, __str_sz - __pos)); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -2060,6 +2089,9 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, _InputIterator __last) { __init(__first, __last); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -2070,6 +2102,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(_InputIterator __first, : __r_(__a) { __init(__first, __last); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } #ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS @@ -2079,6 +2114,9 @@ _LIBCPP_INLINE_VISIBILITY inline basic_string<_CharT, _Traits, _Allocator>::basic_string(initializer_list __il) { __init(__il.begin(), __il.end()); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__insert_c(this); +#endif } template @@ -2087,6 +2125,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(initializer_list= 2 + __get_db()->__insert_c(this); +#endif } #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS @@ -2094,7 +2135,9 @@ basic_string<_CharT, _Traits, _Allocator>::basic_string(initializer_list basic_string<_CharT, _Traits, _Allocator>::~basic_string() { - __invalidate_all_iterators(); +#if _LIBCPP_DEBUG_LEVEL >= 2 + __get_db()->__erase_c(this); +#endif if (__is_long()) __alloc_traits::deallocate(__alloc(), __get_long_pointer(), __get_long_cap()); } @@ -2166,9 +2209,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s, size_type __n) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::assign recieved nullptr"); size_type __cap = capacity(); if (__cap >= __n) { @@ -2342,9 +2383,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::assign recieved nullptr"); return assign(__s, traits_type::length(__s)); } @@ -2354,9 +2393,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s, size_type __n) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::append recieved nullptr"); size_type __cap = capacity(); size_type __sz = size(); if (__cap - __sz >= __n) @@ -2493,9 +2530,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::append recieved nullptr"); return append(__s, traits_type::length(__s)); } @@ -2505,9 +2540,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s, size_type __n) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::insert recieved nullptr"); size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); @@ -2576,13 +2609,22 @@ typename enable_if >::type basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, + "string::insert(iterator, range) called with an iterator not" + " referring to this string"); +#endif size_type __old_sz = size(); difference_type __ip = __pos - begin(); for (; __first != __last; ++__first) push_back(*__first); pointer __p = __get_pointer(); _VSTD::rotate(__p + __ip, __p + __old_sz, __p + size()); +#if _LIBCPP_DEBUG_LEVEL >= 2 + return iterator(this, __p + __ip); +#else return iterator(__p + __ip); +#endif } template @@ -2594,6 +2636,11 @@ typename enable_if >::type basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, + "string::insert(iterator, range) called with an iterator not" + " referring to this string"); +#endif size_type __ip = static_cast(__pos - begin()); size_type __sz = size(); size_type __cap = capacity(); @@ -2645,9 +2692,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::insert recieved nullptr"); return insert(__pos, __s, traits_type::length(__s)); } @@ -2682,6 +2727,11 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, size_type __n, value_type __c) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, + "string::insert(iterator, n, value) called with an iterator not" + " referring to this string"); +#endif difference_type __p = __pos - begin(); insert(static_cast(__p), __n, __c); return begin() + __p; @@ -2693,9 +2743,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::replace recieved nullptr"); size_type __sz = size(); if (__pos > __sz) this->__throw_out_of_range(); @@ -2827,9 +2875,7 @@ template basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::replace recieved nullptr"); return replace(__pos, __n1, __s, traits_type::length(__s)); } @@ -2895,6 +2941,13 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __pos) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__pos) == this, + "string::erase(iterator) called with an iterator not" + " referring to this string"); +#endif + _LIBCPP_ASSERT(__pos != end(), + "string::erase(iterator) called with a non-dereferenceable iterator"); iterator __b = begin(); size_type __r = static_cast(__pos - __b); erase(__r, 1); @@ -2906,6 +2959,12 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::iterator basic_string<_CharT, _Traits, _Allocator>::erase(const_iterator __first, const_iterator __last) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, + "string::erase(iterator, iterator) called with an iterator not" + " referring to this string"); +#endif + _LIBCPP_ASSERT(__first <= __last, "string::erase(first, last) called with invalid range"); iterator __b = begin(); size_type __r = static_cast(__first - __b); erase(__r, static_cast(__last - __first)); @@ -2917,9 +2976,7 @@ _LIBCPP_INLINE_VISIBILITY inline void basic_string<_CharT, _Traits, _Allocator>::pop_back() { -#ifdef _LIBCPP_DEBUG - assert(!empty()); -#endif + _LIBCPP_ASSERT(!empty(), "string::pop_back(): string is already empty"); size_type __sz; if (__is_long()) { @@ -3064,9 +3121,7 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) const { -#ifdef __LIBCPP_DEBUG - assert(__pos <= size()); -#endif + _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds"); return *(data() + __pos); } @@ -3075,9 +3130,7 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::operator[](size_type __pos) { -#ifdef __LIBCPP_DEBUG - assert(__pos < size()); -#endif + _LIBCPP_ASSERT(__pos <= size(), "string index out of bounds"); return *(__get_pointer() + __pos); } @@ -3104,9 +3157,7 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::front() { -#ifdef _LIBCPP_DEBUG - assert(!empty()); -#endif + _LIBCPP_ASSERT(!empty(), "string::front(): string is empty"); return *__get_pointer(); } @@ -3115,9 +3166,7 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::front() const { -#ifdef _LIBCPP_DEBUG - assert(!empty()); -#endif + _LIBCPP_ASSERT(!empty(), "string::front(): string is empty"); return *data(); } @@ -3126,9 +3175,7 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::reference basic_string<_CharT, _Traits, _Allocator>::back() { -#ifdef _LIBCPP_DEBUG - assert(!empty()); -#endif + _LIBCPP_ASSERT(!empty(), "string::back(): string is empty"); return *(__get_pointer() + size() - 1); } @@ -3137,9 +3184,7 @@ _LIBCPP_INLINE_VISIBILITY inline typename basic_string<_CharT, _Traits, _Allocator>::const_reference basic_string<_CharT, _Traits, _Allocator>::back() const { -#ifdef _LIBCPP_DEBUG - assert(!empty()); -#endif + _LIBCPP_ASSERT(!empty(), "string::back(): string is empty"); return *(data() + size() - 1); } @@ -3170,12 +3215,15 @@ basic_string<_CharT, _Traits, _Allocator>::swap(basic_string& __str) _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable::value) { +#if _LIBCPP_DEBUG_LEVEL >= 2 + if (!__is_long()) + __get_db()->__invalidate_all(this); + if (!__str.__is_long()) + __get_db()->__invalidate_all(&__str); + __get_db()->swap(this, &__str); +#endif _VSTD::swap(__r_.first(), __str.__r_.first()); __swap_alloc(__alloc(), __str.__alloc()); -#ifdef _LIBCPP_DEBUG - __invalidate_all_iterators(); - __str.__invalidate_all_iterators(); -#endif // _LIBCPP_DEBUG } // find @@ -3195,9 +3243,7 @@ basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find(): recieved nullptr"); size_type __sz = size(); if (__pos > __sz || __sz - __pos < __n) return npos; @@ -3226,9 +3272,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find(const value_type* __s, size_type __pos) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::find(): recieved nullptr"); return find(__s, __pos, traits_type::length(__s)); } @@ -3255,9 +3299,7 @@ basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::rfind(): recieved nullptr"); size_type __sz = size(); __pos = _VSTD::min(__pos, __sz); if (__n < __sz - __pos) @@ -3287,9 +3329,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::rfind(const value_type* __s, size_type __pos) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::rfind(): recieved nullptr"); return rfind(__s, __pos, traits_type::length(__s)); } @@ -3323,9 +3363,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_of(): recieved nullptr"); size_type __sz = size(); if (__pos >= __sz || __n == 0) return npos; @@ -3352,9 +3390,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_of(const value_type* __s, size_type __pos) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::find_first_of(): recieved nullptr"); return find_first_of(__s, __pos, traits_type::length(__s)); } @@ -3375,9 +3411,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos, size_type __n) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_of(): recieved nullptr"); if (__n != 0) { size_type __sz = size(); @@ -3411,9 +3445,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_of(const value_type* __s, size_type __pos) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::find_last_of(): recieved nullptr"); return find_last_of(__s, __pos, traits_type::length(__s)); } @@ -3434,9 +3466,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* _ size_type __pos, size_type __n) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_first_not_of(): recieved nullptr"); size_type __sz = size(); if (__pos < __sz) { @@ -3464,9 +3494,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_first_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::find_first_not_of(): recieved nullptr"); return find_first_not_of(__s, __pos, traits_type::length(__s)); } @@ -3496,9 +3524,7 @@ basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __ size_type __pos, size_type __n) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n == 0 || __s != nullptr, "string::find_last_not_of(): recieved nullptr"); size_type __sz = size(); if (__pos < __sz) ++__pos; @@ -3526,9 +3552,7 @@ typename basic_string<_CharT, _Traits, _Allocator>::size_type basic_string<_CharT, _Traits, _Allocator>::find_last_not_of(const value_type* __s, size_type __pos) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::find_last_not_of(): recieved nullptr"); return find_last_not_of(__s, __pos, traits_type::length(__s)); } @@ -3599,9 +3623,7 @@ template int basic_string<_CharT, _Traits, _Allocator>::compare(const value_type* __s) const _NOEXCEPT { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::compare(): recieved nullptr"); return compare(0, npos, __s, traits_type::length(__s)); } @@ -3611,9 +3633,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, size_type __n1, const value_type* __s) const { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__s != nullptr, "string::compare(): recieved nullptr"); return compare(__pos1, __n1, __s, traits_type::length(__s)); } @@ -3624,9 +3644,7 @@ basic_string<_CharT, _Traits, _Allocator>::compare(size_type __pos1, const value_type* __s, size_type __n2) const { -#ifdef _LIBCPP_DEBUG - assert(__s != 0); -#endif + _LIBCPP_ASSERT(__n2 == 0 || __s != nullptr, "string::compare(): recieved nullptr"); size_type __sz = size(); if (__pos1 > __sz || __n2 == npos) this->__throw_out_of_range(); @@ -4102,6 +4120,42 @@ getline(basic_istream<_CharT, _Traits>&& __is, #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES +#if _LIBCPP_DEBUG_LEVEL >= 2 + +template +bool +basic_string<_CharT, _Traits, _Allocator>::__dereferenceable(const const_iterator* __i) const +{ + return this->data() <= _VSTD::__to_raw_pointer(__i->base()) && + _VSTD::__to_raw_pointer(__i->base()) < this->data() + this->size(); +} + +template +bool +basic_string<_CharT, _Traits, _Allocator>::__decrementable(const const_iterator* __i) const +{ + return this->data() < _VSTD::__to_raw_pointer(__i->base()) && + _VSTD::__to_raw_pointer(__i->base()) <= this->data() + this->size(); +} + +template +bool +basic_string<_CharT, _Traits, _Allocator>::__addable(const const_iterator* __i, ptrdiff_t __n) const +{ + const value_type* __p = _VSTD::__to_raw_pointer(__i->base()) + __n; + return this->data() <= __p && __p <= this->data() + this->size(); +} + +template +bool +basic_string<_CharT, _Traits, _Allocator>::__subscriptable(const const_iterator* __i, ptrdiff_t __n) const +{ + const value_type* __p = _VSTD::__to_raw_pointer(__i->base()) + __n; + return this->data() <= __p && __p < this->data() + this->size(); +} + +#endif // _LIBCPP_DEBUG_LEVEL >= 2 + #if _LIBCPP_STD_VER > 11 // Literal suffixes for basic_string [basic.string.literals] // inline // Deviation from N3690. @@ -4140,10 +4194,7 @@ namespace literals _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS basic_string) _LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS basic_string) - -extern template - string - operator+, allocator >(char const*, string const&); +_LIBCPP_EXTERN_TEMPLATE(string operator+, allocator >(char const*, string const&)) _LIBCPP_END_NAMESPACE_STD diff --git a/src/debug.cpp b/src/debug.cpp index c9b09b7a..e840b221 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -118,20 +118,19 @@ void __libcpp_db::__insert_ic(void* __i, const void* __c) { WLock _(mut()); - __i_node* i = __insert_iterator(__i); - const char* errmsg = - "Container constructed in a translation unit with debug mode disabled." - " But it is being used in a translation unit with debug mode enabled." - " Enable it in the other translation unit with #define _LIBCPP_DEBUG2 1"; - _LIBCPP_ASSERT(__cbeg_ != __cend_, errmsg); + if (__cbeg_ == __cend_) + return; size_t hc = hash()(__c) % static_cast(__cend_ - __cbeg_); __c_node* c = __cbeg_[hc]; - _LIBCPP_ASSERT(c != nullptr, errmsg); + if (c == nullptr) + return; while (c->__c_ != __c) { c = c->__next_; - _LIBCPP_ASSERT(c != nullptr, errmsg); + if (c == nullptr) + return; } + __i_node* i = __insert_iterator(__i); c->__add(i); i->__c_ = c; } @@ -217,18 +216,23 @@ void __libcpp_db::__invalidate_all(void* __c) { WLock _(mut()); - size_t hc = hash()(__c) % static_cast(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all A"); - while (p->__c_ != __c) + if (__cend_ != __cbeg_) { - p = p->__next_; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all B"); - } - while (p->end_ != p->beg_) - { - --p->end_; - (*p->end_)->__c_ = nullptr; + size_t hc = hash()(__c) % static_cast(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + if (p == nullptr) + return; + while (p->__c_ != __c) + { + p = p->__next_; + if (p == nullptr) + return; + } + while (p->end_ != p->beg_) + { + --p->end_; + (*p->end_)->__c_ = nullptr; + } } } @@ -236,13 +240,26 @@ __c_node* __libcpp_db::__find_c_and_lock(void* __c) const { mut().lock(); + if (__cend_ == __cbeg_) + { + mut().unlock(); + return nullptr; + } size_t hc = hash()(__c) % static_cast(__cend_ - __cbeg_); __c_node* p = __cbeg_[hc]; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock A"); + if (p == nullptr) + { + mut().unlock(); + return nullptr; + } while (p->__c_ != __c) { p = p->__next_; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock B"); + if (p == nullptr) + { + mut().unlock(); + return nullptr; + } } return p; } @@ -271,28 +288,35 @@ void __libcpp_db::__erase_c(void* __c) { WLock _(mut()); - size_t hc = hash()(__c) % static_cast(__cend_ - __cbeg_); - __c_node* p = __cbeg_[hc]; - __c_node* q = nullptr; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); - while (p->__c_ != __c) + if (__cend_ != __cbeg_) { - q = p; - p = p->__next_; - _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); + size_t hc = hash()(__c) % static_cast(__cend_ - __cbeg_); + __c_node* p = __cbeg_[hc]; + if (p == nullptr) + return; + __c_node* q = nullptr; + _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); + while (p->__c_ != __c) + { + q = p; + p = p->__next_; + if (p == nullptr) + return; + _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); + } + if (q == nullptr) + __cbeg_[hc] = p->__next_; + else + q->__next_ = p->__next_; + while (p->end_ != p->beg_) + { + --p->end_; + (*p->end_)->__c_ = nullptr; + } + free(p->beg_); + free(p); + --__csz_; } - if (q == nullptr) - __cbeg_[hc] = p->__next_; - else - q->__next_ = p->__next_; - while (p->end_ != p->beg_) - { - --p->end_; - (*p->end_)->__c_ = nullptr; - } - free(p->beg_); - free(p); - --__csz_; } void diff --git a/test/strings/basic.string/string.access/back.pass.cpp b/test/strings/basic.string/string.access/back.pass.cpp index f241d4d9..9c4800e3 100644 --- a/test/strings/basic.string/string.access/back.pass.cpp +++ b/test/strings/basic.string/string.access/back.pass.cpp @@ -12,6 +12,10 @@ // const charT& back() const; // charT& back(); +#ifdef _LIBCPP_DEBUG2 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -42,4 +46,11 @@ int main() test(S("1234567890123456789012345678901234567890")); } #endif +#ifdef _LIBCPP_DEBUG2 + { + std::string s; + char c = s.back(); + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.access/db_back.pass.cpp b/test/strings/basic.string/string.access/db_back.pass.cpp new file mode 100644 index 00000000..95b0ab05 --- /dev/null +++ b/test/strings/basic.string/string.access/db_back.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call back() on empty container. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + S s(1, '\0'); + assert(s.back() == 0); + s.clear(); + assert(s.back() == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S s(1, '\0'); + assert(s.back() == 0); + s.clear(); + assert(s.back() == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.access/db_cback.pass.cpp b/test/strings/basic.string/string.access/db_cback.pass.cpp new file mode 100644 index 00000000..8a7fe596 --- /dev/null +++ b/test/strings/basic.string/string.access/db_cback.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call back() on empty const container. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + const S s; + assert(s.back() == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + const S s; + assert(s.back() == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.access/db_cfront.pass.cpp b/test/strings/basic.string/string.access/db_cfront.pass.cpp new file mode 100644 index 00000000..55e90e32 --- /dev/null +++ b/test/strings/basic.string/string.access/db_cfront.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call front() on empty const container. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + const S s; + assert(s.front() == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + const S s; + assert(s.front() == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.access/db_cindex.pass.cpp b/test/strings/basic.string/string.access/db_cindex.pass.cpp new file mode 100644 index 00000000..c8e4f79c --- /dev/null +++ b/test/strings/basic.string/string.access/db_cindex.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Index const string out of bounds. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + const S s; + assert(s[0] == 0); + assert(s[1] == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + const S s; + assert(s[0] == 0); + assert(s[1] == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.access/db_front.pass.cpp b/test/strings/basic.string/string.access/db_front.pass.cpp new file mode 100644 index 00000000..e0de8f54 --- /dev/null +++ b/test/strings/basic.string/string.access/db_front.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call front() on empty container. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + S s(1, '\0'); + assert(s.front() == 0); + s.clear(); + assert(s.front() == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S s(1, '\0'); + assert(s.front() == 0); + s.clear(); + assert(s.front() == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.access/db_index.pass.cpp b/test/strings/basic.string/string.access/db_index.pass.cpp new file mode 100644 index 00000000..ecd0fbcf --- /dev/null +++ b/test/strings/basic.string/string.access/db_index.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Index string out of bounds. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + S s; + assert(s[0] == 0); + assert(s[1] == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S s; + assert(s[0] == 0); + assert(s[1] == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.access/front.pass.cpp b/test/strings/basic.string/string.access/front.pass.cpp index ecfafb54..fdeb16d8 100644 --- a/test/strings/basic.string/string.access/front.pass.cpp +++ b/test/strings/basic.string/string.access/front.pass.cpp @@ -12,6 +12,10 @@ // const charT& front() const; // charT& front(); +#ifdef _LIBCPP_DEBUG2 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -42,4 +46,11 @@ int main() test(S("1234567890123456789012345678901234567890")); } #endif +#ifdef _LIBCPP_DEBUG2 + { + std::string s; + char c = s.front(); + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.access/index.pass.cpp b/test/strings/basic.string/string.access/index.pass.cpp index b5643533..76709fea 100644 --- a/test/strings/basic.string/string.access/index.pass.cpp +++ b/test/strings/basic.string/string.access/index.pass.cpp @@ -12,6 +12,10 @@ // const_reference operator[](size_type pos) const; // reference operator[](size_type pos); +#ifdef _LIBCPP_DEBUG2 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -47,4 +51,13 @@ int main() assert(s2[0] == '\0'); } #endif +#ifdef _LIBCPP_DEBUG2 + { + std::string s; + char c = s[0]; + assert(c == '\0'); + c = s[1]; + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.iterators/db_iterators_2.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_2.pass.cpp new file mode 100644 index 00000000..41d9224c --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_2.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Compare iterators from different containers with <. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + S s1; + S s2; + bool b = s1.begin() < s2.begin(); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S s1; + S s2; + bool b = s1.begin() < s2.begin(); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.iterators/db_iterators_3.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_3.pass.cpp new file mode 100644 index 00000000..733a2777 --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_3.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Subtract iterators from different containers with <. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string S; + S s1; + S s2; + int i = s1.begin() - s2.begin(); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S s1; + S s2; + int i = s1.begin() - s2.begin(); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.iterators/db_iterators_4.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_4.pass.cpp new file mode 100644 index 00000000..9668e866 --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_4.pass.cpp @@ -0,0 +1,54 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Index iterator out of bounds. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string C; + C c(1, '\0'); + C::iterator i = c.begin(); + assert(i[0] == 0); + assert(i[1] == 0); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> C; + C c(1, '\0'); + C::iterator i = c.begin(); + assert(i[0] == 0); + assert(i[1] == 0); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.iterators/db_iterators_5.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_5.pass.cpp new file mode 100644 index 00000000..2c355441 --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_5.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Add to iterator out of bounds. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string C; + C c(1, '\0'); + C::iterator i = c.begin(); + i += 1; + assert(i == c.end()); + i = c.begin(); + i += 2; + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> C; + C c(1, '\0'); + C::iterator i = c.begin(); + i += 1; + assert(i == c.end()); + i = c.begin(); + i += 2; + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.iterators/db_iterators_6.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_6.pass.cpp new file mode 100644 index 00000000..bded5e6c --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_6.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Decrement iterator prior to begin. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string C; + C c(1, '\0'); + C::iterator i = c.end(); + --i; + assert(i == c.begin()); + --i; + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> C; + C c(1, '\0'); + C::iterator i = c.end(); + --i; + assert(i == c.begin()); + --i; + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.iterators/db_iterators_7.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_7.pass.cpp new file mode 100644 index 00000000..7d8a219e --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_7.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Increment iterator past end. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string C; + C c(1, '\0'); + C::iterator i = c.begin(); + ++i; + assert(i == c.end()); + ++i; + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> C; + C c(1, '\0'); + C::iterator i = c.begin(); + ++i; + assert(i == c.end()); + ++i; + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.iterators/db_iterators_8.pass.cpp b/test/strings/basic.string/string.iterators/db_iterators_8.pass.cpp new file mode 100644 index 00000000..ed0fe1ae --- /dev/null +++ b/test/strings/basic.string/string.iterators/db_iterators_8.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Dereference non-dereferenceable iterator. + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include +#include + +#include "../min_allocator.h" + +int main() +{ + { + typedef std::string C; + C c(1, '\0'); + C::iterator i = c.end(); + char j = *i; + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> C; + C c(1, '\0'); + C::iterator i = c.end(); + char j = *i; + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/erase_iter_db1.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_db1.pass.cpp new file mode 100644 index 00000000..15f647d7 --- /dev/null +++ b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_db1.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call erase(const_iterator position) with end() + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include + +#include "../../min_allocator.h" + +int main() +{ + { + std::string l1("123"); + std::string::const_iterator i = l1.end(); + l1.erase(i); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S l1("123"); + S::const_iterator i = l1.end(); + l1.erase(i); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/erase_iter_db2.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_db2.pass.cpp new file mode 100644 index 00000000..e3d81272 --- /dev/null +++ b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_db2.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call erase(const_iterator position) with iterator from another container + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include + +#include "../../min_allocator.h" + +int main() +{ + { + std::string l1("123"); + std::string l2("123"); + std::string::const_iterator i = l2.begin(); + l1.erase(i); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S l1("123"); + S l2("123"); + S::const_iterator i = l2.begin(); + l1.erase(i); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db1.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db1.pass.cpp new file mode 100644 index 00000000..be0a7238 --- /dev/null +++ b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db1.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call erase(const_iterator first, const_iterator last); with first iterator from another container + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include + +#include "../../min_allocator.h" + +int main() +{ + { + std::string l1("123"); + std::string l2("123"); + std::string::iterator i = l1.erase(l2.cbegin(), l1.cbegin()+1); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S l1("123"); + S l2("123"); + S::iterator i = l1.erase(l2.cbegin(), l1.cbegin()+1); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db2.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db2.pass.cpp new file mode 100644 index 00000000..dfc29ef9 --- /dev/null +++ b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db2.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call erase(const_iterator first, const_iterator last); with second iterator from another container + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include + +#include "../../min_allocator.h" + +int main() +{ + { + std::string l1("123"); + std::string l2("123"); + std::string::iterator i = l1.erase(l1.cbegin(), l2.cbegin()+1); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S l1("123"); + S l2("123"); + S::iterator i = l1.erase(l1.cbegin(), l2.cbegin()+1); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db3.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db3.pass.cpp new file mode 100644 index 00000000..7c8792bd --- /dev/null +++ b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db3.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call erase(const_iterator first, const_iterator last); with both iterators from another container + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include + +#include "../../min_allocator.h" + +int main() +{ + { + std::string l1("123"); + std::string l2("123"); + std::string::iterator i = l1.erase(l2.cbegin(), l2.cbegin()+1); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S l1("123"); + S l2("123"); + S::iterator i = l1.erase(l2.cbegin(), l2.cbegin()+1); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db4.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db4.pass.cpp new file mode 100644 index 00000000..a0e8d375 --- /dev/null +++ b/test/strings/basic.string/string.modifiers/string_erase/erase_iter_iter_db4.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// + +// Call erase(const_iterator first, const_iterator last); with a bad range + +#if _LIBCPP_DEBUG2 >= 1 + +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) + +#include +#include +#include +#include + +#include "../../min_allocator.h" + +int main() +{ + { + std::string l1("123"); + std::string::iterator i = l1.erase(l1.cbegin()+1, l1.cbegin()); + assert(false); + } +#if __cplusplus >= 201103L + { + typedef std::basic_string, min_allocator> S; + S l1("123"); + S::iterator i = l1.erase(l1.cbegin()+1, l1.cbegin()); + assert(false); + } +#endif +} + +#else + +int main() +{ +} + +#endif diff --git a/test/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp b/test/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp index aaff5b6d..d7c32bea 100644 --- a/test/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp @@ -11,6 +11,10 @@ // void pop_back(); +#if _LIBCPP_DEBUG2 >= 1 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -41,4 +45,11 @@ int main() test(S("abcdefghijklmnopqrst"), S("abcdefghijklmnopqrs")); } #endif +#if _LIBCPP_DEBUG2 >= 1 + { + std::string s; + s.pop_back(); + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp b/test/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp index ec696fee..47b6c5ff 100644 --- a/test/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_insert/iter_char.pass.cpp @@ -11,6 +11,10 @@ // iterator insert(const_iterator p, charT c); +#if _LIBCPP_DEBUG2 >= 1 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include #include @@ -72,4 +76,13 @@ int main() test(s, s.begin()+6, 'C', S("a567ABC1432dcb")); } #endif +#if _LIBCPP_DEBUG2 >= 1 + { + typedef std::string S; + S s; + S s2; + s.insert(s2.begin(), '1'); + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp b/test/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp index 4e249357..798452d0 100644 --- a/test/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_insert/iter_initializer_list.pass.cpp @@ -11,6 +11,10 @@ // iterator insert(const_iterator p, initializer_list il); +#if _LIBCPP_DEBUG2 >= 1 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -34,5 +38,13 @@ int main() assert(s == "123abc456"); } #endif +#if _LIBCPP_DEBUG2 >= 1 + { + std::string s; + std::string s2; + s.insert(s2.begin(), {'a', 'b', 'c'}); + assert(false); + } +#endif #endif // _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS } diff --git a/test/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp b/test/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp index 0eb3216e..ec915984 100644 --- a/test/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_insert/iter_iter_iter.pass.cpp @@ -12,6 +12,10 @@ // template // iterator insert(const_iterator p, InputIterator first, InputIterator last); +#if _LIBCPP_DEBUG2 >= 1 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -123,4 +127,14 @@ int main() S("12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")); } #endif +#if _LIBCPP_DEBUG2 >= 1 + { + std::string v; + std::string v2; + char a[] = "123"; + const int N = sizeof(a)/sizeof(a[0]); + std::string::iterator i = v.insert(v2.cbegin() + 10, a, a+N); + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp b/test/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp index a3e5d29e..7951f195 100644 --- a/test/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_insert/iter_size_char.pass.cpp @@ -11,6 +11,10 @@ // iterator insert(const_iterator p, size_type n, charT c); +#if _LIBCPP_DEBUG2 >= 1 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0)) +#endif + #include #include @@ -166,4 +170,12 @@ int main() test(S("abcdefghijklmnopqrst"), 20, 20, '1', S("abcdefghijklmnopqrst11111111111111111111")); } #endif +#if _LIBCPP_DEBUG2 >= 1 + { + std::string s; + std::string s2; + s.insert(s2.begin(), 1, 'a'); + assert(false); + } +#endif } diff --git a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp index 37262f13..bdc45193 100644 --- a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_iter_iter.pass.cpp @@ -26,10 +26,10 @@ test(S s, typename S::size_type pos1, typename S::size_type n1, It f, It l, S ex typename S::size_type old_size = s.size(); typename S::const_iterator first = s.begin() + pos1; typename S::const_iterator last = s.begin() + pos1 + n1; + typename S::size_type xlen = last - first; s.replace(first, last, f, l); assert(s.__invariants()); assert(s == expected); - typename S::size_type xlen = last - first; typename S::size_type rlen = std::distance(f, l); assert(s.size() == old_size - xlen + rlen); } diff --git a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp index 58a4b20c..6d552f0e 100644 --- a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer.pass.cpp @@ -27,10 +27,10 @@ test(S s, typename S::size_type pos1, typename S::size_type n1, const typename S typename S::size_type old_size = s.size(); typename S::const_iterator first = s.begin() + pos1; typename S::const_iterator last = s.begin() + pos1 + n1; + typename S::size_type xlen = last - first; s.replace(first, last, str); assert(s.__invariants()); assert(s == expected); - typename S::size_type xlen = last - first; typename S::size_type rlen = S::traits_type::length(str); assert(s.size() == old_size - xlen + rlen); } diff --git a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp index 0ef59ed7..a8968ef7 100644 --- a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_pointer_size.pass.cpp @@ -28,10 +28,10 @@ test(S s, typename S::size_type pos1, typename S::size_type n1, const typename S typename S::size_type old_size = s.size(); typename S::const_iterator first = s.begin() + pos1; typename S::const_iterator last = s.begin() + pos1 + n1; + typename S::size_type xlen = last - first; s.replace(first, last, str, n2); assert(s.__invariants()); assert(s == expected); - typename S::size_type xlen = last - first; typename S::size_type rlen = n2; assert(s.size() == old_size - xlen + rlen); } diff --git a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp index 6525607d..b1b3d96f 100644 --- a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_size_char.pass.cpp @@ -28,10 +28,10 @@ test(S s, typename S::size_type pos1, typename S::size_type n1, typename S::size typename S::size_type old_size = s.size(); typename S::const_iterator first = s.begin() + pos1; typename S::const_iterator last = s.begin() + pos1 + n1; + typename S::size_type xlen = last - first; s.replace(first, last, n2, c); assert(s.__invariants()); assert(s == expected); - typename S::size_type xlen = last - first; typename S::size_type rlen = n2; assert(s.size() == old_size - xlen + rlen); } diff --git a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp index 76db558c..95ef8be2 100644 --- a/test/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp +++ b/test/strings/basic.string/string.modifiers/string_replace/iter_iter_string.pass.cpp @@ -27,10 +27,10 @@ test(S s, typename S::size_type pos1, typename S::size_type n1, S str, S expecte typename S::size_type old_size = s.size(); typename S::const_iterator first = s.begin() + pos1; typename S::const_iterator last = s.begin() + pos1 + n1; + typename S::size_type xlen = last - first; s.replace(first, last, str); assert(s.__invariants()); assert(s == expected); - typename S::size_type xlen = last - first; typename S::size_type rlen = str.size(); assert(s.size() == old_size - xlen + rlen); }