[libcxx] r313324 - Fix accidental ADL in std::allocator_traits meta-programming.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 14 17:31:38 PDT 2017


Author: ericwf
Date: Thu Sep 14 17:31:38 2017
New Revision: 313324

URL: http://llvm.org/viewvc/llvm-project?rev=313324&view=rev
Log:
Fix accidental ADL in std::allocator_traits meta-programming.

There were a number of cases where __double_underscore functions,
for example __has_construct_test, were called without being qualified,
causing ADL to occur. This patch qualifies those calls to avoid this
problem.

Thanks to David L. Jones for point out the issue initially.

Added:
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/incomplete_type_helper.h
Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp
    libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Thu Sep 14 17:31:38 2017
@@ -1302,7 +1302,7 @@ struct __allocator_traits_rebind<_Alloc<
 template <class _Alloc, class _SizeType, class _ConstVoidPtr>
 auto
 __has_allocate_hint_test(_Alloc&& __a, _SizeType&& __sz, _ConstVoidPtr&& __p)
-    -> decltype(__a.allocate(__sz, __p), true_type());
+    -> decltype((void)__a.allocate(__sz, __p), true_type());
 
 template <class _Alloc, class _SizeType, class _ConstVoidPtr>
 auto
@@ -1313,7 +1313,7 @@ template <class _Alloc, class _SizeType,
 struct __has_allocate_hint
     : integral_constant<bool,
         is_same<
-            decltype(__has_allocate_hint_test(declval<_Alloc>(),
+            decltype(_VSTD::__has_allocate_hint_test(declval<_Alloc>(),
                                           declval<_SizeType>(),
                                           declval<_ConstVoidPtr>())),
             true_type>::value>
@@ -1346,7 +1346,7 @@ template <class _Alloc, class _Pointer,
 struct __has_construct
     : integral_constant<bool,
         is_same<
-            decltype(__has_construct_test(declval<_Alloc>(),
+            decltype(_VSTD::__has_construct_test(declval<_Alloc>(),
                                           declval<_Pointer>(),
                                           declval<_Args>()...)),
             true_type>::value>
@@ -1367,7 +1367,7 @@ template <class _Alloc, class _Pointer>
 struct __has_destroy
     : integral_constant<bool,
         is_same<
-            decltype(__has_destroy_test(declval<_Alloc>(),
+            decltype(_VSTD::__has_destroy_test(declval<_Alloc>(),
                                         declval<_Pointer>())),
             true_type>::value>
 {
@@ -1387,7 +1387,7 @@ template <class _Alloc>
 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 @@ template <class _Alloc>
 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>
 {
 };

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate.pass.cpp Thu Sep 14 17:31:38 2017
@@ -20,6 +20,8 @@
 #include <cstdint>
 #include <cassert>
 
+#include "incomplete_type_helper.h"
+
 template <class T>
 struct A
 {
@@ -34,6 +36,14 @@ struct A
 
 int main()
 {
+  {
     A<int> a;
     assert(std::allocator_traits<A<int> >::allocate(a, 10) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)));
+  }
+  {
+    typedef IncompleteHolder* VT;
+    typedef A<VT> Alloc;
+    Alloc a;
+    assert(std::allocator_traits<Alloc >::allocate(a, 10) == reinterpret_cast<VT*>(static_cast<std::uintptr_t>(0xDEADBEEF)));
+  }
 }

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/allocate_hint.pass.cpp Thu Sep 14 17:31:38 2017
@@ -21,6 +21,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "incomplete_type_helper.h"
 
 template <class T>
 struct A
@@ -52,12 +53,29 @@ struct B
     }
 };
 
+
 int main()
 {
 #if TEST_STD_VER >= 11
+  {
     A<int> a;
     assert(std::allocator_traits<A<int> >::allocate(a, 10, nullptr) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)));
+  }
+  {
+    typedef IncompleteHolder* VT;
+    typedef A<VT> Alloc;
+    Alloc a;
+    assert(std::allocator_traits<Alloc >::allocate(a, 10, nullptr) == reinterpret_cast<VT*>(static_cast<std::uintptr_t>(0xDEADBEEF)));
+  }
 #endif
+  {
     B<int> b;
     assert(std::allocator_traits<B<int> >::allocate(b, 11, nullptr) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xFEADBEEF)));
+  }
+  {
+    typedef IncompleteHolder* VT;
+    typedef B<VT> Alloc;
+    Alloc b;
+    assert(std::allocator_traits<Alloc >::allocate(b, 11, nullptr) == reinterpret_cast<VT*>(static_cast<std::uintptr_t>(0xFEADBEEF)));
+  }
 }

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/construct.pass.cpp Thu Sep 14 17:31:38 2017
@@ -23,6 +23,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "incomplete_type_helper.h"
 
 template <class T>
 struct A
@@ -107,6 +108,13 @@ int main()
         std::allocator_traits<A<int> >::construct(a, (A2*)&a2, 'd', 5);
         assert(A2::count == 1);
     }
+    {
+      typedef IncompleteHolder* VT;
+      typedef A<VT> Alloc;
+      Alloc a;
+      std::aligned_storage<sizeof(VT)>::type store;
+      std::allocator_traits<Alloc>::construct(a, (VT*)&store, nullptr);
+    }
 #if TEST_STD_VER >= 11
     {
         A0::count = 0;

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/deallocate.pass.cpp Thu Sep 14 17:31:38 2017
@@ -20,6 +20,8 @@
 #include <cstdint>
 #include <cassert>
 
+#include "incomplete_type_helper.h"
+
 int called = 0;
 
 template <class T>
@@ -37,7 +39,17 @@ struct A
 
 int main()
 {
+  {
     A<int> a;
     std::allocator_traits<A<int> >::deallocate(a, reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)), 10);
     assert(called == 1);
+  }
+  called = 0;
+  {
+    typedef IncompleteHolder* VT;
+    typedef A<VT> Alloc;
+    Alloc a;
+    std::allocator_traits<Alloc >::deallocate(a, reinterpret_cast<VT*>(static_cast<std::uintptr_t>(0xDEADBEEF)), 10);
+    assert(called == 1);
+  }
 }

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/destroy.pass.cpp Thu Sep 14 17:31:38 2017
@@ -23,6 +23,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "incomplete_type_helper.h"
 
 template <class T>
 struct A
@@ -65,6 +66,13 @@ int main()
         std::allocator_traits<A<int> >::destroy(a, (A0*)&a0);
         assert(A0::count == 1);
     }
+    {
+      typedef IncompleteHolder* VT;
+      typedef A<VT> Alloc;
+      Alloc a;
+      std::aligned_storage<sizeof(VT)>::type store;
+      std::allocator_traits<Alloc>::destroy(a, (VT*)&store);
+    }
 #if TEST_STD_VER >= 11
     {
         A0::count = 0;

Added: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/incomplete_type_helper.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/incomplete_type_helper.h?rev=313324&view=auto
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/incomplete_type_helper.h (added)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/incomplete_type_helper.h Thu Sep 14 17:31:38 2017
@@ -0,0 +1,14 @@
+#ifndef TEST_INCOMPLETE_TYPE_HELPER_H
+#define TEST_INCOMPLETE_TYPE_HELPER_H
+
+#include "min_allocator.h"
+
+namespace NS {
+  struct Incomplete;
+}
+
+template <class T> struct Holder { T value; };
+
+typedef Holder<NS::Incomplete> IncompleteHolder;
+
+#endif

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/max_size.pass.cpp Thu Sep 14 17:31:38 2017
@@ -22,6 +22,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "incomplete_type_helper.h"
 
 template <class T>
 struct A
@@ -51,6 +52,12 @@ int main()
         const B<int> b = {};
         assert(std::allocator_traits<B<int> >::max_size(b) == 100);
     }
+    {
+        typedef IncompleteHolder* VT;
+        typedef B<VT> Alloc;
+        Alloc a;
+        assert(std::allocator_traits<Alloc >::max_size(a) == 100);
+    }
 #if TEST_STD_VER >= 11
     {
         A<int> a;

Modified: libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp?rev=313324&r1=313323&r2=313324&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/allocator.traits/allocator.traits.members/select_on_container_copy_construction.pass.cpp Thu Sep 14 17:31:38 2017
@@ -23,6 +23,7 @@
 #include <cassert>
 
 #include "test_macros.h"
+#include "incomplete_type_helper.h"
 
 template <class T>
 struct A
@@ -57,6 +58,12 @@ int main()
         const A<int> a(0);
         assert(std::allocator_traits<A<int> >::select_on_container_copy_construction(a).id == 0);
     }
+    {
+        typedef IncompleteHolder* VT;
+        typedef A<VT> Alloc;
+        Alloc a;
+        assert(std::allocator_traits<Alloc>::select_on_container_copy_construction(a).id == 0);
+    }
 #if TEST_STD_VER >= 11
     {
         B<int> b;




More information about the cfe-commits mailing list