Fix PR27684 - std::tuple no longer accepts reference to incomplete type in some cases.

Libc++ has to deduce the 'allocator_arg_t' parameter as 'AllocArgT' for the
following constructor:

  template <class Alloc> tuple(allocator_arg_t, Alloc const&)

Previously libc++ has tried to support tags derived from 'allocator_arg_t' by
using 'is_base_of<AllocArgT, allocator_arg_t>'. However this breaks whenever a
2-tuple contains a reference to an incomplete type as its first parameter.

See https://llvm.org/bugs/show_bug.cgi?id=27684


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@273334 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2016-06-21 23:19:13 +00:00
parent 7c96ddb563
commit fa5a105971
3 changed files with 57 additions and 21 deletions

View File

@@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++98, c++03
// <tuple>
// template <class... Types> class tuple;
@@ -14,7 +16,9 @@
// template <class Alloc>
// tuple(allocator_arg_t, const Alloc& a);
// UNSUPPORTED: c++98, c++03
// NOTE: this constructor does not currently support tags derived from
// allocator_arg_t because libc++ has to deduce the parameter as a template
// argument. See PR27684 (https://llvm.org/bugs/show_bug.cgi?id=27684)
#include <tuple>
#include <cassert>
@@ -41,10 +45,6 @@ int main()
{
std::tuple<> t(std::allocator_arg, A1<int>());
}
{
DerivedFromAllocArgT tag;
std::tuple<> t(tag, A1<int>());
}
{
std::tuple<int> t(std::allocator_arg, A1<int>());
assert(std::get<0>(t) == 0);
@@ -94,21 +94,6 @@ int main()
assert(!alloc_last::allocator_constructed);
assert(std::get<2>(t) == alloc_last());
}
{
// Test that allocator construction is selected when the user provides
// a custom tag type which derives from allocator_arg_t.
DerivedFromAllocArgT tag;
alloc_first::allocator_constructed = false;
alloc_last::allocator_constructed = false;
std::tuple<DefaultOnly, alloc_first, alloc_last> t(tag, A1<int>(5));
assert(std::get<0>(t) == DefaultOnly());
assert(alloc_first::allocator_constructed);
assert(std::get<1>(t) == alloc_first());
assert(alloc_last::allocator_constructed);
assert(std::get<2>(t) == alloc_last());
}
{
// Test that the uses-allocator default constructor does not evaluate
// it's SFINAE when it otherwise shouldn't be selected. Do this by