// RUN: %clang_cc1 %s -verify -Wno-c++20-extensions template struct TypeList; // === Check results of the builtin. template struct TemplateWrapper { static_assert(__is_same( // expected-error {{static assertion contains an unexpanded parameter pack}} TypeList<__builtin_dedup_pack>, TypeList)); }; template typename Templ, typename ...Types> struct Dependent { using empty_list = Templ<__builtin_dedup_pack<>...>; using same = Templ<__builtin_dedup_pack...>; using twice = Templ<__builtin_dedup_pack...>; using dep_only_types = TypeList<__builtin_dedup_pack...>; using dep_only_template = Templ<__builtin_dedup_pack...>; }; // Check the reverse condition to make sure we see an error and not accidentally produced dependent expression. static_assert(!__is_same(Dependent::empty_list, TypeList<>)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::same, TypeList<>)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::twice, TypeList<>)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::dep_only_types, TypeList<>)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::dep_only_template, TypeList)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::empty_list, TypeList<>)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::same, TypeList)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::twice, TypeList)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::dep_only_types, TypeList)); // expected-error {{static assertion failed}} static_assert(!__is_same(Dependent::dep_only_template, TypeList)); // expected-error {{static assertion failed}} template using Twice = TypeList; template struct TwiceTemplateWrapper { static_assert(!__is_same(Twice<__builtin_dedup_pack...>, TypeList)); // expected-error {{static assertion failed}} }; template struct TwiceTemplateWrapper; // expected-note {{in instantiation of template class 'TwiceTemplateWrapper' requested here}} template struct IntList; // Wrong kinds of template arguments. template struct IntListTemplateWrapper { IntList<__builtin_dedup_pack...>* wrong_template; // expected-error {{template argument for non-type template parameter must be an expression}} // expected-note@-4 {{template parameter is declared here}} TypeList<__builtin_dedup_pack<1, 2, 3>...>* wrong_template_args; // expected-error {{template argument for template type parameter must be a type}} // expected-note@* {{template parameter from hidden source}} __builtin_dedup_pack<> not_enough_args; // expected-error {{data member type contains an unexpanded parameter pack}} // expected-note@* {{template declaration from hidden source}} __builtin_dedup_pack missing_template_args; // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}} }; // Make sure various canonical / non-canonical type representations do not affect results // of the deduplication and the qualifiers do end up creating different types when C++ requires it. using Int = int; using CInt = const Int; using IntArray = Int[10]; using CIntArray = Int[10]; using IntPtr = int*; using CIntPtr = const int*; template struct Foo { static_assert( !__is_same( // expected-error {{static assertion failed}} // expected-note@* {{in instantiation of template class 'Foo'}} TypeList<__builtin_dedup_pack< Int, int, const int, const Int, CInt, const CInt, IntArray, Int[10], int[10], const IntArray, const int[10], CIntArray, const CIntArray, IntPtr, int*, const IntPtr, int* const, CIntPtr, const int*, const IntPtr*, int*const*, CIntPtr*, const int**, const CIntPtr*, const int* const* >...>, TypeList), ""); }; template struct Foo; // === Show an error when packs are used in non-template contexts. static_assert(!__is_same(TypeList<__builtin_dedup_pack...>, TypeList)); // expected-error {{outside}} // Non-dependent uses in template are fine, though. template struct NonDepInTemplate { static_assert(!__is_same(TypeList<__builtin_dedup_pack...>, TypeList)); // expected-error {{static assertion failed}} }; template struct NonDepInTemplate; // expected-note {{requested here}} template class T = __builtin_dedup_pack> // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}} // expected-note@* {{template declaration from hidden source}} struct UseAsTemplate; template class> struct AcceptsTemplateArg; template struct UseAsTemplateWrapper { AcceptsTemplateArg<__builtin_dedup_pack>* a; // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}} // expected-note@* {{template declaration from hidden source}} }; // === Check how expansions in various contexts behave. // The following cases are not supported yet, should produce an error. template struct DedupBases : __builtin_dedup_pack... {}; struct Base1 { int a1; }; struct Base2 { int a2; }; static_assert(DedupBases{1, 2}.a1 != 1); // expected-error {{static assertion failed}} \ // expected-note {{}} static_assert(DedupBases{1, 2}.a2 != 2); // expected-error {{static assertion failed}} \ // expected-note {{}} template constexpr int dedup_params(__builtin_dedup_pack... as) { return (as + ...); } static_assert(dedup_params(1, 2)); // expected-error {{no matching function}} \ // expected-note@-3 {{expansions of '__builtin_dedup_pack' are not supported here}} template constexpr int dedup_params_into_type_list(TypeList<__builtin_dedup_pack...> *, T... as) { return (as + ...); } static_assert(dedup_params_into_type_list(static_cast*>(nullptr), 1, short(1), 1, 1l, 1l) != 5); // expected-error {{static assertion failed}} \ // expected-note {{expression evaluates}} template ...> // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here}} struct InTemplateParams {}; InTemplateParams itp1; InTemplateParams itp2; template struct DeepTemplateParams { template <__builtin_dedup_pack...> // expected-error {{expansions of '__builtin_dedup_pack' are not supported here}} struct Templ {}; }; DeepTemplateParams::Templ<> dtp1; // expected-note {{requested here}} \ // expected-error {{no template named 'Templ'}} template struct MemInitializers : T... { MemInitializers() : __builtin_dedup_pack()... {} // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}} }; MemInitializers<> mi1; // expected-note {{in instantiation of member function}} MemInitializers mi2; // expected-note {{in instantiation of member function}} template constexpr int dedup_in_expressions() { // counts the number of unique Ts. return ((1 + __builtin_dedup_pack()) + ...); // expected-error {{expansions of '__builtin_dedup_pack' are not supported here.}} \ // expected-note@+3 {{in instantiation of function template specialization}} } static_assert(dedup_in_expressions() == 3); // expected-error {{not an integral constant expression}} template void in_exception_spec() throw(__builtin_dedup_pack...); // expected-error{{C++17 does not allow dynamic exception specifications}} \ // expected-note {{use 'noexcept}} \ // expected-error{{expansions of '__builtin_dedup_pack' are not supported here.}} void test_in_exception_spec() { in_exception_spec(); // expected-note {{instantiation of exception specification}} } template constexpr bool in_type_trait = __is_trivially_constructible(int, __builtin_dedup_pack...); // expected-error{{expansions of '__builtin_dedup_pack' are not supported here.}} static_assert(in_type_trait); // expected-note{{in instantiation of variable template specialization}} template struct InFriends { friend __builtin_dedup_pack...; // expected-warning {{variadic 'friend' declarations are a C++2c extension}} \ // expected-error 2 {{expansions of '__builtin_dedup_pack' are not supported here.}} \ // expected-note@* 2 {{in instantiation of template class}} }; struct Friend1 {}; struct Friend2 {}; InFriends<> if1; InFriends if2; template struct InUsingDecl { using __builtin_dedup_pack::func...; // expected-error 2 {{expansions of '__builtin_dedup_pack' are not supported here.}} }; struct WithFunc1 { void func(); }; struct WithFunc2 { void func(int); }; InUsingDecl<> iu1; // expected-note {{in instantiation of template class}} InUsingDecl iu2; // expected-note {{in instantiation of template class}} // Note: produces parsing errors and does not construct pack indexing. // Keep this commented out until the parser supports this. // // template // struct InPackIndexing { // // using type = __builtin_dedup_pack...[0]; // }; // static_assert(__is_same(InPackIndexing, int)); template struct LambdaInitCaptures { static constexpr int test() { [...foos=__builtin_dedup_pack()]{}; // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}} return 3; } }; static_assert(LambdaInitCaptures<>::test() == 3); // expected-note {{in instantiation of member function}} static_assert(LambdaInitCaptures::test() == 3); // expected-note {{in instantiation of member function}} template struct alignas(__builtin_dedup_pack...) AlignAs {}; // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}} AlignAs<> aa1; // expected-note {{in instantiation of template class}} AlignAs aa2; // expected-note {{in instantiation of template class}}