Author: ericwf Date: Tue Jun 21 18:19:13 2016 New Revision: 273334 URL: http://llvm.org/viewvc/llvm-project?rev=273334&view=rev Log: 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 Added: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR27684_contains_ref_to_incomplete_type.pass.cpp Modified: libcxx/trunk/include/tuple libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc.pass.cpp Modified: libcxx/trunk/include/tuple URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=273334&r1=273333&r2=273334&view=diff ============================================================================== --- libcxx/trunk/include/tuple (original) +++ libcxx/trunk/include/tuple Tue Jun 21 18:19:13 2016 @@ -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> Added: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR27684_contains_ref_to_incomplete_type.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR27684_contains_ref_to_incomplete_type.pass.cpp?rev=273334&view=auto ============================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR27684_contains_ref_to_incomplete_type.pass.cpp (added) +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR27684_contains_ref_to_incomplete_type.pass.cpp Tue Jun 21 18:19:13 2016 @@ -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; Modified: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc.pass.cpp?rev=273334&r1=273333&r2=273334&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc.pass.cpp Tue Jun 21 18:19:13 2016 @@ -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> @@ -42,10 +46,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); } @@ -95,21 +95,6 @@ int main() 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 // using 'NonDefaultConstructible' which will cause a compile error _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits