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:
Eric Fiselier
2017-09-15 00:31:38 +00:00
parent 0a2af12aff
commit 63d88110cc
9 changed files with 90 additions and 6 deletions

View File

@@ -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)));
}
}

View File

@@ -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)));
}
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;