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. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@313324 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1302,7 +1302,7 @@ struct __allocator_traits_rebind<_Alloc<_Tp, _A0, _A1, _A2>, _Up, false>
|
|||||||
template <class _Alloc, class _SizeType, class _ConstVoidPtr>
|
template <class _Alloc, class _SizeType, class _ConstVoidPtr>
|
||||||
auto
|
auto
|
||||||
__has_allocate_hint_test(_Alloc&& __a, _SizeType&& __sz, _ConstVoidPtr&& __p)
|
__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>
|
template <class _Alloc, class _SizeType, class _ConstVoidPtr>
|
||||||
auto
|
auto
|
||||||
@@ -1313,7 +1313,7 @@ template <class _Alloc, class _SizeType, class _ConstVoidPtr>
|
|||||||
struct __has_allocate_hint
|
struct __has_allocate_hint
|
||||||
: integral_constant<bool,
|
: integral_constant<bool,
|
||||||
is_same<
|
is_same<
|
||||||
decltype(__has_allocate_hint_test(declval<_Alloc>(),
|
decltype(_VSTD::__has_allocate_hint_test(declval<_Alloc>(),
|
||||||
declval<_SizeType>(),
|
declval<_SizeType>(),
|
||||||
declval<_ConstVoidPtr>())),
|
declval<_ConstVoidPtr>())),
|
||||||
true_type>::value>
|
true_type>::value>
|
||||||
@@ -1346,7 +1346,7 @@ template <class _Alloc, class _Pointer, class ..._Args>
|
|||||||
struct __has_construct
|
struct __has_construct
|
||||||
: integral_constant<bool,
|
: integral_constant<bool,
|
||||||
is_same<
|
is_same<
|
||||||
decltype(__has_construct_test(declval<_Alloc>(),
|
decltype(_VSTD::__has_construct_test(declval<_Alloc>(),
|
||||||
declval<_Pointer>(),
|
declval<_Pointer>(),
|
||||||
declval<_Args>()...)),
|
declval<_Args>()...)),
|
||||||
true_type>::value>
|
true_type>::value>
|
||||||
@@ -1367,7 +1367,7 @@ template <class _Alloc, class _Pointer>
|
|||||||
struct __has_destroy
|
struct __has_destroy
|
||||||
: integral_constant<bool,
|
: integral_constant<bool,
|
||||||
is_same<
|
is_same<
|
||||||
decltype(__has_destroy_test(declval<_Alloc>(),
|
decltype(_VSTD::__has_destroy_test(declval<_Alloc>(),
|
||||||
declval<_Pointer>())),
|
declval<_Pointer>())),
|
||||||
true_type>::value>
|
true_type>::value>
|
||||||
{
|
{
|
||||||
@@ -1387,7 +1387,7 @@ template <class _Alloc>
|
|||||||
struct __has_max_size
|
struct __has_max_size
|
||||||
: integral_constant<bool,
|
: integral_constant<bool,
|
||||||
is_same<
|
is_same<
|
||||||
decltype(__has_max_size_test(declval<_Alloc&>())),
|
decltype(_VSTD::__has_max_size_test(declval<_Alloc&>())),
|
||||||
true_type>::value>
|
true_type>::value>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
@@ -1406,7 +1406,7 @@ template <class _Alloc>
|
|||||||
struct __has_select_on_container_copy_construction
|
struct __has_select_on_container_copy_construction
|
||||||
: integral_constant<bool,
|
: integral_constant<bool,
|
||||||
is_same<
|
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>
|
true_type>::value>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A
|
struct A
|
||||||
{
|
{
|
||||||
@@ -33,7 +35,15 @@ struct A
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
{
|
||||||
{
|
{
|
||||||
A<int> a;
|
A<int> a;
|
||||||
assert(std::allocator_traits<A<int> >::allocate(a, 10) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)));
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A
|
struct A
|
||||||
@@ -52,12 +53,29 @@ struct B
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
|
{
|
||||||
A<int> a;
|
A<int> a;
|
||||||
assert(std::allocator_traits<A<int> >::allocate(a, 10, nullptr) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)));
|
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
|
#endif
|
||||||
|
{
|
||||||
B<int> b;
|
B<int> b;
|
||||||
assert(std::allocator_traits<B<int> >::allocate(b, 11, nullptr) == reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xFEADBEEF)));
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A
|
struct A
|
||||||
@@ -107,6 +108,13 @@ int main()
|
|||||||
std::allocator_traits<A<int> >::construct(a, (A2*)&a2, 'd', 5);
|
std::allocator_traits<A<int> >::construct(a, (A2*)&a2, 'd', 5);
|
||||||
assert(A2::count == 1);
|
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
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
A0::count = 0;
|
A0::count = 0;
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
int called = 0;
|
int called = 0;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -36,8 +38,18 @@ struct A
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
{
|
||||||
{
|
{
|
||||||
A<int> a;
|
A<int> a;
|
||||||
std::allocator_traits<A<int> >::deallocate(a, reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)), 10);
|
std::allocator_traits<A<int> >::deallocate(a, reinterpret_cast<int*>(static_cast<std::uintptr_t>(0xDEADBEEF)), 10);
|
||||||
assert(called == 1);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A
|
struct A
|
||||||
@@ -65,6 +66,13 @@ int main()
|
|||||||
std::allocator_traits<A<int> >::destroy(a, (A0*)&a0);
|
std::allocator_traits<A<int> >::destroy(a, (A0*)&a0);
|
||||||
assert(A0::count == 1);
|
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
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
A0::count = 0;
|
A0::count = 0;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A
|
struct A
|
||||||
@@ -51,6 +52,12 @@ int main()
|
|||||||
const B<int> b = {};
|
const B<int> b = {};
|
||||||
assert(std::allocator_traits<B<int> >::max_size(b) == 100);
|
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
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
A<int> a;
|
A<int> a;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
#include "incomplete_type_helper.h"
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct A
|
struct A
|
||||||
@@ -57,6 +58,12 @@ int main()
|
|||||||
const A<int> a(0);
|
const A<int> a(0);
|
||||||
assert(std::allocator_traits<A<int> >::select_on_container_copy_construction(a).id == 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
|
#if TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
B<int> b;
|
B<int> b;
|
||||||
|
|||||||
Reference in New Issue
Block a user