xref: /llvm-project/clang/test/SemaTemplate/concepts-friends.cpp (revision 358165ded3c45115ce587d56ef792a9e7c0214ea)
1 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
2 
3 template <typename T>
4 concept constraint = false;
5 
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
14   {}
15 
16   friend void baz() // expected-error {{non-template friend declaration with a requires clause must be a definition}}
17     requires true;
18 };
19 
20 struct TempP9NotShownIfFunctionWouldBeInvalidAnyway {
21   friend void foo()
22     requires true; // expected-error {{non-templated function cannot have a requires clause}}
23 };
24 
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>;
34 
35   template <typename U>
36   friend void foo()
37     requires constraint<T>
38   {}
39 
40   T variable;
41   template <typename U>
42   friend void foo2()
43     requires constraint<decltype(variable)>
44   {}
45 
46   template <typename U>
47   friend void foo3(T parmvar)
48     requires constraint<decltype(parmvar)>
49   {}
50 
51   template <typename U>
52   friend void foo4()
53     requires requires(T &req) { (void)req; }
54   {}
55 
56   using Alias = T;
57   template <typename U>
58   friend void foo5()
59     requires constraint<Alias>
60   {}
61 
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>
67     {}
68     template <typename U>
69     friend void foo7()
70       requires constraint<decltype(variable)>
71     {}
72     template <typename U>
73     friend void foo8(T parmvar)
74       requires constraint<decltype(parmvar)>
75     {}
76     // This is NOT a duplicate since it itself is not a template.
77     friend void foo9()
78       requires true
79     {}
80   };
81   template <typename T2>
82   struct TemplChildOfEnclosing {
83     template <typename U>
84     friend void foo10()
85       requires constraint<T>
86     {}
87   };
88 };
89 
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>
97   {}
98 
99   struct ChildOfRedef {
100     template <typename U>
101     friend void foo2() // #REDEF2
102       requires constraint<U>
103     {}
104   };
105   template <typename T2>
106   struct ChildOfRedef2 {
107     template <typename U>
108     friend void foo3() // #REDEF3
109       requires constraint<U>
110     {}
111   };
112 };
113 
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}}
131 
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}}
137 }
138 } // namespace temp_friend_9
139 
140 namespace SameScopeRedefs {
141 template <typename T>
142 struct NonTemplateFriend {
143   friend void foo() // #NTF1
144     requires true
145   {}
146   friend void foo() // #NTF2
147     requires true
148   {}
149 };
150 
151 template <typename T>
152 struct TemplateFromEnclosing {
153   template <typename U>
154   friend void foo() // #TFE1
155     requires constraint<T>
156   {}
157   template <typename U>
158   friend void foo() // #TFE2
159     requires constraint<T>
160   {}
161 };
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>
168   {}
169   template <typename U>
170   friend void foo() // #RD2
171     requires constraint<U>
172   {}
173 };
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}}
179 
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}}
184 
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}}
189 }
190 } // namespace SameScopeRedefs
191 
192 namespace LibCXXOperatorRedef {
193 template <typename T, typename U> struct is_same {
194   static constexpr bool value = false;
195 };
196 template <typename T> struct is_same<T, T> {
197   static constexpr bool value = false;
198 };
199 
200 template <typename T, typename U>
201 concept same_as = is_same<T, U>::value;
202 
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>
214   {};
215   template <same_as<_Tp> _View, typename _Closure>
216   friend constexpr decltype(auto) R1func3(_View &&__view,
217                                           _Closure &&__closure){};
218 };
219 
220 struct A : __range_adaptor_closure<A> {};
221 struct B : __range_adaptor_closure<B> {};
222 
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>
234   {};
235   template <typename _View, same_as<_View> _Closure>
236   friend constexpr decltype(auto) R2func3(_View &&__view, // #FUNC3
237                                           _Closure &&__closure){};
238 };
239 
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}}
249 
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>
261   {};
262   template <same_as<typename _Tp::type> _View, typename _Closure>
263   friend constexpr decltype(auto) R3func3(_View &&__view,
264                                           _Closure &&__closure){};
265 };
266 
267 struct A3 : __range_adaptor_closure3<A3> {};
268 struct B3 : __range_adaptor_closure3<B3> {};
269 
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 &&) {}
279 
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>
284   {}
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>
289   {}
290 
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 &&) {}
297 };
298 
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() {}
305 };
306 
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
312 };
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}}
317 
318 template <class T> struct S1 {
319   template <typename U>
320   friend void dupe() {} // #S1DUPE
321 
322   template <typename U>
323     requires same_as<U, U>
324   friend void dupe2() {} // #S1DUPE2
325 };
326 template <class T> struct S2 {
327   template <typename U>
328   friend void dupe() {} // #S2DUPE
329 
330   template <typename U>
331     requires same_as<U, U>
332   friend void dupe2() {} // #S2DUPE2
333 };
334 
335 template <class T> struct S3 {
336   template <typename U>
337     requires same_as<T, U>
338   friend void dupe() {}
339 };
340 template <class T> struct S4 {
341   template <typename U>
342     requires same_as<T, U>
343   friend void dupe() {}
344 };
345 
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() {}
351 };
352 template <class T> struct S6 {
353   template <typename U>
354     requires same_as<T, U>
355   friend void not_dupe() {}
356 };
357 
358 template <class T> struct S7 {
359   void not_dupe()
360     requires same_as<T, T>
361   {}
362 };
363 
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}}
372 
373   // OK, they have different 'scopes'.
374   S3<int> s3;
375   S4<int> s4;
376 
377   // OK, because only instantiated with different T.
378   S5<int> s5;
379   S6<double> s6;
380 
381   S7<int> s7;
382 }
383 
384 } // namespace LibCXXOperatorRedef
385 
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;
392   }
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>>{}
401     };
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}}
408   }
409 } // namespace NamedDeclRefs
410 
411 namespace RefersToParentInConstraint {
412   // No diagnostic, these aren't duplicates.
413   template<typename T, typename U>
414   concept similar = true;
415 
416   template <typename X>
417   struct S{
418     friend void f(similar<S> auto && self){}
419     friend void f2(similar<S<X>> auto && self){}
420   };
421 
422   void use() {
423     S<int> x;
424     S<long> y;
425   }
426 } // namespace RefersToParentInConstraint
427 
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; }
436   };
437 
438   template<typename T>
439   struct U : Base {
440     template<T N>
441       friend int templ_func(Base&) requires(N>0)
442       { return 10; }
443   };
444 
445   void use() {
446     S<1> s1;
447     templ_func<float>(s1);
448     S<2> s2;
449     templ_func<float>(s2);
450 
451     U<int> u1;
452     templ_func<1>(u1);
453     U<short> u2;
454     templ_func<1>(u2);
455   }
456 }
457 
458 
459 namespace FriendOfFriend {
460 
461 template <typename>
462 concept Concept = true;
463 
464 template <Concept> class FriendOfBar;
465 
466 template <Concept> class Bar {
467   template <Concept> friend class FriendOfBar;
468 };
469 
470 Bar<void> BarInstance;
471 
472 namespace internal {
473 void FriendOfFoo(FriendOfBar<void>);
474 }
475 
476 template <Concept> class Foo {
477   friend void internal::FriendOfFoo(FriendOfBar<void>);
478 };
479 
480 } // namespace FriendOfFriend
481 
482 namespace GH86769 {
483 
484 template <typename T>
485 concept X = true;
486 
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;
492 };
493 
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;
500 };
501 
502 template struct Y<int>;
503 template struct Z<int>;
504 Y y(1);
505 
506 }
507 
508 namespace GH98258 {
509 
510 struct S {
511   template <typename U>
512   friend void f() requires requires { []<typename V>(V){}; } {
513     return;
514   }
515 
516   template <typename U>
517   friend void f2() requires requires { [](auto){}; } {
518     return;
519   }
520 
521   template <typename U>
522   friend void f3() requires requires { []<int X>(){ return X; }; } {
523     return;
524   }
525 };
526 
527 }
528 
529 namespace GH78101 {
530 
531 template <typename T, int i>
532 concept True = true;
533 
534 template <typename T, int I> struct Template {
535   static constexpr int i = I;
536 
537   friend constexpr auto operator+(True<i> auto f) { return i; }
538 };
539 
540 template <int I> struct Template<float, I> {
541   static constexpr int i = I;
542 
543   friend constexpr auto operator+(True<i> auto f) { return i; }
544 };
545 
546 Template<void, 4> f{};
547 
548 static_assert(+Template<float, 5>{} == 5);
549 
550 } // namespace GH78101
551