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#ifndef SUPPORT_TRACKED_VALUE_H
10#define SUPPORT_TRACKED_VALUE_H
11
12#include <cassert>
13
14#include "test_macros.h"
15
16struct TrackedValue {
17    enum State { CONSTRUCTED, MOVED_FROM, DESTROYED };
18    State state;
19
20    TrackedValue() : state(State::CONSTRUCTED) {}
21
22    TrackedValue(TrackedValue const& t) : state(State::CONSTRUCTED) {
23        assert(t.state != State::MOVED_FROM && "copying a moved-from object");
24        assert(t.state != State::DESTROYED  && "copying a destroyed object");
25    }
26
27#if TEST_STD_VER >= 11
28    TrackedValue(TrackedValue&& t) : state(State::CONSTRUCTED) {
29        assert(t.state != State::MOVED_FROM && "double moving from an object");
30        assert(t.state != State::DESTROYED  && "moving from a destroyed object");
31        t.state = State::MOVED_FROM;
32    }
33#endif
34
35    TrackedValue& operator=(TrackedValue const& t) {
36        assert(state != State::DESTROYED && "copy assigning into destroyed object");
37        assert(t.state != State::MOVED_FROM && "copying a moved-from object");
38        assert(t.state != State::DESTROYED  && "copying a destroyed object");
39        state = t.state;
40        return *this;
41    }
42
43#if TEST_STD_VER >= 11
44    TrackedValue& operator=(TrackedValue&& t) {
45        assert(state != State::DESTROYED && "move assigning into destroyed object");
46        assert(t.state != State::MOVED_FROM && "double moving from an object");
47        assert(t.state != State::DESTROYED  && "moving from a destroyed object");
48        state = t.state;
49        t.state = State::MOVED_FROM;
50        return *this;
51    }
52#endif
53
54    ~TrackedValue() {
55        assert(state != State::DESTROYED && "double-destroying an object");
56        state = State::DESTROYED;
57    }
58};
59
60#endif // SUPPORT_TRACKED_VALUE_H
61