aboutsummaryrefslogtreecommitdiff
path: root/test/support/unique_ptr_test_helper.h
diff options
context:
space:
mode:
Diffstat (limited to 'test/support/unique_ptr_test_helper.h')
-rw-r--r--test/support/unique_ptr_test_helper.h158
1 files changed, 158 insertions, 0 deletions
diff --git a/test/support/unique_ptr_test_helper.h b/test/support/unique_ptr_test_helper.h
new file mode 100644
index 000000000000..6fb9eaa24679
--- /dev/null
+++ b/test/support/unique_ptr_test_helper.h
@@ -0,0 +1,158 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
+#define TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H
+
+#include <memory>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "deleter_types.h"
+
+struct A {
+ static int count;
+ A() { ++count; }
+ A(const A&) { ++count; }
+ virtual ~A() { --count; }
+};
+
+int A::count = 0;
+
+struct B : public A {
+ static int count;
+ B() { ++count; }
+ B(const B&) { ++count; }
+ virtual ~B() { --count; }
+};
+
+int B::count = 0;
+
+template <class T>
+typename std::enable_if<!std::is_array<T>::value, T*>::type
+newValue(int num_elements) {
+ assert(num_elements == 1);
+ return new T;
+}
+
+template <class T>
+typename std::enable_if<std::is_array<T>::value,
+ typename std::remove_all_extents<T>::type*>::type
+newValue(int num_elements) {
+ typedef typename std::remove_all_extents<T>::type VT;
+ assert(num_elements >= 1);
+ return new VT[num_elements];
+}
+
+struct IncompleteType;
+
+void checkNumIncompleteTypeAlive(int i);
+int getNumIncompleteTypeAlive();
+IncompleteType* getNewIncomplete();
+IncompleteType* getNewIncompleteArray(int size);
+
+#if TEST_STD_VER >= 11
+template <class ThisT, class ...Args>
+struct args_is_this_type : std::false_type {};
+
+template <class ThisT, class A1>
+struct args_is_this_type<ThisT, A1> : std::is_same<ThisT, typename std::decay<A1>::type> {};
+#endif
+
+template <class IncompleteT = IncompleteType,
+ class Del = std::default_delete<IncompleteT> >
+struct StoresIncomplete {
+ static_assert((std::is_same<IncompleteT, IncompleteType>::value ||
+ std::is_same<IncompleteT, IncompleteType[]>::value), "");
+
+ std::unique_ptr<IncompleteT, Del> m_ptr;
+
+#if TEST_STD_VER >= 11
+ StoresIncomplete(StoresIncomplete const&) = delete;
+ StoresIncomplete(StoresIncomplete&&) = default;
+
+ template <class ...Args>
+ StoresIncomplete(Args&&... args) : m_ptr(std::forward<Args>(args)...) {
+ static_assert(!args_is_this_type<StoresIncomplete, Args...>::value, "");
+ }
+#else
+private:
+ StoresIncomplete();
+ StoresIncomplete(StoresIncomplete const&);
+public:
+#endif
+
+ ~StoresIncomplete();
+
+ IncompleteType* get() const { return m_ptr.get(); }
+ Del& get_deleter() { return m_ptr.get_deleter(); }
+};
+
+#if TEST_STD_VER >= 11
+template <class IncompleteT = IncompleteType,
+ class Del = std::default_delete<IncompleteT>, class... Args>
+void doIncompleteTypeTest(int expect_alive, Args&&... ctor_args) {
+ using ValueT = typename std::remove_all_extents<IncompleteT>::type;
+ checkNumIncompleteTypeAlive(expect_alive);
+ {
+ StoresIncomplete<IncompleteT, Del> sptr(std::forward<Args>(ctor_args)...);
+ checkNumIncompleteTypeAlive(expect_alive);
+ if (expect_alive == 0)
+ assert(sptr.get() == nullptr);
+ else
+ assert(sptr.get() != nullptr);
+ }
+ checkNumIncompleteTypeAlive(0);
+}
+#endif
+
+#define INCOMPLETE_TEST_EPILOGUE() \
+ int is_incomplete_test_anchor = is_incomplete_test(); \
+ \
+ struct IncompleteType { \
+ static int count; \
+ IncompleteType() { ++count; } \
+ ~IncompleteType() { --count; } \
+ }; \
+ \
+ int IncompleteType::count = 0; \
+ \
+ void checkNumIncompleteTypeAlive(int i) { \
+ assert(IncompleteType::count == i); \
+ } \
+ int getNumIncompleteTypeAlive() { return IncompleteType::count; } \
+ IncompleteType* getNewIncomplete() { return new IncompleteType; } \
+ IncompleteType* getNewIncompleteArray(int size) { \
+ return new IncompleteType[size]; \
+ } \
+ \
+ template <class IncompleteT, class Del> \
+ StoresIncomplete<IncompleteT, Del>::~StoresIncomplete() {}
+#
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvariadic-macros"
+#endif
+
+#if TEST_STD_VER >= 11
+#define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...) \
+ static int is_incomplete_test() { __VA_ARGS__ return 0; } \
+ INCOMPLETE_TEST_EPILOGUE()
+#else
+#define DEFINE_AND_RUN_IS_INCOMPLETE_TEST(...) \
+ static int is_incomplete_test() { return 0; } \
+ INCOMPLETE_TEST_EPILOGUE()
+#endif
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+#endif // TEST_SUPPORT_UNIQUE_PTR_TEST_HELPER_H