226 lines · cpp
1// RUN: %clang_cc1 %s -verify -Wno-c++20-extensions2template <typename...> struct TypeList;3 4// === Check results of the builtin.5template <class>6struct TemplateWrapper {7 static_assert(__is_same( // expected-error {{static assertion contains an unexpanded parameter pack}}8 TypeList<__builtin_dedup_pack<int, int*, int, double, float>>,9 TypeList<int, int*, double, float>));10};11 12template <template<typename ...> typename Templ, typename ...Types>13struct Dependent {14 using empty_list = Templ<__builtin_dedup_pack<>...>;15 using same = Templ<__builtin_dedup_pack<Types...>...>;16 using twice = Templ<__builtin_dedup_pack<Types..., Types...>...>;17 using dep_only_types = TypeList<__builtin_dedup_pack<Types...>...>;18 using dep_only_template = Templ<__builtin_dedup_pack<int, double, int>...>;19};20 21// Check the reverse condition to make sure we see an error and not accidentally produced dependent expression.22static_assert(!__is_same(Dependent<TypeList>::empty_list, TypeList<>)); // expected-error {{static assertion failed}}23static_assert(!__is_same(Dependent<TypeList>::same, TypeList<>)); // expected-error {{static assertion failed}}24static_assert(!__is_same(Dependent<TypeList>::twice, TypeList<>)); // expected-error {{static assertion failed}}25static_assert(!__is_same(Dependent<TypeList>::dep_only_types, TypeList<>)); // expected-error {{static assertion failed}}26static_assert(!__is_same(Dependent<TypeList>::dep_only_template, TypeList<int, double>)); // expected-error {{static assertion failed}}27static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::empty_list, TypeList<>)); // expected-error {{static assertion failed}}28static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::same, TypeList<int*, double*>)); // expected-error {{static assertion failed}}29static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::twice, TypeList<int*, double*>)); // expected-error {{static assertion failed}}30static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::dep_only_types, TypeList<int*, double*>)); // expected-error {{static assertion failed}}31static_assert(!__is_same(Dependent<TypeList, int*, double*, int*>::dep_only_template, TypeList<int, double>)); // expected-error {{static assertion failed}}32 33 34template <class ...T>35using Twice = TypeList<T..., T...>;36 37template <class>38struct TwiceTemplateWrapper {39 static_assert(!__is_same(Twice<__builtin_dedup_pack<int, double, int>...>, TypeList<int, double, int, double>)); // expected-error {{static assertion failed}}40 41};42template struct TwiceTemplateWrapper<int>; // expected-note {{in instantiation of template class 'TwiceTemplateWrapper<int>' requested here}}43 44template <int...> struct IntList;45// Wrong kinds of template arguments.46template <class> struct IntListTemplateWrapper {47 IntList<__builtin_dedup_pack<int>...>* wrong_template; // expected-error {{template argument for non-type template parameter must be an expression}}48 // expected-note@-4 {{template parameter is declared here}}49 TypeList<__builtin_dedup_pack<1, 2, 3>...>* wrong_template_args; // expected-error {{template argument for template type parameter must be a type}}50 // expected-note@* {{template parameter from hidden source}}51 __builtin_dedup_pack<> not_enough_args; // expected-error {{data member type contains an unexpanded parameter pack}}52 // expected-note@* {{template declaration from hidden source}}53 __builtin_dedup_pack missing_template_args; // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}}54};55 56// Make sure various canonical / non-canonical type representations do not affect results57// of the deduplication and the qualifiers do end up creating different types when C++ requires it.58using Int = int;59using CInt = const Int;60using IntArray = Int[10];61using CIntArray = Int[10];62using IntPtr = int*;63using CIntPtr = const int*;64 65template <class>66struct Foo {67 static_assert(68 !__is_same( // expected-error {{static assertion failed}}69 // expected-note@* {{in instantiation of template class 'Foo<int>'}}70 TypeList<__builtin_dedup_pack<71 Int, int,72 const int, const Int, CInt, const CInt,73 IntArray, Int[10], int[10],74 const IntArray, const int[10], CIntArray, const CIntArray,75 IntPtr, int*,76 const IntPtr, int* const,77 CIntPtr, const int*,78 const IntPtr*, int*const*,79 CIntPtr*, const int**,80 const CIntPtr*, const int* const*81 >...>,82 TypeList<int, const int, int[10], const int [10], int*, int* const, const int*, int*const *, const int**, const int*const*>),83 "");84};85 86template struct Foo<int>;87 88// === Show an error when packs are used in non-template contexts.89static_assert(!__is_same(TypeList<__builtin_dedup_pack<int>...>, TypeList<int>)); // expected-error {{outside}}90// Non-dependent uses in template are fine, though.91template <class T>92struct NonDepInTemplate {93 static_assert(!__is_same(TypeList<__builtin_dedup_pack<int>...>, TypeList<int>)); // expected-error {{static assertion failed}}94};95template struct NonDepInTemplate<int>; // expected-note {{requested here}}96 97template <template<class...> class T = __builtin_dedup_pack> // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}}98 // expected-note@* {{template declaration from hidden source}}99struct UseAsTemplate;100template <template<class...> class>101struct AcceptsTemplateArg;102template <class>103struct UseAsTemplateWrapper {104 AcceptsTemplateArg<__builtin_dedup_pack>* a; // expected-error {{use of template '__builtin_dedup_pack' requires template arguments}}105 // expected-note@* {{template declaration from hidden source}}106};107 108// === Check how expansions in various contexts behave.109// The following cases are not supported yet, should produce an error.110template <class... T>111struct DedupBases : __builtin_dedup_pack<T...>... {};112struct Base1 {113 int a1;114};115struct Base2 {116 int a2;117};118static_assert(DedupBases<Base1, Base1, Base2, Base1, Base2, Base2>{1, 2}.a1 != 1); // expected-error {{static assertion failed}} \119 // expected-note {{}}120static_assert(DedupBases<Base1, Base1, Base2, Base1, Base2, Base2>{1, 2}.a2 != 2); // expected-error {{static assertion failed}} \121 // expected-note {{}}122 123template <class ...T>124constexpr int dedup_params(__builtin_dedup_pack<T...>... as) {125 return (as + ...);126}127static_assert(dedup_params<int, int, short, int, short, short>(1, 2)); // expected-error {{no matching function}} \128 // expected-note@-3 {{expansions of '__builtin_dedup_pack' are not supported here}}129 130template <class ...T>131constexpr int dedup_params_into_type_list(TypeList<__builtin_dedup_pack<T...>...> *, T... as) {132 return (as + ...);133}134static_assert(dedup_params_into_type_list(static_cast<TypeList<int,short,long>*>(nullptr), 1, short(1), 1, 1l, 1l) != 5); // expected-error {{static assertion failed}} \135 // expected-note {{expression evaluates}}136 137template <class T, __builtin_dedup_pack<T, int>...> // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here}}138struct InTemplateParams {};139InTemplateParams<int> itp1;140InTemplateParams<int, 1, 2, 3, 4, 5> itp2;141 142template <class T>143struct DeepTemplateParams {144 template <__builtin_dedup_pack<T, int>...> // expected-error {{expansions of '__builtin_dedup_pack' are not supported here}}145 struct Templ {};146};147DeepTemplateParams<int>::Templ<> dtp1; // expected-note {{requested here}} \148 // expected-error {{no template named 'Templ'}}149 150 151template <class ...T>152struct MemInitializers : T... {153 MemInitializers() : __builtin_dedup_pack<T...>()... {} // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}}154};155MemInitializers<> mi1; // expected-note {{in instantiation of member function}}156MemInitializers<Base1, Base2> mi2; // expected-note {{in instantiation of member function}}157 158template <class ...T>159constexpr int dedup_in_expressions() {160 // counts the number of unique Ts.161 return ((1 + __builtin_dedup_pack<T...>()) + ...); // expected-error {{expansions of '__builtin_dedup_pack' are not supported here.}} \162 // expected-note@+3 {{in instantiation of function template specialization}}163}164static_assert(dedup_in_expressions<int, int, short, double, int, short, double, int>() == 3); // expected-error {{not an integral constant expression}}165 166template <class ...T>167void in_exception_spec() throw(__builtin_dedup_pack<T...>...); // expected-error{{C++17 does not allow dynamic exception specifications}} \168 // expected-note {{use 'noexcept}} \169 // expected-error{{expansions of '__builtin_dedup_pack' are not supported here.}}170 171void test_in_exception_spec() {172 in_exception_spec<int, double, int>(); // expected-note {{instantiation of exception specification}}173}174 175template <class ...T>176constexpr bool in_type_trait = __is_trivially_constructible(int, __builtin_dedup_pack<T...>...); // expected-error{{expansions of '__builtin_dedup_pack' are not supported here.}}177 178static_assert(in_type_trait<int, int, int>); // expected-note{{in instantiation of variable template specialization}}179 180template <class ...T>181struct InFriends {182 friend __builtin_dedup_pack<T>...; // expected-warning {{variadic 'friend' declarations are a C++2c extension}} \183 // expected-error 2 {{expansions of '__builtin_dedup_pack' are not supported here.}} \184 // expected-note@* 2 {{in instantiation of template class}}185 186};187struct Friend1 {};188struct Friend2 {};189InFriends<> if1;190InFriends<Friend1, Friend2> if2;191 192template <class ...T>193struct InUsingDecl {194 using __builtin_dedup_pack<T...>::func...; // expected-error 2 {{expansions of '__builtin_dedup_pack' are not supported here.}}195};196struct WithFunc1 { void func(); };197struct WithFunc2 { void func(int); };198InUsingDecl<> iu1; // expected-note {{in instantiation of template class}}199InUsingDecl<WithFunc1, WithFunc2> iu2; // expected-note {{in instantiation of template class}}200 201// Note: produces parsing errors and does not construct pack indexing.202// Keep this commented out until the parser supports this.203//204// template <class ...T>205// struct InPackIndexing {206//207// using type = __builtin_dedup_pack<T...>...[0];208// };209// static_assert(__is_same(InPackIndexing<int, int>, int));210 211template <class ...T>212struct LambdaInitCaptures {213 static constexpr int test() {214 [...foos=__builtin_dedup_pack<T...>()]{}; // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}}215 return 3;216 }217};218static_assert(LambdaInitCaptures<>::test() == 3); // expected-note {{in instantiation of member function}}219static_assert(LambdaInitCaptures<int, int, int>::test() == 3); // expected-note {{in instantiation of member function}}220 221template <class ...T>222struct alignas(__builtin_dedup_pack<T...>...) AlignAs {}; // expected-error 2{{expansions of '__builtin_dedup_pack' are not supported here.}}223AlignAs<> aa1; // expected-note {{in instantiation of template class}}224AlignAs<int, double> aa2; // expected-note {{in instantiation of template class}}225 226