forked from OSchip/llvm-project
[asan] Make vector asan annotations exception-friendly
Fix vector asan annotations with RAII. Add a test. Also, remove one dead function. Review: http://reviews.llvm.org/D4170 llvm-svn: 216995
This commit is contained in:
parent
ca616acd73
commit
3f0e834842
|
@ -784,7 +784,6 @@ private:
|
||||||
void
|
void
|
||||||
>::type
|
>::type
|
||||||
__construct_at_end(_ForwardIterator __first, _ForwardIterator __last);
|
__construct_at_end(_ForwardIterator __first, _ForwardIterator __last);
|
||||||
void __move_construct_at_end(pointer __first, pointer __last);
|
|
||||||
void __append(size_type __n);
|
void __append(size_type __n);
|
||||||
void __append(size_type __n, const_reference __x);
|
void __append(size_type __n, const_reference __x);
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
@ -836,7 +835,7 @@ private:
|
||||||
// may not meet the AddressSanitizer alignment constraints.
|
// may not meet the AddressSanitizer alignment constraints.
|
||||||
// See the documentation for __sanitizer_annotate_contiguous_container for more details.
|
// See the documentation for __sanitizer_annotate_contiguous_container for more details.
|
||||||
void __annotate_contiguous_container
|
void __annotate_contiguous_container
|
||||||
(const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid)
|
(const void *__beg, const void *__end, const void *__old_mid, const void *__new_mid) const
|
||||||
{
|
{
|
||||||
#ifndef _LIBCPP_HAS_NO_ASAN
|
#ifndef _LIBCPP_HAS_NO_ASAN
|
||||||
if (__beg && is_same<allocator_type, __default_allocator_type>::value)
|
if (__beg && is_same<allocator_type, __default_allocator_type>::value)
|
||||||
|
@ -844,26 +843,42 @@ private:
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __annotate_new(size_type __current_size)
|
void __annotate_new(size_type __current_size) const
|
||||||
{
|
{
|
||||||
__annotate_contiguous_container(data(), data() + capacity(),
|
__annotate_contiguous_container(data(), data() + capacity(),
|
||||||
data() + capacity(), data() + __current_size);
|
data() + capacity(), data() + __current_size);
|
||||||
}
|
}
|
||||||
void __annotate_delete()
|
void __annotate_delete() const
|
||||||
{
|
{
|
||||||
__annotate_contiguous_container(data(), data() + capacity(),
|
__annotate_contiguous_container(data(), data() + capacity(),
|
||||||
data() + size(), data() + capacity());
|
data() + size(), data() + capacity());
|
||||||
}
|
}
|
||||||
void __annotate_increase(size_type __n)
|
void __annotate_increase(size_type __n) const
|
||||||
{
|
{
|
||||||
__annotate_contiguous_container(data(), data() + capacity(),
|
__annotate_contiguous_container(data(), data() + capacity(),
|
||||||
data() + size(), data() + size() + __n);
|
data() + size(), data() + size() + __n);
|
||||||
}
|
}
|
||||||
void __annotate_shrink(size_type __old_size)
|
void __annotate_shrink(size_type __old_size) const
|
||||||
{
|
{
|
||||||
__annotate_contiguous_container(data(), data() + capacity(),
|
__annotate_contiguous_container(data(), data() + capacity(),
|
||||||
data() + __old_size, data() + size());
|
data() + __old_size, data() + size());
|
||||||
}
|
}
|
||||||
|
// The annotation for size increase should happen before the actual increase,
|
||||||
|
// but if an exception is thrown after that the annotation has to be undone.
|
||||||
|
struct __RAII_IncreaseAnnotator {
|
||||||
|
__RAII_IncreaseAnnotator(const vector &__v, size_type __n = 1)
|
||||||
|
: __commit(false), __v(__v), __n(__n) {
|
||||||
|
__v.__annotate_increase(__n);
|
||||||
|
}
|
||||||
|
void __done() { __commit = true; }
|
||||||
|
~__RAII_IncreaseAnnotator() {
|
||||||
|
if (__commit) return;
|
||||||
|
__v.__annotate_shrink(__v.size() + __n);
|
||||||
|
}
|
||||||
|
bool __commit;
|
||||||
|
size_type __n;
|
||||||
|
const vector &__v;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class _Tp, class _Allocator>
|
template <class _Tp, class _Allocator>
|
||||||
|
@ -959,12 +974,13 @@ void
|
||||||
vector<_Tp, _Allocator>::__construct_at_end(size_type __n)
|
vector<_Tp, _Allocator>::__construct_at_end(size_type __n)
|
||||||
{
|
{
|
||||||
allocator_type& __a = this->__alloc();
|
allocator_type& __a = this->__alloc();
|
||||||
__annotate_increase(__n);
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_));
|
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_));
|
||||||
++this->__end_;
|
++this->__end_;
|
||||||
--__n;
|
--__n;
|
||||||
|
__annotator.__done();
|
||||||
} while (__n > 0);
|
} while (__n > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,12 +996,13 @@ void
|
||||||
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
|
vector<_Tp, _Allocator>::__construct_at_end(size_type __n, const_reference __x)
|
||||||
{
|
{
|
||||||
allocator_type& __a = this->__alloc();
|
allocator_type& __a = this->__alloc();
|
||||||
__annotate_increase(__n);
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x);
|
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), __x);
|
||||||
++this->__end_;
|
++this->__end_;
|
||||||
--__n;
|
--__n;
|
||||||
|
__annotator.__done();
|
||||||
} while (__n > 0);
|
} while (__n > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,22 +1018,9 @@ vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIt
|
||||||
allocator_type& __a = this->__alloc();
|
allocator_type& __a = this->__alloc();
|
||||||
for (; __first != __last; ++__first)
|
for (; __first != __last; ++__first)
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first);
|
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_), *__first);
|
||||||
++this->__end_;
|
__annotator.__done();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class _Tp, class _Allocator>
|
|
||||||
void
|
|
||||||
vector<_Tp, _Allocator>::__move_construct_at_end(pointer __first, pointer __last)
|
|
||||||
{
|
|
||||||
allocator_type& __a = this->__alloc();
|
|
||||||
for (; __first != __last; ++__first)
|
|
||||||
{
|
|
||||||
__annotate_increase(1);
|
|
||||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(this->__end_),
|
|
||||||
_VSTD::move(*__first));
|
|
||||||
++this->__end_;
|
++this->__end_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1578,9 +1582,10 @@ vector<_Tp, _Allocator>::push_back(const_reference __x)
|
||||||
{
|
{
|
||||||
if (this->__end_ != this->__end_cap())
|
if (this->__end_ != this->__end_cap())
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__alloc_traits::construct(this->__alloc(),
|
__alloc_traits::construct(this->__alloc(),
|
||||||
_VSTD::__to_raw_pointer(this->__end_), __x);
|
_VSTD::__to_raw_pointer(this->__end_), __x);
|
||||||
|
__annotator.__done();
|
||||||
++this->__end_;
|
++this->__end_;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1596,10 +1601,11 @@ vector<_Tp, _Allocator>::push_back(value_type&& __x)
|
||||||
{
|
{
|
||||||
if (this->__end_ < this->__end_cap())
|
if (this->__end_ < this->__end_cap())
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__alloc_traits::construct(this->__alloc(),
|
__alloc_traits::construct(this->__alloc(),
|
||||||
_VSTD::__to_raw_pointer(this->__end_),
|
_VSTD::__to_raw_pointer(this->__end_),
|
||||||
_VSTD::move(__x));
|
_VSTD::move(__x));
|
||||||
|
__annotator.__done();
|
||||||
++this->__end_;
|
++this->__end_;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1629,10 +1635,11 @@ vector<_Tp, _Allocator>::emplace_back(_Args&&... __args)
|
||||||
{
|
{
|
||||||
if (this->__end_ < this->__end_cap())
|
if (this->__end_ < this->__end_cap())
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__alloc_traits::construct(this->__alloc(),
|
__alloc_traits::construct(this->__alloc(),
|
||||||
_VSTD::__to_raw_pointer(this->__end_),
|
_VSTD::__to_raw_pointer(this->__end_),
|
||||||
_VSTD::forward<_Args>(__args)...);
|
_VSTD::forward<_Args>(__args)...);
|
||||||
|
__annotator.__done();
|
||||||
++this->__end_;
|
++this->__end_;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1712,7 +1719,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
|
||||||
pointer __p = this->__begin_ + (__position - begin());
|
pointer __p = this->__begin_ + (__position - begin());
|
||||||
if (this->__end_ < this->__end_cap())
|
if (this->__end_ < this->__end_cap())
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
if (__p == this->__end_)
|
if (__p == this->__end_)
|
||||||
{
|
{
|
||||||
__alloc_traits::construct(this->__alloc(),
|
__alloc_traits::construct(this->__alloc(),
|
||||||
|
@ -1727,6 +1734,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, const_reference __x)
|
||||||
++__xr;
|
++__xr;
|
||||||
*__p = *__xr;
|
*__p = *__xr;
|
||||||
}
|
}
|
||||||
|
__annotator.__done();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1752,7 +1760,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x)
|
||||||
pointer __p = this->__begin_ + (__position - begin());
|
pointer __p = this->__begin_ + (__position - begin());
|
||||||
if (this->__end_ < this->__end_cap())
|
if (this->__end_ < this->__end_cap())
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
if (__p == this->__end_)
|
if (__p == this->__end_)
|
||||||
{
|
{
|
||||||
__alloc_traits::construct(this->__alloc(),
|
__alloc_traits::construct(this->__alloc(),
|
||||||
|
@ -1765,6 +1773,7 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, value_type&& __x)
|
||||||
__move_range(__p, this->__end_, __p + 1);
|
__move_range(__p, this->__end_, __p + 1);
|
||||||
*__p = _VSTD::move(__x);
|
*__p = _VSTD::move(__x);
|
||||||
}
|
}
|
||||||
|
__annotator.__done();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1791,7 +1800,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args)
|
||||||
pointer __p = this->__begin_ + (__position - begin());
|
pointer __p = this->__begin_ + (__position - begin());
|
||||||
if (this->__end_ < this->__end_cap())
|
if (this->__end_ < this->__end_cap())
|
||||||
{
|
{
|
||||||
__annotate_increase(1);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
if (__p == this->__end_)
|
if (__p == this->__end_)
|
||||||
{
|
{
|
||||||
__alloc_traits::construct(this->__alloc(),
|
__alloc_traits::construct(this->__alloc(),
|
||||||
|
@ -1805,6 +1814,7 @@ vector<_Tp, _Allocator>::emplace(const_iterator __position, _Args&&... __args)
|
||||||
__move_range(__p, this->__end_, __p + 1);
|
__move_range(__p, this->__end_, __p + 1);
|
||||||
*__p = _VSTD::move(__tmp);
|
*__p = _VSTD::move(__tmp);
|
||||||
}
|
}
|
||||||
|
__annotator.__done();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1843,8 +1853,9 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, size_type __n, const_
|
||||||
}
|
}
|
||||||
if (__n > 0)
|
if (__n > 0)
|
||||||
{
|
{
|
||||||
__annotate_increase(__n);
|
__RAII_IncreaseAnnotator __annotator(*this);
|
||||||
__move_range(__p, __old_last, __p + __old_n);
|
__move_range(__p, __old_last, __p + __old_n);
|
||||||
|
__annotator.__done();
|
||||||
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
|
const_pointer __xr = pointer_traits<const_pointer>::pointer_to(__x);
|
||||||
if (__p <= __xr && __xr < this->__end_)
|
if (__p <= __xr && __xr < this->__end_)
|
||||||
__xr += __old_n;
|
__xr += __old_n;
|
||||||
|
@ -1954,8 +1965,9 @@ vector<_Tp, _Allocator>::insert(const_iterator __position, _ForwardIterator __fi
|
||||||
}
|
}
|
||||||
if (__n > 0)
|
if (__n > 0)
|
||||||
{
|
{
|
||||||
__annotate_increase(__n);
|
__RAII_IncreaseAnnotator __annotator(*this, __n);
|
||||||
__move_range(__p, __old_last, __p + __old_n);
|
__move_range(__p, __old_last, __p + __old_n);
|
||||||
|
__annotator.__done();
|
||||||
_VSTD::copy(__first, __m, __p);
|
_VSTD::copy(__first, __m, __p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,198 @@
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Test asan vector annotations with a class that throws in a CTOR.
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "asan_testing.h"
|
||||||
|
|
||||||
|
class X {
|
||||||
|
public:
|
||||||
|
X(const X &x) { Init(x.a); }
|
||||||
|
X(char arg) { Init(arg); }
|
||||||
|
X() { Init(42); }
|
||||||
|
X &operator=(const X &x) {
|
||||||
|
Init(x.a);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
void Init(char arg) {
|
||||||
|
if (arg == 42)
|
||||||
|
throw 0;
|
||||||
|
if (arg == 66)
|
||||||
|
arg = 42;
|
||||||
|
a = arg;
|
||||||
|
}
|
||||||
|
char get() const { return a; }
|
||||||
|
void set(char arg) { a = arg; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
char a;
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_push_back() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(2);
|
||||||
|
v.push_back(X(2));
|
||||||
|
assert(v.size() == 1);
|
||||||
|
try {
|
||||||
|
v.push_back(X(66));
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 1);
|
||||||
|
}
|
||||||
|
assert(v.size() == 1);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_emplace_back() {
|
||||||
|
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(2);
|
||||||
|
v.push_back(X(2));
|
||||||
|
assert(v.size() == 1);
|
||||||
|
try {
|
||||||
|
v.emplace_back(42);
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 1);
|
||||||
|
}
|
||||||
|
assert(v.size() == 1);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_insert_range() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(4);
|
||||||
|
v.push_back(X(1));
|
||||||
|
v.push_back(X(2));
|
||||||
|
assert(v.size() == 2);
|
||||||
|
assert(v.capacity() >= 4);
|
||||||
|
try {
|
||||||
|
char a[2] = {21, 42};
|
||||||
|
v.insert(v.end(), a, a + 2);
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 3);
|
||||||
|
}
|
||||||
|
assert(v.size() == 3);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_insert() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(3);
|
||||||
|
v.insert(v.end(), X(1));
|
||||||
|
v.insert(v.begin(), X(2));
|
||||||
|
assert(v.size() == 2);
|
||||||
|
try {
|
||||||
|
v.insert(v.end(), X(66));
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 2);
|
||||||
|
}
|
||||||
|
assert(v.size() == 2);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_emplace() {
|
||||||
|
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(3);
|
||||||
|
v.insert(v.end(), X(1));
|
||||||
|
v.insert(v.begin(), X(2));
|
||||||
|
assert(v.size() == 2);
|
||||||
|
try {
|
||||||
|
v.emplace(v.end(), 42);
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 2);
|
||||||
|
}
|
||||||
|
assert(v.size() == 2);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_insert_range2() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(4);
|
||||||
|
v.insert(v.end(), X(1));
|
||||||
|
v.insert(v.begin(), X(2));
|
||||||
|
assert(v.size() == 2);
|
||||||
|
assert(v.capacity() >= 4);
|
||||||
|
try {
|
||||||
|
char a[2] = {10, 42};
|
||||||
|
v.insert(v.begin(), a, a + 2);
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() <= 4);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_insert_n() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(10);
|
||||||
|
v.insert(v.end(), X(1));
|
||||||
|
v.insert(v.begin(), X(2));
|
||||||
|
assert(v.size() == 2);
|
||||||
|
try {
|
||||||
|
v.insert(v.begin(), 1, X(66));
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() <= 3);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_resize() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(3);
|
||||||
|
v.push_back(X(0));
|
||||||
|
try {
|
||||||
|
v.resize(3);
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 1);
|
||||||
|
}
|
||||||
|
assert(v.size() == 1);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_resize_param() {
|
||||||
|
std::vector<X> v;
|
||||||
|
v.reserve(3);
|
||||||
|
v.push_back(X(0));
|
||||||
|
try {
|
||||||
|
v.resize(3, X(66));
|
||||||
|
assert(0);
|
||||||
|
} catch (int e) {
|
||||||
|
assert(v.size() == 1);
|
||||||
|
}
|
||||||
|
assert(v.size() == 1);
|
||||||
|
assert(is_contiguous_container_asan_correct(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_push_back();
|
||||||
|
test_emplace_back();
|
||||||
|
test_insert_range();
|
||||||
|
test_insert();
|
||||||
|
test_emplace();
|
||||||
|
test_insert_range2();
|
||||||
|
test_insert_n();
|
||||||
|
test_resize();
|
||||||
|
test_resize_param();
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ extern "C" int __sanitizer_verify_contiguous_container
|
||||||
template <typename T, typename Alloc>
|
template <typename T, typename Alloc>
|
||||||
bool is_contiguous_container_asan_correct ( const std::vector<T, Alloc> &c )
|
bool is_contiguous_container_asan_correct ( const std::vector<T, Alloc> &c )
|
||||||
{
|
{
|
||||||
if ( std::is_same<Alloc, std::allocator<T>>::value && c.data() != NULL)
|
if ( std::is_same<Alloc, std::allocator<T> >::value && c.data() != NULL)
|
||||||
return __sanitizer_verify_contiguous_container (
|
return __sanitizer_verify_contiguous_container (
|
||||||
c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0;
|
c.data(), c.data() + c.size(), c.data() + c.capacity()) != 0;
|
||||||
return true;
|
return true;
|
||||||
|
@ -34,4 +34,4 @@ bool is_contiguous_container_asan_correct ( const std::vector<T, Alloc> &c )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif // ASAN_TESTING_H
|
#endif // ASAN_TESTING_H
|
||||||
|
|
Loading…
Reference in New Issue