dlj updated this revision to Diff 115164.
dlj added a comment.

- Remove deque from the test for now.


https://reviews.llvm.org/D37538

Files:
  include/__split_buffer
  include/deque
  include/memory
  test/std/containers/containers.general/construct_destruct.pass.cpp

Index: test/std/containers/containers.general/construct_destruct.pass.cpp
===================================================================
--- /dev/null
+++ test/std/containers/containers.general/construct_destruct.pass.cpp
@@ -0,0 +1,128 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+#include <array>
+#include <cassert>
+#include <forward_list>
+#include <list>
+#include <map>
+#include <queue>
+#include <set>
+#include <stack>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+// Holder<ns::T> is a do-nothing wrapper around a value of the given type.
+//
+// Since unqualified name lookup and operator overload lookup participate in
+// ADL, the dependent type ns::T contributes to the overload set considered by
+// ADL. In other words, ADL will consider all associated namespaces: this
+// includes not only N, but also any inline friend functions declared by ns::T.
+//
+// The purpose of this test is to ensure that simply constructing or destroying
+// a container does not invoke ADL which would be problematic for unknown types.
+// By using the type 'Holder<ns::T> *' as a container value, we can avoid the
+// obvious problems with unknown types: a pointer is trivial, and its size is
+// known. However, any ADL which includes ns::T as an associated namesapce will
+// fail.
+//
+// For example:
+//
+//   namespace ns {
+//     class T {
+//       // 13.5.7 [over.inc]:
+//       friend std::list<T *>::const_iterator
+//       operator++(std::list<T *>::const_iterator it) {
+//         return /* ... */;
+//       }
+//     };
+//   }
+//
+// The C++ standard stipulates that some functions, such as std::advance, use
+// overloaded operators (in C++14: 24.4.4 [iterator.operations]). The
+// implication is that calls to such a function are dependent on knowing the
+// overload set of operators in all associated namespaces; under ADL, this
+// includes the private friend function in the example above.
+//
+// However, for some operations, such as construction and destruction, no such
+// ADL is required. This can be important, for example, when using the Pimpl
+// pattern:
+//
+//   // Defined in a header file:
+//   class InterfaceList {
+//     // Defined in a .cpp file:
+//     class Impl;
+//     vector<Impl*> impls;
+//   public:
+//     ~InterfaceList();
+//   };
+//
+template <class T>
+class Holder { T value; };
+
+namespace ns { class Fwd; }
+
+// TestSequencePtr and TestMappingPtr ensure that a given container type can be
+// default-constructed and destroyed with an incomplete value pointer type.
+template <template <class...> class Container>
+void TestSequencePtr() {
+  using X = Container<Holder<ns::Fwd>*>;
+  {
+    X u;
+    assert(u.empty());
+  }
+  {
+    auto u = X();
+    assert(u.empty());
+  }
+}
+
+template <template <class...> class Container>
+void TestMappingPtr() {
+  {
+    using X = Container<int, Holder<ns::Fwd>*>;
+    X u1;
+    assert(u1.empty());
+    auto u2 = X();
+    assert(u2.empty());
+  }
+  {
+    using X = Container<Holder<ns::Fwd>*, int>;
+    X u1;
+    assert(u1.empty());
+    auto u2 = X();
+    assert(u2.empty());
+  }
+}
+
+int main()
+{
+  // Sequence containers:
+  {
+    std::array<Holder<ns::Fwd>*, 1> a;
+    (void)a;
+  }
+  TestSequencePtr<std::forward_list>();
+  TestSequencePtr<std::list>();
+  TestSequencePtr<std::vector>();
+
+  // Associative containers, non-mapping:
+  TestSequencePtr<std::set>();
+  TestSequencePtr<std::unordered_set>();
+
+  // Associative containers, mapping:
+  TestMappingPtr<std::map>();
+  TestMappingPtr<std::unordered_map>();
+
+  // Container adapters:
+  TestSequencePtr<std::queue>();
+  TestSequencePtr<std::stack>();
+}
Index: include/memory
===================================================================
--- include/memory
+++ include/memory
@@ -1346,9 +1346,9 @@
 struct __has_construct
     : integral_constant<bool,
         is_same<
-            decltype(__has_construct_test(declval<_Alloc>(),
-                                          declval<_Pointer>(),
-                                          declval<_Args>()...)),
+            decltype(_VSTD::__has_construct_test(declval<_Alloc>(),
+                                                 declval<_Pointer>(),
+                                                 declval<_Args>()...)),
             true_type>::value>
 {
 };
@@ -1367,8 +1367,8 @@
 struct __has_destroy
     : integral_constant<bool,
         is_same<
-            decltype(__has_destroy_test(declval<_Alloc>(),
-                                        declval<_Pointer>())),
+            decltype(_VSTD::__has_destroy_test(declval<_Alloc>(),
+                                               declval<_Pointer>())),
             true_type>::value>
 {
 };
@@ -1387,7 +1387,7 @@
 struct __has_max_size
     : integral_constant<bool,
         is_same<
-            decltype(__has_max_size_test(declval<_Alloc&>())),
+            decltype(_VSTD::__has_max_size_test(declval<_Alloc&>())),
             true_type>::value>
 {
 };
@@ -1406,7 +1406,7 @@
 struct __has_select_on_container_copy_construction
     : integral_constant<bool,
         is_same<
-            decltype(__has_select_on_container_copy_construction_test(declval<_Alloc&>())),
+            decltype(_VSTD::__has_select_on_container_copy_construction_test(declval<_Alloc&>())),
             true_type>::value>
 {
 };
@@ -1547,7 +1547,7 @@
     template <class _Tp>
         _LIBCPP_INLINE_VISIBILITY
         static void destroy(allocator_type& __a, _Tp* __p)
-            {__destroy(__has_destroy<allocator_type, _Tp*>(), __a, __p);}
+            {__destroy(_VSTD::__has_destroy<allocator_type, _Tp*>(), __a, __p);}
 
     _LIBCPP_INLINE_VISIBILITY
     static size_type max_size(const allocator_type& __a) _NOEXCEPT
Index: include/deque
===================================================================
--- include/deque
+++ include/deque
@@ -1164,8 +1164,8 @@
 __deque_base<_Tp, _Allocator>::clear() _NOEXCEPT
 {
     allocator_type& __a = __alloc();
-    for (iterator __i = begin(), __e = end(); __i != __e; ++__i)
-        __alloc_traits::destroy(__a, _VSTD::addressof(*__i));
+    for (iterator __i = begin(), __e = end(); __i.__ptr_ != __e.__ptr_; __i.operator++())
+        __alloc_traits::destroy(__a, _VSTD::addressof(__i.operator*()));
     size() = 0;
     while (__map_.size() > 2)
     {
Index: include/__split_buffer
===================================================================
--- include/__split_buffer
+++ include/__split_buffer
@@ -276,7 +276,7 @@
 __split_buffer<_Tp, _Allocator>::__destruct_at_begin(pointer __new_begin, false_type)
 {
     while (__begin_ != __new_begin)
-        __alloc_traits::destroy(__alloc(), __to_raw_pointer(__begin_++));
+        __alloc_traits::destroy(__alloc(), _VSTD::__to_raw_pointer(__begin_++));
 }
 
 template <class _Tp, class _Allocator>
@@ -293,7 +293,7 @@
 __split_buffer<_Tp, _Allocator>::__destruct_at_end(pointer __new_last, false_type) _NOEXCEPT
 {
     while (__new_last != __end_)
-        __alloc_traits::destroy(__alloc(), __to_raw_pointer(--__end_));
+        __alloc_traits::destroy(__alloc(), _VSTD::__to_raw_pointer(--__end_));
 }
 
 template <class _Tp, class _Allocator>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to