forked from OSchip/llvm-project
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 llvm-svn: 273334
This commit is contained in:
parent
62ef3bfd3d
commit
092386771d
|
@ -662,7 +662,7 @@ public:
|
|||
|
||||
template <class _AllocArgT, class _Alloc, bool _Dummy = true, class = typename enable_if<
|
||||
__lazy_and<
|
||||
is_base_of<allocator_arg_t, _AllocArgT>,
|
||||
is_same<allocator_arg_t, _AllocArgT>,
|
||||
__lazy_all<__dependent_type<is_default_constructible<_Tp>, _Dummy>...>
|
||||
>::value
|
||||
>::type>
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
// <tuple>
|
||||
|
||||
// template <class... Types> class tuple;
|
||||
|
||||
// template <class Alloc> tuple(allocator_arg_t, Alloc const&)
|
||||
|
||||
// Libc++ has to deduce the 'allocator_arg_t' parameter for this constructor
|
||||
// as 'AllocArgT'. 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 PR27684.
|
||||
|
||||
#include <tuple>
|
||||
#include <cassert>
|
||||
|
||||
struct IncompleteType;
|
||||
extern IncompleteType inc1;
|
||||
extern IncompleteType inc2;
|
||||
IncompleteType const& cinc1 = inc1;
|
||||
IncompleteType const& cinc2 = inc2;
|
||||
|
||||
int main() {
|
||||
using IT = IncompleteType;
|
||||
{ // try calling tuple(Tp const&...)
|
||||
using Tup = std::tuple<const IT&, const IT&>;
|
||||
Tup t(cinc1, cinc2);
|
||||
assert(&std::get<0>(t) == &inc1);
|
||||
assert(&std::get<1>(t) == &inc2);
|
||||
}
|
||||
{ // try calling tuple(Up&&...)
|
||||
using Tup = std::tuple<const IT&, const IT&>;
|
||||
Tup t(inc1, inc2);
|
||||
assert(&std::get<0>(t) == &inc1);
|
||||
assert(&std::get<1>(t) == &inc2);
|
||||
}
|
||||
}
|
||||
|
||||
struct IncompleteType {};
|
||||
IncompleteType inc1;
|
||||
IncompleteType inc2;
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue