diff options
Diffstat (limited to 'test/std/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp')
-rw-r--r-- | test/std/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/test/std/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp b/test/std/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp new file mode 100644 index 000000000000..6615a25a620f --- /dev/null +++ b/test/std/containers/sequences/vector/vector.modifiers/push_back_exception_safety.pass.cpp @@ -0,0 +1,86 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +#include "asan_testing.h" + +// Flag that makes the copy constructor for CMyClass throw an exception +static bool gCopyConstructorShouldThow = false; + + +class CMyClass { + public: CMyClass(int tag); + public: CMyClass(const CMyClass& iOther); + public: ~CMyClass(); + + bool equal(const CMyClass &rhs) const + { return fTag == rhs.fTag && fMagicValue == rhs.fMagicValue; } + private: + int fMagicValue; + int fTag; + + 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(int tag) : + fMagicValue(kStartedConstructionMagicValue), fTag(tag) +{ + // Signal that the constructor has finished running + fMagicValue = kFinishedConstructionMagicValue; +} + +CMyClass::CMyClass(const CMyClass& iOther) : + fMagicValue(kStartedConstructionMagicValue), fTag(iOther.fTag) +{ + // 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); +} + +bool operator==(const CMyClass &lhs, const CMyClass &rhs) { return lhs.equal(rhs); } + +int main() +{ + CMyClass instance(42); + std::vector<CMyClass> vec; + + vec.push_back(instance); + std::vector<CMyClass> vec2(vec); + assert(is_contiguous_container_asan_correct(vec)); + assert(is_contiguous_container_asan_correct(vec2)); + + gCopyConstructorShouldThow = true; + try { + vec.push_back(instance); + } + catch (...) { + assert(vec==vec2); + assert(is_contiguous_container_asan_correct(vec)); + } +} |