[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaTemplate / concepts-friends.cpp
blobd05be423a8cfcdea996fb72e7326d4198e946682
1 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
3 template <typename T>
4 concept constraint = false;
6 namespace temp_friend_9 {
7 // A non-template friend declaration with a requires-clause shall be a
8 // definition. ...Such a constrained friend function ... does not declare the
9 // same function or function template as a declaration in any other scope.
10 template <typename T>
11 struct NonTemplateFriend {
12 friend void foo()
13 requires true
16 friend void baz() // expected-error {{non-template friend declaration with a requires clause must be a definition}}
17 requires true;
20 struct TempP9NotShownIfFunctionWouldBeInvalidAnyway {
21 friend void foo()
22 requires true; // expected-error {{non-templated function cannot have a requires clause}}
25 // A friend function template with a constraint that depends on a template
26 // parameter from an enclosing template shall be a definition. Such a ...
27 // function template declaration does not declare the same function or
28 // function template as a declaration in any other scope.
29 template <typename T>
30 struct TemplateFromEnclosing {
31 template <typename U>
32 friend void bar2() // expected-error {{friend declaration with a constraint that depends on an enclosing template parameter must be a definition}}
33 requires constraint<T>;
35 template <typename U>
36 friend void foo()
37 requires constraint<T>
40 T variable;
41 template <typename U>
42 friend void foo2()
43 requires constraint<decltype(variable)>
46 template <typename U>
47 friend void foo3(T parmvar)
48 requires constraint<decltype(parmvar)>
51 template <typename U>
52 friend void foo4()
53 requires requires(T &req) { (void)req; }
56 using Alias = T;
57 template <typename U>
58 friend void foo5()
59 requires constraint<Alias>
62 // All of these refer to a parent, so these are not duplicate definitions.
63 struct ChildOfEnclosing {
64 template <typename U>
65 friend void foo6()
66 requires constraint<T>
68 template <typename U>
69 friend void foo7()
70 requires constraint<decltype(variable)>
72 template <typename U>
73 friend void foo8(T parmvar)
74 requires constraint<decltype(parmvar)>
76 // This is NOT a duplicate since it itself is not a template.
77 friend void foo9()
78 requires true
81 template <typename T2>
82 struct TemplChildOfEnclosing {
83 template <typename U>
84 friend void foo10()
85 requires constraint<T>
90 // Doesn't meet either of the requirements in the above as they don't refer to
91 // an enclosing scope.
92 template <typename T>
93 struct Redefinition {
94 template <typename U>
95 friend void foo() // #REDEF
96 requires constraint<U>
99 struct ChildOfRedef {
100 template <typename U>
101 friend void foo2() // #REDEF2
102 requires constraint<U>
105 template <typename T2>
106 struct ChildOfRedef2 {
107 template <typename U>
108 friend void foo3() // #REDEF3
109 requires constraint<U>
114 void bar() {
115 NonTemplateFriend<int> S1;
116 NonTemplateFriend<float> S2;
117 TemplateFromEnclosing<int> S3;
118 TemplateFromEnclosing<int>::ChildOfEnclosing S3b;
119 TemplateFromEnclosing<float> S4;
120 TemplateFromEnclosing<float>::ChildOfEnclosing S4b;
121 Redefinition<int> S5;
122 Redefinition<float> S6;
123 // expected-error@#REDEF {{redefinition of 'foo'}}
124 // expected-note@-2{{in instantiation of template class }}
125 // expected-note@#REDEF {{previous definition is here}}
126 Redefinition<int>::ChildOfRedef S7;
127 Redefinition<float>::ChildOfRedef S8;
128 // expected-error@#REDEF2 {{redefinition of 'foo2'}}
129 // expected-note@-2{{in instantiation of member class }}
130 // expected-note@#REDEF2 {{previous definition is here}}
132 Redefinition<int>::ChildOfRedef2<int> S9;
133 Redefinition<float>::ChildOfRedef2<float> S10;
134 // expected-error@#REDEF3 {{redefinition of 'foo3'}}
135 // expected-note@-2{{in instantiation of template class }}
136 // expected-note@#REDEF3 {{previous definition is here}}
138 } // namespace temp_friend_9
140 namespace SameScopeRedefs {
141 template <typename T>
142 struct NonTemplateFriend {
143 friend void foo() // #NTF1
144 requires true
146 friend void foo() // #NTF2
147 requires true
151 template <typename T>
152 struct TemplateFromEnclosing {
153 template <typename U>
154 friend void foo() // #TFE1
155 requires constraint<T>
157 template <typename U>
158 friend void foo() // #TFE2
159 requires constraint<T>
162 // Same as above, but doesn't require an instantiation pair to cause.
163 template <typename T>
164 struct Redefinition {
165 template <typename U>
166 friend void foo() // #RD1
167 requires constraint<U>
169 template <typename U>
170 friend void foo() // #RD2
171 requires constraint<U>
174 void bar() {
175 NonTemplateFriend<int> S1;
176 // expected-error@#NTF2 {{redefinition of 'foo'}}
177 // expected-note@-2{{in instantiation of template class}}
178 // expected-note@#NTF1 {{previous definition is here}}
180 TemplateFromEnclosing<int> S2;
181 // expected-error@#TFE2 {{redefinition of 'foo'}}
182 // expected-note@-2{{in instantiation of template class}}
183 // expected-note@#TFE1 {{previous definition is here}}
185 Redefinition<int> S3;
186 // expected-error@#RD2 {{redefinition of 'foo'}}
187 // expected-note@-2{{in instantiation of template class}}
188 // expected-note@#RD1 {{previous definition is here}}
190 } // namespace SameScopeRedefs
192 namespace LibCXXOperatorRedef {
193 template <typename T, typename U> struct is_same {
194 static constexpr bool value = false;
196 template <typename T> struct is_same<T, T> {
197 static constexpr bool value = false;
200 template <typename T, typename U>
201 concept same_as = is_same<T, U>::value;
203 // An issue found from libcxx when trying to commit the deferred concepts patch.
204 // This caused an error of 'redefinition of funcN'.
205 template <class _Tp> struct __range_adaptor_closure {
206 template <typename _View, typename _Closure>
207 requires same_as<_Tp, _Closure>
208 friend constexpr decltype(auto) R1func1(_View &&__view,
209 _Closure &&__closure){};
210 template <typename _View, typename _Closure>
211 friend constexpr decltype(auto) R1func2(_View &&__view,
212 _Closure &&__closure)
213 requires same_as<_Tp, _Closure>
215 template <same_as<_Tp> _View, typename _Closure>
216 friend constexpr decltype(auto) R1func3(_View &&__view,
217 _Closure &&__closure){};
220 struct A : __range_adaptor_closure<A> {};
221 struct B : __range_adaptor_closure<B> {};
223 // These three fail because after the 1st pass of instantiation, they are still
224 // identical.
225 template <class _Tp> struct __range_adaptor_closure2 {
226 template <typename _View, typename _Closure>
227 requires same_as<_View, _Closure>
228 friend constexpr decltype(auto) R2func1(_View &&__view, // #FUNC1
229 _Closure &&__closure){};
230 template <typename _View, typename _Closure>
231 friend constexpr decltype(auto) R2func2(_View &&__view, // #FUNC2
232 _Closure &&__closure)
233 requires same_as<_View, _Closure>
235 template <typename _View, same_as<_View> _Closure>
236 friend constexpr decltype(auto) R2func3(_View &&__view, // #FUNC3
237 _Closure &&__closure){};
240 struct A2 : __range_adaptor_closure2<A2> {};
241 struct B2 : __range_adaptor_closure2<B2> {};
242 // expected-error@#FUNC1{{redefinition of 'R2func1'}}
243 // expected-note@-2{{in instantiation of template class}}
244 // expected-note@#FUNC1{{previous definition is here}}
245 // expected-error@#FUNC2{{redefinition of 'R2func2'}}
246 // expected-note@#FUNC2{{previous definition is here}}
247 // expected-error@#FUNC3{{redefinition of 'R2func3'}}
248 // expected-note@#FUNC3{{previous definition is here}}
250 // These three are fine, they all depend on the parent template parameter, so
251 // are different despite ::type not being valid.
252 template <class _Tp> struct __range_adaptor_closure3 {
253 template <typename _View, typename _Closure>
254 requires same_as<typename _Tp::type, _Closure>
255 friend constexpr decltype(auto) R3func1(_View &&__view,
256 _Closure &&__closure){};
257 template <typename _View, typename _Closure>
258 friend constexpr decltype(auto) R3func2(_View &&__view,
259 _Closure &&__closure)
260 requires same_as<typename _Tp::type, _Closure>
262 template <same_as<typename _Tp::type> _View, typename _Closure>
263 friend constexpr decltype(auto) R3func3(_View &&__view,
264 _Closure &&__closure){};
267 struct A3 : __range_adaptor_closure3<A3> {};
268 struct B3 : __range_adaptor_closure3<B3> {};
270 template <class _Tp> struct __range_adaptor_closure4 {
271 template <typename _View, typename _Closure>
272 requires same_as<_Tp, _View>
273 // expected-note@+1{{previous definition is here}}
274 void foo1(_View &&, _Closure &&) {}
275 template <typename _View, typename _Closure>
276 requires same_as<_Tp, _View>
277 // expected-error@+1{{class member cannot be redeclared}}
278 void foo1(_View &&, _Closure &&) {}
280 template <typename _View, typename _Closure>
281 // expected-note@+1{{previous definition is here}}
282 void foo2(_View &&, _Closure &&)
283 requires same_as<_Tp, _View>
285 template <typename _View, typename _Closure>
286 // expected-error@+1{{class member cannot be redeclared}}
287 void foo2(_View &&, _Closure &&)
288 requires same_as<_Tp, _View>
291 template <same_as<_Tp> _View, typename _Closure>
292 // expected-note@+1{{previous definition is here}}
293 void foo3(_View &&, _Closure &&) {}
294 template <same_as<_Tp> _View, typename _Closure>
295 // expected-error@+1{{class member cannot be redeclared}}
296 void foo3(_View &&, _Closure &&) {}
299 // Requires instantiation to fail, so no errors here.
300 template <class _Tp> struct __range_adaptor_closure5 {
301 template <same_as<_Tp> U>
302 friend void foo() {}
303 template <same_as<_Tp> U>
304 friend void foo() {}
307 template <class _Tp> struct __range_adaptor_closure6 {
308 template <same_as<_Tp> U>
309 friend void foo() {} // #RAC6FOO1
310 template <same_as<_Tp> U>
311 friend void foo() {} // #RAC6FOO2
313 struct A6 : __range_adaptor_closure6<A6> {};
314 // expected-error@#RAC6FOO2{{redefinition of 'foo'}}
315 // expected-note@-2{{in instantiation of template class}}
316 // expected-note@#RAC6FOO1{{previous definition is here}}
318 template <class T> struct S1 {
319 template <typename U>
320 friend void dupe() {} // #S1DUPE
322 template <typename U>
323 requires same_as<U, U>
324 friend void dupe2() {} // #S1DUPE2
326 template <class T> struct S2 {
327 template <typename U>
328 friend void dupe() {} // #S2DUPE
330 template <typename U>
331 requires same_as<U, U>
332 friend void dupe2() {} // #S2DUPE2
335 template <class T> struct S3 {
336 template <typename U>
337 requires same_as<T, U>
338 friend void dupe() {}
340 template <class T> struct S4 {
341 template <typename U>
342 requires same_as<T, U>
343 friend void dupe() {}
346 // Same as S3 and S4, but aren't instantiated with the same T.
347 template <class T> struct S5 {
348 template <typename U>
349 requires same_as<T, U>
350 friend void not_dupe() {}
352 template <class T> struct S6 {
353 template <typename U>
354 requires same_as<T, U>
355 friend void not_dupe() {}
358 template <class T> struct S7 {
359 void not_dupe()
360 requires same_as<T, T>
364 void useS() {
365 S1<int> s1;
366 S2<double> s2;
367 // expected-error@#S2DUPE{{redefinition}}
368 // expected-note@-2{{in instantiation of template class}}
369 // expected-note@#S1DUPE{{previous definition is here}}
370 // expected-error@#S2DUPE2{{redefinition}}
371 // expected-note@#S1DUPE2{{previous definition is here}}
373 // OK, they have different 'scopes'.
374 S3<int> s3;
375 S4<int> s4;
377 // OK, because only instantiated with different T.
378 S5<int> s5;
379 S6<double> s6;
381 S7<int> s7;
384 } // namespace LibCXXOperatorRedef
386 namespace NamedDeclRefs {
387 namespace my_std {
388 template<typename T, typename U>
389 concept Outer = true;
390 template<typename T>
391 using Inner = T;
393 template<typename T>
394 struct Proxy {
395 template<class U>
396 friend constexpr void RefOuter()
397 requires my_std::Outer<my_std::Inner<T>, my_std::Inner<U>>{}
398 template<class U>
399 friend constexpr void NoRefOuter() // #NOREFOUTER
400 requires my_std::Outer<my_std::Inner<U>, my_std::Inner<U>>{}
402 void use() {
403 Proxy<int> p;
404 Proxy<float> p2;
405 // expected-error@#NOREFOUTER {{redefinition of 'NoRefOuter'}}
406 // expected-note@-2{{in instantiation of template class}}
407 // expected-note@#NOREFOUTER{{previous definition is here}}
409 } // namespace NamedDeclRefs
411 namespace RefersToParentInConstraint {
412 // No diagnostic, these aren't duplicates.
413 template<typename T, typename U>
414 concept similar = true;
416 template <typename X>
417 struct S{
418 friend void f(similar<S> auto && self){}
419 friend void f2(similar<S<X>> auto && self){}
422 void use() {
423 S<int> x;
424 S<long> y;
426 } // namespace RefersToParentInConstraint
428 namespace NTTP {
429 struct Base{};
430 template<int N>
431 struct S : Base {
432 // N is from the parent template.
433 template<typename T>
434 friend int templ_func(Base&) requires(N > 0)
435 { return 10; }
438 template<typename T>
439 struct U : Base {
440 template<T N>
441 friend int templ_func(Base&) requires(N>0)
442 { return 10; }
445 void use() {
446 S<1> s1;
447 templ_func<float>(s1);
448 S<2> s2;
449 templ_func<float>(s2);
451 U<int> u1;
452 templ_func<1>(u1);
453 U<short> u2;
454 templ_func<1>(u2);
459 namespace FriendOfFriend {
461 template <typename>
462 concept Concept = true;
464 template <Concept> class FriendOfBar;
466 template <Concept> class Bar {
467 template <Concept> friend class FriendOfBar;
470 Bar<void> BarInstance;
472 namespace internal {
473 void FriendOfFoo(FriendOfBar<void>);
476 template <Concept> class Foo {
477 friend void internal::FriendOfFoo(FriendOfBar<void>);
480 } // namespace FriendOfFriend
482 namespace GH86769 {
484 template <typename T>
485 concept X = true;
487 template <X T> struct Y {
488 Y(T) {}
489 template <X U> friend struct Y;
490 template <X U> friend struct Y;
491 template <X U> friend struct Y;
494 template <class T>
495 struct Z {
496 // FIXME: This is ill-formed per C++11 N3337 [temp.param]p12:
497 // A default template argument shall not be specified in a friend class
498 // template declaration.
499 template <X U = void> friend struct Y;
502 template struct Y<int>;
503 template struct Z<int>;
504 Y y(1);
508 namespace GH98258 {
510 struct S {
511 template <typename U>
512 friend void f() requires requires { []<typename V>(V){}; } {
513 return;
516 template <typename U>
517 friend void f2() requires requires { [](auto){}; } {
518 return;
521 template <typename U>
522 friend void f3() requires requires { []<int X>(){ return X; }; } {
523 return;
529 namespace GH78101 {
531 template <typename T, int i>
532 concept True = true;
534 template <typename T, int I> struct Template {
535 static constexpr int i = I;
537 friend constexpr auto operator+(True<i> auto f) { return i; }
540 template <int I> struct Template<float, I> {
541 static constexpr int i = I;
543 friend constexpr auto operator+(True<i> auto f) { return i; }
546 Template<void, 4> f{};
548 static_assert(+Template<float, 5>{} == 5);
550 } // namespace GH78101