Fix exception safety bug in vector::push_back
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@172250 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
304c31b355
commit
f619e230cc
@ -1571,7 +1571,10 @@ struct _LIBCPP_VISIBLE allocator_traits
|
|||||||
__construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
|
__construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
|
||||||
{
|
{
|
||||||
while (__end1 != __begin1)
|
while (__end1 != __begin1)
|
||||||
construct(__a, _VSTD::__to_raw_pointer(--__end2), _VSTD::move_if_noexcept(*--__end1));
|
{
|
||||||
|
construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));
|
||||||
|
--__end2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Tp>
|
template <class _Tp>
|
||||||
|
@ -1458,7 +1458,8 @@ vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x)
|
|||||||
allocator_type& __a = this->__alloc();
|
allocator_type& __a = this->__alloc();
|
||||||
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
||||||
// __v.push_back(_VSTD::forward<_Up>(__x));
|
// __v.push_back(_VSTD::forward<_Up>(__x));
|
||||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Up>(__x));
|
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Up>(__x));
|
||||||
|
__v.__end_++;
|
||||||
__swap_out_circular_buffer(__v);
|
__swap_out_circular_buffer(__v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1505,7 +1506,8 @@ vector<_Tp, _Allocator>::__emplace_back_slow_path(_Args&&... __args)
|
|||||||
allocator_type& __a = this->__alloc();
|
allocator_type& __a = this->__alloc();
|
||||||
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);
|
||||||
// __v.emplace_back(_VSTD::forward<_Args>(__args)...);
|
// __v.emplace_back(_VSTD::forward<_Args>(__args)...);
|
||||||
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_++), _VSTD::forward<_Args>(__args)...);
|
__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Args>(__args)...);
|
||||||
|
__v.__end_++;
|
||||||
__swap_out_circular_buffer(__v);
|
__swap_out_circular_buffer(__v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <deque>
|
||||||
|
|
||||||
|
// void push_back(const value_type& x);
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Flag that makes the copy constructor for CMyClass throw an exception
|
||||||
|
static bool gCopyConstructorShouldThow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class CMyClass {
|
||||||
|
public: CMyClass();
|
||||||
|
public: CMyClass(const CMyClass& iOther);
|
||||||
|
public: ~CMyClass();
|
||||||
|
|
||||||
|
private: int fMagicValue;
|
||||||
|
|
||||||
|
private: static int kStartedConstructionMagicValue;
|
||||||
|
private: static int kFinishedConstructionMagicValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Value for fMagicValue when the constructor has started running, but not yet finished
|
||||||
|
int CMyClass::kStartedConstructionMagicValue = 0;
|
||||||
|
// Value for fMagicValue when the constructor has finished running
|
||||||
|
int CMyClass::kFinishedConstructionMagicValue = 12345;
|
||||||
|
|
||||||
|
CMyClass::CMyClass() :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::CMyClass(const CMyClass& /*iOther*/) :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
|
||||||
|
if (gCopyConstructorShouldThow) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::~CMyClass() {
|
||||||
|
// Only instances for which the constructor has finished running should be destructed
|
||||||
|
assert(fMagicValue == kFinishedConstructionMagicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CMyClass instance;
|
||||||
|
std::deque<CMyClass> vec;
|
||||||
|
|
||||||
|
vec.push_back(instance);
|
||||||
|
|
||||||
|
gCopyConstructorShouldThow = true;
|
||||||
|
try {
|
||||||
|
vec.push_back(instance);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <deque>
|
||||||
|
|
||||||
|
// void push_front(const value_type& x);
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Flag that makes the copy constructor for CMyClass throw an exception
|
||||||
|
static bool gCopyConstructorShouldThow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class CMyClass {
|
||||||
|
public: CMyClass();
|
||||||
|
public: CMyClass(const CMyClass& iOther);
|
||||||
|
public: ~CMyClass();
|
||||||
|
|
||||||
|
private: int fMagicValue;
|
||||||
|
|
||||||
|
private: static int kStartedConstructionMagicValue;
|
||||||
|
private: static int kFinishedConstructionMagicValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Value for fMagicValue when the constructor has started running, but not yet finished
|
||||||
|
int CMyClass::kStartedConstructionMagicValue = 0;
|
||||||
|
// Value for fMagicValue when the constructor has finished running
|
||||||
|
int CMyClass::kFinishedConstructionMagicValue = 12345;
|
||||||
|
|
||||||
|
CMyClass::CMyClass() :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::CMyClass(const CMyClass& /*iOther*/) :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
|
||||||
|
if (gCopyConstructorShouldThow) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::~CMyClass() {
|
||||||
|
// Only instances for which the constructor has finished running should be destructed
|
||||||
|
assert(fMagicValue == kFinishedConstructionMagicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CMyClass instance;
|
||||||
|
std::deque<CMyClass> vec;
|
||||||
|
|
||||||
|
vec.push_front(instance);
|
||||||
|
|
||||||
|
gCopyConstructorShouldThow = true;
|
||||||
|
try {
|
||||||
|
vec.push_front(instance);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <forward_list>
|
||||||
|
|
||||||
|
// void push_front(const value_type& x);
|
||||||
|
|
||||||
|
#include <forward_list>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Flag that makes the copy constructor for CMyClass throw an exception
|
||||||
|
static bool gCopyConstructorShouldThow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class CMyClass {
|
||||||
|
public: CMyClass();
|
||||||
|
public: CMyClass(const CMyClass& iOther);
|
||||||
|
public: ~CMyClass();
|
||||||
|
|
||||||
|
private: int fMagicValue;
|
||||||
|
|
||||||
|
private: static int kStartedConstructionMagicValue;
|
||||||
|
private: static int kFinishedConstructionMagicValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Value for fMagicValue when the constructor has started running, but not yet finished
|
||||||
|
int CMyClass::kStartedConstructionMagicValue = 0;
|
||||||
|
// Value for fMagicValue when the constructor has finished running
|
||||||
|
int CMyClass::kFinishedConstructionMagicValue = 12345;
|
||||||
|
|
||||||
|
CMyClass::CMyClass() :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::CMyClass(const CMyClass& /*iOther*/) :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
|
||||||
|
if (gCopyConstructorShouldThow) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::~CMyClass() {
|
||||||
|
// Only instances for which the constructor has finished running should be destructed
|
||||||
|
assert(fMagicValue == kFinishedConstructionMagicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CMyClass instance;
|
||||||
|
std::forward_list<CMyClass> vec;
|
||||||
|
|
||||||
|
vec.push_front(instance);
|
||||||
|
|
||||||
|
gCopyConstructorShouldThow = true;
|
||||||
|
try {
|
||||||
|
vec.push_front(instance);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <list>
|
||||||
|
|
||||||
|
// void push_back(const value_type& x);
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Flag that makes the copy constructor for CMyClass throw an exception
|
||||||
|
static bool gCopyConstructorShouldThow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class CMyClass {
|
||||||
|
public: CMyClass();
|
||||||
|
public: CMyClass(const CMyClass& iOther);
|
||||||
|
public: ~CMyClass();
|
||||||
|
|
||||||
|
private: int fMagicValue;
|
||||||
|
|
||||||
|
private: static int kStartedConstructionMagicValue;
|
||||||
|
private: static int kFinishedConstructionMagicValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Value for fMagicValue when the constructor has started running, but not yet finished
|
||||||
|
int CMyClass::kStartedConstructionMagicValue = 0;
|
||||||
|
// Value for fMagicValue when the constructor has finished running
|
||||||
|
int CMyClass::kFinishedConstructionMagicValue = 12345;
|
||||||
|
|
||||||
|
CMyClass::CMyClass() :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::CMyClass(const CMyClass& /*iOther*/) :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
|
||||||
|
if (gCopyConstructorShouldThow) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::~CMyClass() {
|
||||||
|
// Only instances for which the constructor has finished running should be destructed
|
||||||
|
assert(fMagicValue == kFinishedConstructionMagicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CMyClass instance;
|
||||||
|
std::list<CMyClass> vec;
|
||||||
|
|
||||||
|
vec.push_back(instance);
|
||||||
|
|
||||||
|
gCopyConstructorShouldThow = true;
|
||||||
|
try {
|
||||||
|
vec.push_back(instance);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <list>
|
||||||
|
|
||||||
|
// void push_front(const value_type& x);
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Flag that makes the copy constructor for CMyClass throw an exception
|
||||||
|
static bool gCopyConstructorShouldThow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class CMyClass {
|
||||||
|
public: CMyClass();
|
||||||
|
public: CMyClass(const CMyClass& iOther);
|
||||||
|
public: ~CMyClass();
|
||||||
|
|
||||||
|
private: int fMagicValue;
|
||||||
|
|
||||||
|
private: static int kStartedConstructionMagicValue;
|
||||||
|
private: static int kFinishedConstructionMagicValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Value for fMagicValue when the constructor has started running, but not yet finished
|
||||||
|
int CMyClass::kStartedConstructionMagicValue = 0;
|
||||||
|
// Value for fMagicValue when the constructor has finished running
|
||||||
|
int CMyClass::kFinishedConstructionMagicValue = 12345;
|
||||||
|
|
||||||
|
CMyClass::CMyClass() :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::CMyClass(const CMyClass& /*iOther*/) :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
|
||||||
|
if (gCopyConstructorShouldThow) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::~CMyClass() {
|
||||||
|
// Only instances for which the constructor has finished running should be destructed
|
||||||
|
assert(fMagicValue == kFinishedConstructionMagicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CMyClass instance;
|
||||||
|
std::list<CMyClass> vec;
|
||||||
|
|
||||||
|
vec.push_front(instance);
|
||||||
|
|
||||||
|
gCopyConstructorShouldThow = true;
|
||||||
|
try {
|
||||||
|
vec.push_front(instance);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <vector>
|
||||||
|
|
||||||
|
// void push_back(const value_type& x);
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// Flag that makes the copy constructor for CMyClass throw an exception
|
||||||
|
static bool gCopyConstructorShouldThow = false;
|
||||||
|
|
||||||
|
|
||||||
|
class CMyClass {
|
||||||
|
public: CMyClass();
|
||||||
|
public: CMyClass(const CMyClass& iOther);
|
||||||
|
public: ~CMyClass();
|
||||||
|
|
||||||
|
private: int fMagicValue;
|
||||||
|
|
||||||
|
private: static int kStartedConstructionMagicValue;
|
||||||
|
private: static int kFinishedConstructionMagicValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Value for fMagicValue when the constructor has started running, but not yet finished
|
||||||
|
int CMyClass::kStartedConstructionMagicValue = 0;
|
||||||
|
// Value for fMagicValue when the constructor has finished running
|
||||||
|
int CMyClass::kFinishedConstructionMagicValue = 12345;
|
||||||
|
|
||||||
|
CMyClass::CMyClass() :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::CMyClass(const CMyClass& /*iOther*/) :
|
||||||
|
fMagicValue(kStartedConstructionMagicValue)
|
||||||
|
{
|
||||||
|
// If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
|
||||||
|
if (gCopyConstructorShouldThow) {
|
||||||
|
throw std::exception();
|
||||||
|
}
|
||||||
|
// Signal that the constructor has finished running
|
||||||
|
fMagicValue = kFinishedConstructionMagicValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMyClass::~CMyClass() {
|
||||||
|
// Only instances for which the constructor has finished running should be destructed
|
||||||
|
assert(fMagicValue == kFinishedConstructionMagicValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
CMyClass instance;
|
||||||
|
std::vector<CMyClass> vec;
|
||||||
|
|
||||||
|
vec.push_back(instance);
|
||||||
|
|
||||||
|
gCopyConstructorShouldThow = true;
|
||||||
|
try {
|
||||||
|
vec.push_back(instance);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user