569 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s2 3template <typename T>4concept constraint = false;5 6namespace temp_friend_9 {7// A non-template friend declaration with a requires-clause shall be a8// definition. ...Such a constrained friend function ... does not declare the9// same function or function template as a declaration in any other scope.10template <typename T>11struct NonTemplateFriend {12 friend void foo()13 requires true14 {}15 16 friend void baz() // expected-error {{non-template friend declaration with a requires clause must be a definition}}17 requires true;18};19 20struct 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 template26// parameter from an enclosing template shall be a definition. Such a ...27// function template declaration does not declare the same function or28// function template as a declaration in any other scope.29template <typename T>30struct 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 true79 {}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 to91// an enclosing scope.92template <typename T>93struct Redefinition {94 template <typename U>95 friend void foo() // #REDEF96 requires constraint<U>97 {}98 99 struct ChildOfRedef {100 template <typename U>101 friend void foo2() // #REDEF2102 requires constraint<U>103 {}104 };105 template <typename T2>106 struct ChildOfRedef2 {107 template <typename U>108 friend void foo3() // #REDEF3109 requires constraint<U>110 {}111 };112};113 114void 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_9139 140namespace SameScopeRedefs {141template <typename T>142struct NonTemplateFriend {143 friend void foo() // #NTF1144 requires true145 {}146 friend void foo() // #NTF2147 requires true148 {}149};150 151template <typename T>152struct TemplateFromEnclosing {153 template <typename U>154 friend void foo() // #TFE1155 requires constraint<T>156 {}157 template <typename U>158 friend void foo() // #TFE2159 requires constraint<T>160 {}161};162// Same as above, but doesn't require an instantiation pair to cause.163template <typename T>164struct Redefinition {165 template <typename U>166 friend void foo() // #RD1167 requires constraint<U>168 {}169 template <typename U>170 friend void foo() // #RD2171 requires constraint<U>172 {}173};174void 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 SameScopeRedefs191 192namespace LibCXXOperatorRedef {193template <typename T, typename U> struct is_same {194 static constexpr bool value = false;195};196template <typename T> struct is_same<T, T> {197 static constexpr bool value = false;198};199 200template <typename T, typename U>201concept 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'.205template <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 220struct A : __range_adaptor_closure<A> {};221struct B : __range_adaptor_closure<B> {};222 223// These three fail because after the 1st pass of instantiation, they are still224// identical.225template <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, // #FUNC1229 _Closure &&__closure){};230 template <typename _View, typename _Closure>231 friend constexpr decltype(auto) R2func2(_View &&__view, // #FUNC2232 _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, // #FUNC3237 _Closure &&__closure){};238};239 240struct A2 : __range_adaptor_closure2<A2> {};241struct 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, so251// are different despite ::type not being valid.252template <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 267struct A3 : __range_adaptor_closure3<A3> {};268struct B3 : __range_adaptor_closure3<B3> {};269 270template <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.300template <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 307template <class _Tp> struct __range_adaptor_closure6 {308 template <same_as<_Tp> U>309 friend void foo() {} // #RAC6FOO1310 template <same_as<_Tp> U>311 friend void foo() {} // #RAC6FOO2312};313struct 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 318template <class T> struct S1 {319 template <typename U>320 friend void dupe() {} // #S1DUPE321 322 template <typename U>323 requires same_as<U, U>324 friend void dupe2() {} // #S1DUPE2325};326template <class T> struct S2 {327 template <typename U>328 friend void dupe() {} // #S2DUPE329 330 template <typename U>331 requires same_as<U, U>332 friend void dupe2() {} // #S2DUPE2333};334 335template <class T> struct S3 {336 template <typename U>337 requires same_as<T, U>338 friend void dupe() {}339};340template <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.347template <class T> struct S5 {348 template <typename U>349 requires same_as<T, U>350 friend void not_dupe() {}351};352template <class T> struct S6 {353 template <typename U>354 requires same_as<T, U>355 friend void not_dupe() {}356};357 358template <class T> struct S7 {359 void not_dupe()360 requires same_as<T, T>361 {}362};363 364void 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 LibCXXOperatorRedef385 386namespace 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() // #NOREFOUTER400 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 NamedDeclRefs410 411namespace 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 RefersToParentInConstraint427 428namespace 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 459namespace FriendOfFriend {460 461template <typename>462concept Concept = true;463 464template <Concept> class FriendOfBar;465 466template <Concept> class Bar {467 template <Concept> friend class FriendOfBar;468};469 470Bar<void> BarInstance;471 472namespace internal {473void FriendOfFoo(FriendOfBar<void>);474}475 476template <Concept> class Foo {477 friend void internal::FriendOfFoo(FriendOfBar<void>);478};479 480} // namespace FriendOfFriend481 482namespace GH86769 {483 484template <typename T>485concept X = true;486 487template <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 494template <class T>495struct 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 class498 // template declaration.499 template <X U = void> friend struct Y;500};501 502template struct Y<int>;503template struct Z<int>;504Y y(1);505 506}507 508namespace GH98258 {509 510struct 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 529namespace GH78101 {530 531template <typename T, int i>532concept True = true;533 534template <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 540template <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 546Template<void, 4> f{};547 548static_assert(+Template<float, 5>{} == 5);549 550} // namespace GH78101551 552namespace GH156225 {553 554struct Test {555 template <class T>556 friend constexpr bool foo()557 requires([] {558 bool flags[1];559 for (bool x : flags)560 return false;561 return true;562 }())563 {564 return {};565 }566};567 568}569