1 //===----------------------------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
10 #define TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
11 
12 #include <memory>
13 #include <type_traits>
14 
15 #include "test_macros.h"
16 #include "deleter_types.h"
17 
18 struct A {
19   static int count;
AA20   A() { ++count; }
AA21   A(const A&) { ++count; }
~AA22   virtual ~A() { --count; }
23 };
24 
25 int A::count = 0;
26 
27 struct B : public A {
28   static int count;
BB29   B() { ++count; }
BB30   B(const B& other) : A(other) { ++count; }
~BB31   virtual ~B() { --count; }
32 };
33 
34 int B::count = 0;
35 
36 template <class T>
37 typename std::enable_if<!std::is_array<T>::value, T*>::type
newValue(int num_elements)38 newValue(int num_elements) {
39   assert(num_elements == 1);
40   return new T;
41 }
42 
43 template <class T>
44 typename std::enable_if<std::is_array<T>::value,
45                         typename std::remove_all_extents<T>::type*>::type
newValue(int num_elements)46 newValue(int num_elements) {
47   typedef typename std::remove_all_extents<T>::type VT;
48   assert(num_elements >= 1);
49   return new VT[num_elements];
50 }
51 
52 struct IncompleteType;
53 
54 void checkNumIncompleteTypeAlive(int i);
55 int getNumIncompleteTypeAlive();
56 IncompleteType* getNewIncomplete();
57 IncompleteType* getNewIncompleteArray(int size);
58 
59 #if TEST_STD_VER >= 11
60 template <class ThisT, class ...Args>
61 struct args_is_this_type : std::false_type {};
62 
63 template <class ThisT, class A1>
64 struct args_is_this_type<ThisT, A1> : std::is_same<ThisT, typename std::decay<A1>::type> {};
65 #endif
66 
67 template <class IncompleteT = IncompleteType,
68           class Del = std::default_delete<IncompleteT> >
69 struct StoresIncomplete {
70   static_assert((std::is_same<IncompleteT, IncompleteType>::value ||
71                  std::is_same<IncompleteT, IncompleteType[]>::value), "");
72 
73   std::unique_ptr<IncompleteT, Del> m_ptr;
74 
75 #if TEST_STD_VER >= 11
76   StoresIncomplete(StoresIncomplete const&) = delete;
77   StoresIncomplete(StoresIncomplete&&) = default;
78 
79   template <class ...Args>
80   StoresIncomplete(Args&&... args) : m_ptr(std::forward<Args>(args)...) {
81     static_assert(!args_is_this_type<StoresIncomplete, Args...>::value, "");
82   }
83 #else
84 private:
85   StoresIncomplete();
86   StoresIncomplete(StoresIncomplete const&);
87 public:
88 #endif
89 
90   ~StoresIncomplete();
91 
92   IncompleteType* get() const { return m_ptr.get(); }
93   Del& get_deleter() { return m_ptr.get_deleter(); }
94 };
95 
96 #if TEST_STD_VER >= 11
97 template <class IncompleteT = IncompleteType,
98           class Del = std::default_delete<IncompleteT>, class... Args>
99 void doIncompleteTypeTest(int expect_alive, Args&&... ctor_args) {
100   checkNumIncompleteTypeAlive(expect_alive);
101   {
102     StoresIncomplete<IncompleteT, Del> sptr(std::forward<Args>(ctor_args)...);
103     checkNumIncompleteTypeAlive(expect_alive);
104     if (expect_alive == 0)
105       assert(sptr.get() == nullptr);
106     else
107       assert(sptr.get() != nullptr);
108   }
109   checkNumIncompleteTypeAlive(0);
110 }
111 #endif
112 
113 #define INCOMPLETE_TEST_EPILOGUE()                                             \
114   int is_incomplete_test_anchor = is_incomplete_test();                        \
115                                                                                \
116   struct IncompleteType {                                                      \
117     static int count;                                                          \
118     IncompleteType() { ++count; }                                              \
119     ~IncompleteType() { --count; }                                             \
120   };                                                                           \
121                                                                                \
122   int IncompleteType::count = 0;                                               \
123                                                                                \
124   void checkNumIncompleteTypeAlive(int i) {                                    \
125     assert(IncompleteType::count == i);                                        \
126   }                                                                            \
127   int getNumIncompleteTypeAlive() { return IncompleteType::count; }            \
128   IncompleteType* getNewIncomplete() { return new IncompleteType; }            \
129   IncompleteType* getNewIncompleteArray(int size) {                            \
130     return new IncompleteType[size];                                           \
131   }                                                                            \
132                                                                                \
133   template <class IncompleteT, class Del>                                      \
134   StoresIncomplete<IncompleteT, Del>::~StoresIncomplete() {}
135 #
136 
137 #if TEST_STD_VER >= 11
138 #define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...)                                 \
139   static int is_incomplete_test() { __VA_ARGS__ return 0; }                    \
140   INCOMPLETE_TEST_EPILOGUE()
141 #else
142 #define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...)                                 \
143   static int is_incomplete_test() { return 0; }                                \
144   INCOMPLETE_TEST_EPILOGUE()
145 #endif
146 
147 #endif // TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
148