// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s template concept constraint = false; namespace temp_friend_9 { // A non-template friend declaration with a requires-clause shall be a // definition. ...Such a constrained friend function ... does not declare the // same function or function template as a declaration in any other scope. template struct NonTemplateFriend { friend void foo() requires true {} }; // A friend function template with a constraint that depends on a template // parameter from an enclosing template shall be a definition. Such a ... // function template declaration does not declare the same function or // function template as a declaration in any other scope. template struct TemplateFromEnclosing { template friend void foo() requires constraint {} T variable; template friend void foo2() requires constraint {} template friend void foo3(T parmvar) requires constraint {} template friend void foo4() requires requires(T &req) { (void)req; } {} using Alias = T; template friend void foo5() requires constraint {} // All of these refer to a parent, so these are not duplicate definitions. struct ChildOfEnclosing { template friend void foo6() requires constraint {} template friend void foo7() requires constraint {} template friend void foo8(T parmvar) requires constraint {} // This is NOT a duplicate since it itself is not a template. friend void foo9() requires true {} }; template struct TemplChildOfEnclosing { template friend void foo10() requires constraint {} }; }; // Doesn't meet either of the requirements in the above as they don't refer to // an enclosing scope. template struct Redefinition { template friend void foo() // #REDEF requires constraint {} struct ChildOfRedef { template friend void foo2() // #REDEF2 requires constraint {} }; template struct ChildOfRedef2 { template friend void foo3() // #REDEF3 requires constraint {} }; }; void bar() { NonTemplateFriend S1; NonTemplateFriend S2; TemplateFromEnclosing S3; TemplateFromEnclosing::ChildOfEnclosing S3b; TemplateFromEnclosing S4; TemplateFromEnclosing::ChildOfEnclosing S4b; Redefinition S5; Redefinition S6; // expected-error@#REDEF {{redefinition of 'foo'}} // expected-note@-2{{in instantiation of template class }} // expected-note@#REDEF {{previous definition is here}} Redefinition::ChildOfRedef S7; Redefinition::ChildOfRedef S8; // expected-error@#REDEF2 {{redefinition of 'foo2'}} // expected-note@-2{{in instantiation of member class }} // expected-note@#REDEF2 {{previous definition is here}} Redefinition::ChildOfRedef2 S9; Redefinition::ChildOfRedef2 S10; // expected-error@#REDEF3 {{redefinition of 'foo3'}} // expected-note@-2{{in instantiation of template class }} // expected-note@#REDEF3 {{previous definition is here}} } } // namespace temp_friend_9 namespace SameScopeRedefs { template struct NonTemplateFriend { friend void foo() // #NTF1 requires true {} friend void foo() // #NTF2 requires true {} }; template struct TemplateFromEnclosing { template friend void foo() // #TFE1 requires constraint {} template friend void foo() // #TFE2 requires constraint {} }; // Same as above, but doesn't require an instantiation pair to cause. template struct Redefinition { template friend void foo() // #RD1 requires constraint {} template friend void foo() // #RD2 requires constraint {} }; void bar() { NonTemplateFriend S1; // expected-error@#NTF2 {{redefinition of 'foo'}} // expected-note@-2{{in instantiation of template class}} // expected-note@#NTF1 {{previous definition is here}} TemplateFromEnclosing S2; // expected-error@#TFE2 {{redefinition of 'foo'}} // expected-note@-2{{in instantiation of template class}} // expected-note@#TFE1 {{previous definition is here}} Redefinition S3; // expected-error@#RD2 {{redefinition of 'foo'}} // expected-note@-2{{in instantiation of template class}} // expected-note@#RD1 {{previous definition is here}} } } // namespace SameScopeRedefs namespace LibCXXOperatorRedef { template struct is_same { static constexpr bool value = false; }; template struct is_same { static constexpr bool value = false; }; template concept same_as = is_same::value; // An issue found from libcxx when trying to commit the deferred concepts patch. // This caused an error of 'redefinition of funcN'. template struct __range_adaptor_closure { template requires same_as<_Tp, _Closure> friend constexpr decltype(auto) R1func1(_View &&__view, _Closure &&__closure){}; template friend constexpr decltype(auto) R1func2(_View &&__view, _Closure &&__closure) requires same_as<_Tp, _Closure> {}; template _View, typename _Closure> friend constexpr decltype(auto) R1func3(_View &&__view, _Closure &&__closure){}; }; struct A : __range_adaptor_closure {}; struct B : __range_adaptor_closure {}; // These three fail because after the 1st pass of instantiation, they are still // identical. template struct __range_adaptor_closure2 { template requires same_as<_View, _Closure> friend constexpr decltype(auto) R2func1(_View &&__view, // #FUNC1 _Closure &&__closure){}; template friend constexpr decltype(auto) R2func2(_View &&__view, // #FUNC2 _Closure &&__closure) requires same_as<_View, _Closure> {}; template _Closure> friend constexpr decltype(auto) R2func3(_View &&__view, // #FUNC3 _Closure &&__closure){}; }; struct A2 : __range_adaptor_closure2 {}; struct B2 : __range_adaptor_closure2 {}; // expected-error@#FUNC1{{redefinition of 'R2func1'}} // expected-note@-2{{in instantiation of template class}} // expected-note@#FUNC1{{previous definition is here}} // expected-error@#FUNC2{{redefinition of 'R2func2'}} // expected-note@#FUNC2{{previous definition is here}} // expected-error@#FUNC3{{redefinition of 'R2func3'}} // expected-note@#FUNC3{{previous definition is here}} // These three are fine, they all depend on the parent template parameter, so // are different despite ::type not being valid. template struct __range_adaptor_closure3 { template requires same_as friend constexpr decltype(auto) R3func1(_View &&__view, _Closure &&__closure){}; template friend constexpr decltype(auto) R3func2(_View &&__view, _Closure &&__closure) requires same_as {}; template _View, typename _Closure> friend constexpr decltype(auto) R3func3(_View &&__view, _Closure &&__closure){}; }; struct A3 : __range_adaptor_closure3 {}; struct B3 : __range_adaptor_closure3 {}; template struct __range_adaptor_closure4 { template requires same_as<_Tp, _View> // expected-note@+1{{previous definition is here}} void foo1(_View &&, _Closure &&) {} template requires same_as<_Tp, _View> // expected-error@+1{{class member cannot be redeclared}} void foo1(_View &&, _Closure &&) {} template // expected-note@+1{{previous definition is here}} void foo2(_View &&, _Closure &&) requires same_as<_Tp, _View> {} template // expected-error@+1{{class member cannot be redeclared}} void foo2(_View &&, _Closure &&) requires same_as<_Tp, _View> {} template _View, typename _Closure> // expected-note@+1{{previous definition is here}} void foo3(_View &&, _Closure &&) {} template _View, typename _Closure> // expected-error@+1{{class member cannot be redeclared}} void foo3(_View &&, _Closure &&) {} }; // Requires instantiation to fail, so no errors here. template struct __range_adaptor_closure5 { template U> friend void foo() {} template U> friend void foo() {} }; template struct __range_adaptor_closure6 { template U> friend void foo() {} // #RAC6FOO1 template U> friend void foo() {} // #RAC6FOO2 }; struct A6 : __range_adaptor_closure6 {}; // expected-error@#RAC6FOO2{{redefinition of 'foo'}} // expected-note@-2{{in instantiation of template class}} // expected-note@#RAC6FOO1{{previous definition is here}} template struct S1 { template friend void dupe() {} // #S1DUPE template requires same_as friend void dupe2() {} // #S1DUPE2 }; template struct S2 { template friend void dupe() {} // #S2DUPE template requires same_as friend void dupe2() {} // #S2DUPE2 }; template struct S3 { template requires same_as friend void dupe() {} }; template struct S4 { template requires same_as friend void dupe() {} }; // Same as S3 and S4, but aren't instantiated with the same T. template struct S5 { template requires same_as friend void not_dupe() {} }; template struct S6 { template requires same_as friend void not_dupe() {} }; template struct S7 { void not_dupe() requires same_as {} }; void useS() { S1 s1; S2 s2; // expected-error@#S2DUPE{{redefinition}} // expected-note@-2{{in instantiation of template class}} // expected-note@#S1DUPE{{previous definition is here}} // expected-error@#S2DUPE2{{redefinition}} // expected-note@#S1DUPE2{{previous definition is here}} // OK, they have different 'scopes'. S3 s3; S4 s4; // OK, because only instantiated with different T. S5 s5; S6 s6; S7 s7; } } // namespace LibCXXOperatorRedef namespace NamedDeclRefs { namespace my_std { template concept Outer = true; template using Inner = T; } template struct Proxy { template friend constexpr void RefOuter() requires my_std::Outer, my_std::Inner>{} template friend constexpr void NoRefOuter() // #NOREFOUTER requires my_std::Outer, my_std::Inner>{} }; void use() { Proxy p; Proxy p2; // expected-error@#NOREFOUTER {{redefinition of 'NoRefOuter'}} // expected-note@-2{{in instantiation of template class}} // expected-note@#NOREFOUTER{{previous definition is here}} } } // namespace NamedDeclRefs namespace RefersToParentInConstraint { // No diagnostic, these aren't duplicates. template concept similar = true; template struct S{ friend void f(similar auto && self){} friend void f2(similar> auto && self){} }; void use() { S x; S y; } } // namespace RefersToParentInConstraint namespace NTTP { struct Base{}; template struct S : Base { // N is from the parent template. template friend int templ_func(Base&) requires(N > 0) { return 10; } }; template struct U : Base { template friend int templ_func(Base&) requires(N>0) { return 10; } }; void use() { S<1> s1; templ_func(s1); S<2> s2; templ_func(s2); U u1; templ_func<1>(u1); U u2; templ_func<1>(u2); } } namespace FriendOfFriend { template concept Concept = true; template class FriendOfBar; template class Bar { template friend class FriendOfBar; }; Bar BarInstance; namespace internal { void FriendOfFoo(FriendOfBar); } template class Foo { friend void internal::FriendOfFoo(FriendOfBar); }; } // namespace FriendOfFriend