1 // RUN: %clang_cc1 -verify -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s -fclang-abi-compat=latest | FileCheck %s
2 // RUN: %clang_cc1 -verify -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s -fclang-abi-compat=19 | FileCheck %s --check-prefix=CLANG19
3 // RUN: %clang_cc1 -verify -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s -fclang-abi-compat=17 | FileCheck %s --check-prefix=CLANG17
4 // expected-no-diagnostics
7 template <bool> struct S
{};
8 template <typename
> concept C
= true;
9 template <typename T
= int> S
<C
<T
>> f0() { return S
<C
<T
>>{}; }
10 template S
<C
<int>> f0
<>();
11 // CHECK: @_ZN5test12f0IiEENS_1SIX1CIT_EEEEv(
12 // CLANG17: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv(
15 template <bool> struct S
{};
16 template <typename
> concept C
= true;
17 template <typename
, typename
> concept D
= true;
19 template <typename T
= int> S
<test1::C
<T
>> f0a() { return S
<C
<T
>>{}; }
20 template S
<test1::C
<int>> f0a
<>();
21 // CHECK: @_Z3f0aIiE1SIXsr5test1E1CIT_EEEv(
22 // CLANG17: @_Z3f0aIiE1SIL_ZN5test11CIT_EEEEv(
24 template <typename T
= int> S
<C
<T
>> f0() { return S
<C
<T
>>{}; }
25 template S
<C
<int>> f0
<>();
26 // CHECK: @_Z2f0IiE1SIX1CIT_EEEv(
27 // CLANG17: @_Z2f0IiE1SIL_Z1CIT_EEEv(
29 template<typename T
> concept True
= true;
32 // Member-like friends.
33 template<typename T
> struct A
{
34 friend void f(...) requires True
<T
> {}
36 template<typename U
= void>
37 friend void g(...) requires True
<T
> && True
<U
> {}
39 template<typename U
= void>
40 friend void h(...) requires True
<U
> {}
42 template<typename U
= void> requires True
<T
> && True
<U
>
45 template<typename U
= void> requires True
<U
>
48 template<True U
= void> requires True
<T
>
51 template<True U
= void>
57 // CHECK-LABEL: define {{.*}}@{{.*}}test2{{.*}}use
59 // CHECK: call {{.*}}@_ZN5test21AIiEF1fEzQ4TrueIT_E(
60 // CLANG17: call {{.*}}@_ZN5test21fEz(
62 // CHECK: call {{.*}}@_ZN5test21AIiEF1gIvEEvzQaa4TrueIT_E4TrueITL0__E(
63 // CLANG19: call {{.*}}@_ZN5test2F1gIvEEvzQaa4TrueIT_E4TrueITL0__E(
64 // CLANG17: call {{.*}}@_ZN5test21gIvEEvz(
66 // CHECK: call {{.*}}@_ZN5test21hIvEEvzQ4TrueITL0__E(
67 // CLANG17: call {{.*}}@_ZN5test21hIvEEvz(
69 // CHECK: call {{.*}}@_ZN5test21AIiEF1iIvQaa4TrueIT_E4TrueITL0__EEEvz(
70 // CLANG19: call {{.*}}@_ZN5test2F1iIvQaa4TrueIT_E4TrueITL0__EEEvz(
71 // CLANG17: call {{.*}}@_ZN5test21iIvEEvz(
73 // CHECK: call {{.*}}@_ZN5test21jIvQ4TrueITL0__EEEvz(
74 // CLANG17: call {{.*}}@_ZN5test21jIvEEvz(
76 // CHECK: call {{.*}}@_ZN5test21AIiEF1kITk4TruevQ4TrueIT_EEEvz(
77 // CLANG19: call {{.*}}@_ZN5test2F1kITk4TruevQ4TrueIT_EEEvz(
78 // CLANG17: call {{.*}}@_ZN5test21kIvEEvz(
80 // CHECK: call {{.*}}@_ZN5test21lITk4TruevEEvz(
81 // CLANG17: call {{.*}}@_ZN5test21lIvEEvz(
87 // Unconstrained auto.
88 template<auto> void d() {}
90 // CHECK: define {{.*}}@_ZN5test31dITnDaLi0EEEvv(
91 // CLANG17: define {{.*}}@_ZN5test31dILi0EEEvv(
93 template<decltype(auto)> void e() {}
95 // CHECK: define {{.*}}@_ZN5test31eITnDcLi0EEEvv(
96 // CLANG17: define {{.*}}@_ZN5test31eILi0EEEvv(
99 template<C
auto> void f() {}
100 template void f
<0>();
101 // CHECK: define {{.*}}@_ZN5test31fITnDk1CLi0EEEvv(
102 // CLANG17: define {{.*}}@_ZN5test31fILi0EEEvv(
104 template<D
<int> auto> void g() {}
105 template void g
<0>();
106 // CHECK: define {{.*}}@_ZN5test31gITnDk1DIiELi0EEEvv(
107 // CLANG17: define {{.*}}@_ZN5test31gILi0EEEvv(
109 template<typename T
, D
<T
> auto> void h() {}
110 template void h
<int, 0>();
111 // CHECK: define {{.*}}@_ZN5test31hIiTnDk1DIT_ELi0EEEvv(
112 // CLANG17: define {{.*}}@_ZN5test31hIiLi0EEEvv(
114 template<typename T
> void i(decltype(new C
auto(T()))) {}
115 template void i
<int>(int*);
116 // CHECK: define {{.*}}@_ZN5test31iIiEEvDTnw_Dk1CpicvT__EEE(
117 // CLANG17: define {{.*}}@_ZN5test31iIiEEvDTnw_DapicvT__EEE(
119 template<typename T
> void j(decltype(new C
decltype(auto)(T()))) {}
120 template void j
<int>(int*);
121 // CHECK: define {{.*}}@_ZN5test31jIiEEvDTnw_DK1CpicvT__EEE(
122 // CLANG17: define {{.*}}@_ZN5test31jIiEEvDTnw_DcpicvT__EEE(
126 // Constrained type parameters.
127 template<C
> void f() {}
128 template void f
<int>();
129 // CHECK: define {{.*}}@_ZN5test41fITk1CiEEvv(
130 // CLANG17: define {{.*}}@_ZN5test41fIiEEvv(
132 template<D
<int>> void g() {}
133 template void g
<int>();
134 // CHECK: define {{.*}}@_ZN5test41gITk1DIiEiEEvv(
135 // CLANG17: define {{.*}}@_ZN5test41gIiEEvv(
139 // Exact-match vs non-exact-match template template parameters.
140 template<typename T
, T V
> struct X
{};
141 template<typename T
, T V
> requires C
<T
> struct Y
{};
142 template<C T
, T V
> struct Z
{};
144 template<template<typename T
, T
> typename
> void f() {}
145 // CHECK: define {{.*}}@_ZN5test51fINS_1XEEEvv(
146 template void f
<X
>();
147 // CHECK: define {{.*}}@_ZN5test51fITtTyTnTL0__ENS_1YEEEvv(
148 template void f
<Y
>();
149 // CHECK: define {{.*}}@_ZN5test51fITtTyTnTL0__ENS_1ZEEEvv(
150 template void f
<Z
>();
152 template<template<typename T
, T
> requires C
<T
> typename
> void g() {}
153 // CHECK: define {{.*}}@_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1XEEEvv(
154 template void g
<X
>();
155 // CHECK: define {{.*}}@_ZN5test51gINS_1YEEEvv(
156 template void g
<Y
>();
157 // CHECK: define {{.*}}@_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1ZEEEvv(
158 template void g
<Z
>();
160 template<template<C T
, T
> typename
> void h() {}
161 // CHECK: define {{.*}}@_ZN5test51hITtTk1CTnTL0__ENS_1XEEEvv(
162 template void h
<X
>();
163 // CHECK: define {{.*}}@_ZN5test51hITtTk1CTnTL0__ENS_1YEEEvv(
164 template void h
<Y
>();
165 // CHECK: define {{.*}}@_ZN5test51hINS_1ZEEEvv(
166 template void h
<Z
>();
168 // Packs must match the first argument.
169 template<template<C T
, T
> typename
...> void i() {}
170 // CHECK: define {{.*}}@_ZN5test51iITpTtTk1CTnTL0__EJNS_1XENS_1YENS_1ZEEEEvv(
171 template void i
<X
, Y
, Z
>();
172 // CHECK: define {{.*}}@_ZN5test51iITpTtTk1CTnTL0__EJNS_1YENS_1ZENS_1XEEEEvv(
173 template void i
<Y
, Z
, X
>();
174 // CHECK: define {{.*}}@_ZN5test51iIJNS_1ZENS_1XENS_1YEEEEvv(
175 template void i
<Z
, X
, Y
>();
177 template<typename
...T
> struct A
{};
178 template<typename
, typename
> struct B
{};
180 template<template<typename
...> typename
> void p() {}
181 // CHECK: define {{.*}}@_ZN5test51pINS_1AEEEvv(
182 // CLANG17: define {{.*}}@_ZN5test51pINS_1AEEEvv(
183 template void p
<A
>();
184 // CHECK: define {{.*}}@_ZN5test51pITtTpTyENS_1BEEEvv(
185 // CLANG17: define {{.*}}@_ZN5test51pINS_1BEEEvv(
186 template void p
<B
>();
188 template<template<typename
, typename
> typename
> void q() {}
189 // CHECK: define {{.*}}@_ZN5test51qITtTyTyENS_1AEEEvv(
190 // CLANG17: define {{.*}}@_ZN5test51qINS_1AEEEvv(
191 template void q
<A
>();
192 // CHECK: define {{.*}}@_ZN5test51qINS_1BEEEvv(
193 // CLANG17: define {{.*}}@_ZN5test51qINS_1BEEEvv(
194 template void q
<B
>();
198 // Abbreviated function templates.
200 // CHECK: define {{.*}}@_ZN5test61fITk1CiEEvT_(
201 // CLANG17: define {{.*}}@_ZN5test61fIiEEvT_(
202 template void f(int);
206 // CHECK: define {{.*}}@_ZN5test61gIiTk1DIT_EiEEvT0_(
207 // CLANG17: define {{.*}}@_ZN5test61gIiiEEvT0_(
208 template void g
<int>(int);
212 // Constrained lambdas.
213 template<typename T
> void f() {
214 // Ensure that requires-clauses affect lambda numbering.
215 // CHECK-LABEL: define {{.*}}@_ZN5test71fIiEEvv(
216 // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E_clIiiEEDaS3_Q1CIDtfp_EE(
217 ([]<typename U
> requires C
<T
> && C
<U
> (auto x
) requires C
<decltype(x
)> {}).template operator()<int>(0);
218 // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E0_clIiiEEDaS3_Qaa1CIDtfp_EELb1E(
219 ([]<typename U
> requires C
<T
> && C
<U
> (auto x
) requires C
<decltype(x
)> && true {}).template operator()<int>(0);
220 // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E1_clIiiEEDaS3_Q1CIDtfp_EE(
221 ([]<typename U
> requires C
<T
> && C
<U
> (auto x
) requires C
<decltype(x
)> {}).template operator()<int>(0);
222 // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyT0_E_clIiiEEDaS1_(
223 ([]<typename U
> (auto x
){}).template operator()<int>(0);
225 template void f
<int>();
229 template<typename T
, typename
...Ts
> constexpr bool B
= true;
230 template<typename T
, typename
...Ts
> concept C
= B
<T
, Ts
...>;
231 template<C
<int, float> T
> void f(T
) {}
232 // CHECK: define {{.*}} @_ZN7gh672441fITkNS_1CIifEEiEEvT_(
233 template void f(int);
237 template<typename
, typename T
> concept C
= true;
238 template<typename T
> void f(T t
, C
<decltype(t
)> auto) {}
239 // CHECK: define {{.*}} @_ZN7gh673561fIiTkNS_1CIDtfL0p_EEEiEEvT_T0_(
240 template void f(int, int);
242 // Note, we use `fL0p` not `fp` above because:
243 template<typename T
> void g(T t
, C
<auto (T u
) -> decltype(f(t
, u
))> auto) {}
244 // CHECK: define {{.*}} @_ZN7gh673561gIiTkNS_1CIFDTcl1ffL0p_fp_EET_EEEiEEvS3_T0_(
245 template void g(int, int);