xref: /llvm-project/libcxx/test/support/unique_ptr_test_helper.h (revision 30dadaa2eb499395f5bef44b9e1a18db6360ad1f)
12561885fSEric Fiselier //===----------------------------------------------------------------------===//
22561885fSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62561885fSEric Fiselier //
72561885fSEric Fiselier //===----------------------------------------------------------------------===//
82561885fSEric Fiselier 
92561885fSEric Fiselier #ifndef TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
102561885fSEric Fiselier #define TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
112561885fSEric Fiselier 
122561885fSEric Fiselier #include <memory>
132561885fSEric Fiselier #include <type_traits>
142561885fSEric Fiselier 
152561885fSEric Fiselier #include "test_macros.h"
162561885fSEric Fiselier #include "deleter_types.h"
172561885fSEric Fiselier 
182561885fSEric Fiselier struct A {
192561885fSEric Fiselier   static int count;
AA20*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 A() {
21*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
22*30dadaa2SIgor Zhukov       ++count;
23*30dadaa2SIgor Zhukov   }
AA24*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 A(const A&) {
25*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
26*30dadaa2SIgor Zhukov       ++count;
27*30dadaa2SIgor Zhukov   }
~AA28*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 virtual ~A() {
29*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
30*30dadaa2SIgor Zhukov       --count;
31*30dadaa2SIgor Zhukov   }
322561885fSEric Fiselier };
332561885fSEric Fiselier 
342561885fSEric Fiselier int A::count = 0;
352561885fSEric Fiselier 
362561885fSEric Fiselier struct B : public A {
372561885fSEric Fiselier   static int count;
BB38*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 B() {
39*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
40*30dadaa2SIgor Zhukov       ++count;
41*30dadaa2SIgor Zhukov   }
BB42*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 B(const B& other) : A(other) {
43*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
44*30dadaa2SIgor Zhukov       ++count;
45*30dadaa2SIgor Zhukov   }
~BB46*30dadaa2SIgor Zhukov   TEST_CONSTEXPR_CXX23 virtual ~B() {
47*30dadaa2SIgor Zhukov     if (!TEST_IS_CONSTANT_EVALUATED)
48*30dadaa2SIgor Zhukov       --count;
49*30dadaa2SIgor Zhukov   }
502561885fSEric Fiselier };
512561885fSEric Fiselier 
522561885fSEric Fiselier int B::count = 0;
532561885fSEric Fiselier 
542561885fSEric Fiselier template <class T>
newValue(int num_elements)55*30dadaa2SIgor Zhukov TEST_CONSTEXPR_CXX23 typename std::enable_if<!std::is_array<T>::value, T*>::type newValue(int num_elements) {
562561885fSEric Fiselier   assert(num_elements == 1);
572561885fSEric Fiselier   return new T;
582561885fSEric Fiselier }
592561885fSEric Fiselier 
602561885fSEric Fiselier template <class T>
61*30dadaa2SIgor Zhukov TEST_CONSTEXPR_CXX23 typename std::enable_if<std::is_array<T>::value, typename std::remove_all_extents<T>::type*>::type
newValue(int num_elements)622561885fSEric Fiselier newValue(int num_elements) {
632561885fSEric Fiselier   typedef typename std::remove_all_extents<T>::type VT;
642561885fSEric Fiselier   assert(num_elements >= 1);
652561885fSEric Fiselier   return new VT[num_elements];
662561885fSEric Fiselier }
672561885fSEric Fiselier 
682561885fSEric Fiselier struct IncompleteType;
692561885fSEric Fiselier 
702561885fSEric Fiselier void checkNumIncompleteTypeAlive(int i);
712561885fSEric Fiselier int getNumIncompleteTypeAlive();
722561885fSEric Fiselier IncompleteType* getNewIncomplete();
732561885fSEric Fiselier IncompleteType* getNewIncompleteArray(int size);
742561885fSEric Fiselier 
752561885fSEric Fiselier #if TEST_STD_VER >= 11
762561885fSEric Fiselier template <class ThisT, class... Args>
772561885fSEric Fiselier struct args_is_this_type : std::false_type {};
782561885fSEric Fiselier 
792561885fSEric Fiselier template <class ThisT, class A1>
802561885fSEric Fiselier struct args_is_this_type<ThisT, A1> : std::is_same<ThisT, typename std::decay<A1>::type> {};
812561885fSEric Fiselier #endif
822561885fSEric Fiselier 
83*30dadaa2SIgor Zhukov template <class IncompleteT = IncompleteType, class Del = std::default_delete<IncompleteT> >
842561885fSEric Fiselier struct StoresIncomplete {
85*30dadaa2SIgor Zhukov   static_assert(
86*30dadaa2SIgor Zhukov       (std::is_same<IncompleteT, IncompleteType>::value || std::is_same<IncompleteT, IncompleteType[]>::value), "");
872561885fSEric Fiselier 
882561885fSEric Fiselier   std::unique_ptr<IncompleteT, Del> m_ptr;
892561885fSEric Fiselier 
902561885fSEric Fiselier #if TEST_STD_VER >= 11
912561885fSEric Fiselier   StoresIncomplete(StoresIncomplete const&) = delete;
922561885fSEric Fiselier   StoresIncomplete(StoresIncomplete&&)      = default;
932561885fSEric Fiselier 
942561885fSEric Fiselier   template <class... Args>
952561885fSEric Fiselier   StoresIncomplete(Args&&... args) : m_ptr(std::forward<Args>(args)...) {
962561885fSEric Fiselier     static_assert(!args_is_this_type<StoresIncomplete, Args...>::value, "");
972561885fSEric Fiselier   }
982561885fSEric Fiselier #else
99*30dadaa2SIgor Zhukov 
1002561885fSEric Fiselier private:
1012561885fSEric Fiselier   StoresIncomplete();
1022561885fSEric Fiselier   StoresIncomplete(StoresIncomplete const&);
103*30dadaa2SIgor Zhukov 
1042561885fSEric Fiselier public:
1052561885fSEric Fiselier #endif
1062561885fSEric Fiselier 
1072561885fSEric Fiselier   ~StoresIncomplete();
1082561885fSEric Fiselier 
1092561885fSEric Fiselier   IncompleteType* get() const { return m_ptr.get(); }
1102561885fSEric Fiselier   Del& get_deleter() { return m_ptr.get_deleter(); }
1112561885fSEric Fiselier };
1122561885fSEric Fiselier 
1132561885fSEric Fiselier #if TEST_STD_VER >= 11
114*30dadaa2SIgor Zhukov template <class IncompleteT = IncompleteType, class Del = std::default_delete<IncompleteT>, class... Args>
1152561885fSEric Fiselier void doIncompleteTypeTest(int expect_alive, Args&&... ctor_args) {
1162561885fSEric Fiselier   checkNumIncompleteTypeAlive(expect_alive);
1172561885fSEric Fiselier   {
1182561885fSEric Fiselier     StoresIncomplete<IncompleteT, Del> sptr(std::forward<Args>(ctor_args)...);
1192561885fSEric Fiselier     checkNumIncompleteTypeAlive(expect_alive);
1202561885fSEric Fiselier     if (expect_alive == 0)
1212561885fSEric Fiselier       assert(sptr.get() == nullptr);
1222561885fSEric Fiselier     else
1232561885fSEric Fiselier       assert(sptr.get() != nullptr);
1242561885fSEric Fiselier   }
1252561885fSEric Fiselier   checkNumIncompleteTypeAlive(0);
1262561885fSEric Fiselier }
1272561885fSEric Fiselier #endif
1282561885fSEric Fiselier 
1292561885fSEric Fiselier #define INCOMPLETE_TEST_EPILOGUE()                                                                                     \
1302561885fSEric Fiselier   int is_incomplete_test_anchor = is_incomplete_test();                                                                \
1312561885fSEric Fiselier                                                                                                                        \
1322561885fSEric Fiselier   struct IncompleteType {                                                                                              \
1332561885fSEric Fiselier     static int count;                                                                                                  \
1342561885fSEric Fiselier     IncompleteType() { ++count; }                                                                                      \
1352561885fSEric Fiselier     ~IncompleteType() { --count; }                                                                                     \
1362561885fSEric Fiselier   };                                                                                                                   \
1372561885fSEric Fiselier                                                                                                                        \
1382561885fSEric Fiselier   int IncompleteType::count = 0;                                                                                       \
1392561885fSEric Fiselier                                                                                                                        \
140*30dadaa2SIgor Zhukov   void checkNumIncompleteTypeAlive(int i) { assert(IncompleteType::count == i); }                                      \
1412561885fSEric Fiselier   int getNumIncompleteTypeAlive() { return IncompleteType::count; }                                                    \
1422561885fSEric Fiselier   IncompleteType* getNewIncomplete() { return new IncompleteType; }                                                    \
143*30dadaa2SIgor Zhukov   IncompleteType* getNewIncompleteArray(int size) { return new IncompleteType[size]; }                                 \
1442561885fSEric Fiselier                                                                                                                        \
1452561885fSEric Fiselier   template <class IncompleteT, class Del>                                                                              \
1462561885fSEric Fiselier   StoresIncomplete<IncompleteT, Del>::~StoresIncomplete() {}
1472561885fSEric Fiselier #
1482561885fSEric Fiselier 
1492561885fSEric Fiselier #if TEST_STD_VER >= 11
1502561885fSEric Fiselier #  define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...)                                                                       \
1512561885fSEric Fiselier     static int is_incomplete_test() { __VA_ARGS__ return 0; }                                                          \
1522561885fSEric Fiselier     INCOMPLETE_TEST_EPILOGUE()
1532561885fSEric Fiselier #else
1542561885fSEric Fiselier #  define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...)                                                                       \
1552561885fSEric Fiselier     static int is_incomplete_test() { return 0; }                                                                      \
1562561885fSEric Fiselier     INCOMPLETE_TEST_EPILOGUE()
1572561885fSEric Fiselier #endif
1582561885fSEric Fiselier 
1592561885fSEric Fiselier #endif // TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
160