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