1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef SUPPORT_EXCEPTION_SAFETY_HELPERS_H
10 #define SUPPORT_EXCEPTION_SAFETY_HELPERS_H
16 #include "test_macros.h"
18 #if !defined(TEST_HAS_NO_EXCEPTIONS)
21 static bool throwing_enabled
;
22 static int created_by_copying
;
24 int x
= 0; // Allows distinguishing between different instances.
26 ThrowingCopy() = default;
27 ThrowingCopy(int value
) : x(value
) {}
32 ThrowingCopy(const ThrowingCopy
& other
) : x(other
.x
) {
34 if (throwing_enabled
&& created_by_copying
== N
) {
39 // Defined to silence GCC warnings. For test purposes, only copy construction is considered `created_by_copying`.
40 ThrowingCopy
& operator=(const ThrowingCopy
& other
) {
45 friend bool operator==(const ThrowingCopy
& lhs
, const ThrowingCopy
& rhs
) { return lhs
.x
== rhs
.x
; }
46 friend bool operator<(const ThrowingCopy
& lhs
, const ThrowingCopy
& rhs
) { return lhs
.x
< rhs
.x
; }
49 created_by_copying
= destroyed
= 0;
54 bool ThrowingCopy
<N
>::throwing_enabled
= true;
56 int ThrowingCopy
<N
>::created_by_copying
= 0;
58 int ThrowingCopy
<N
>::destroyed
= 0;
61 struct std::hash
<ThrowingCopy
<N
>> {
62 std::size_t operator()(const ThrowingCopy
<N
>& value
) const {
67 template <int ThrowOn
, int Size
, class Func
>
68 void test_exception_safety_throwing_copy(Func
&& func
) {
69 using T
= ThrowingCopy
<ThrowOn
>;
75 assert(false); // The function call above should throw.
78 assert(T::created_by_copying
== ThrowOn
);
79 assert(T::destroyed
== ThrowOn
- 1); // No destructor call for the partially-constructed element.
83 // Destroys the container outside the user callback to avoid destroying extra elements upon throwing (which would
84 // complicate asserting that the expected number of elements was destroyed).
85 template <class Container
, int ThrowOn
, int Size
, class Func
>
86 void test_exception_safety_throwing_copy_container(Func
&& func
) {
87 using T
= ThrowingCopy
<ThrowOn
>;
88 T::throwing_enabled
= false;
90 Container
c(in
, in
+ Size
);
91 T::throwing_enabled
= true;
96 assert(false); // The function call above should throw.
99 assert(T::created_by_copying
== ThrowOn
);
100 assert(T::destroyed
== ThrowOn
- 1); // No destructor call for the partially-constructed element.
104 #endif // !defined(TEST_HAS_NO_EXCEPTIONS)
106 #endif // SUPPORT_EXCEPTION_SAFETY_HELPERS_H