1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <vector>
11
12// void push_back(const value_type& x);
13
14#include <vector>
15#include <cassert>
16
17#include "asan_testing.h"
18#include "test_macros.h"
19
20// Flag that makes the copy constructor for CMyClass throw an exception
21static bool gCopyConstructorShouldThrow = false;
22
23class CMyClass {
24    public: CMyClass(int tag);
25    public: CMyClass(const CMyClass& iOther);
26    public: ~CMyClass();
27
28    bool equal(const CMyClass &rhs) const
29        { return fTag == rhs.fTag && fMagicValue == rhs.fMagicValue; }
30    private:
31        int fMagicValue;
32        int fTag;
33
34    private: static int kStartedConstructionMagicValue;
35    private: static int kFinishedConstructionMagicValue;
36};
37
38// Value for fMagicValue when the constructor has started running, but not yet finished
39int CMyClass::kStartedConstructionMagicValue = 0;
40// Value for fMagicValue when the constructor has finished running
41int CMyClass::kFinishedConstructionMagicValue = 12345;
42
43CMyClass::CMyClass(int tag) :
44    fMagicValue(kStartedConstructionMagicValue), fTag(tag)
45{
46    // Signal that the constructor has finished running
47    fMagicValue = kFinishedConstructionMagicValue;
48}
49
50CMyClass::CMyClass(const CMyClass& iOther) :
51    fMagicValue(kStartedConstructionMagicValue), fTag(iOther.fTag)
52{
53    // If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
54    if (gCopyConstructorShouldThrow) {
55        TEST_THROW(std::exception());
56    }
57    // Signal that the constructor has finished running
58    fMagicValue = kFinishedConstructionMagicValue;
59}
60
61CMyClass::~CMyClass() {
62    // Only instances for which the constructor has finished running should be destructed
63    assert(fMagicValue == kFinishedConstructionMagicValue);
64}
65
66bool operator==(const CMyClass &lhs, const CMyClass &rhs) { return lhs.equal(rhs); }
67
68int main()
69{
70    CMyClass instance(42);
71    std::vector<CMyClass> vec;
72
73    vec.push_back(instance);
74    std::vector<CMyClass> vec2(vec);
75    assert(is_contiguous_container_asan_correct(vec));
76    assert(is_contiguous_container_asan_correct(vec2));
77
78#ifndef TEST_HAS_NO_EXCEPTIONS
79    gCopyConstructorShouldThrow = true;
80    try {
81        vec.push_back(instance);
82        assert(false);
83    }
84    catch (...) {
85        assert(vec==vec2);
86        assert(is_contiguous_container_asan_correct(vec));
87    }
88#endif
89}
90