// RUN: %clang_cc1 -verify -frelaxed-template-template-args -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s -fclang-abi-compat=latest | FileCheck %s // RUN: %clang_cc1 -verify -frelaxed-template-template-args -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s -fclang-abi-compat=16 | FileCheck %s --check-prefix=CLANG16 // expected-no-diagnostics namespace test1 { template struct S {}; template concept C = true; template S> f0() { return S>{}; } template S> f0<>(); // CHECK: @_ZN5test12f0IiEENS_1SIX1CIT_EEEEv( // CLANG16: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv( } template struct S {}; template concept C = true; template concept D = true; template S> f0a() { return S>{}; } template S> f0a<>(); // CHECK: @_Z3f0aIiE1SIXsr5test1E1CIT_EEEv( // CLANG16: @_Z3f0aIiE1SIL_ZN5test11CIT_EEEEv( template S> f0() { return S>{}; } template S> f0<>(); // CHECK: @_Z2f0IiE1SIX1CIT_EEEv( // CLANG16: @_Z2f0IiE1SIL_Z1CIT_EEEv( template concept True = true; namespace test2 { // Member-like friends. template struct A { friend void f(...) requires True {} template friend void g(...) requires True && True {} template friend void h(...) requires True {} template requires True && True friend void i(...) {} template requires True friend void j(...) {} template requires True friend void k(...) {} template friend void l(...) {} }; A ai; // CHECK-LABEL: define {{.*}}@{{.*}}test2{{.*}}use void use() { // CHECK: call {{.*}}@_ZN5test21AIiEF1fEzQ4TrueIT_E( // CLANG16: call {{.*}}@_ZN5test21fEz( f(ai); // CHECK: call {{.*}}@_ZN5test2F1gIvEEvzQaa4TrueIT_E4TrueITL0__E( // CLANG16: call {{.*}}@_ZN5test21gIvEEvz( g(ai); // CHECK: call {{.*}}@_ZN5test21hIvEEvzQ4TrueITL0__E( // CLANG16: call {{.*}}@_ZN5test21hIvEEvz( h(ai); // CHECK: call {{.*}}@_ZN5test2F1iIvQaa4TrueIT_E4TrueITL0__EEEvz( // CLANG16: call {{.*}}@_ZN5test21iIvEEvz( i(ai); // CHECK: call {{.*}}@_ZN5test21jIvQ4TrueITL0__EEEvz( // CLANG16: call {{.*}}@_ZN5test21jIvEEvz( j(ai); // CHECK: call {{.*}}@_ZN5test2F1kITk4TruevQ4TrueIT_EEEvz( // CLANG16: call {{.*}}@_ZN5test21kIvEEvz( k(ai); // CHECK: call {{.*}}@_ZN5test21lITk4TruevEEvz( // CLANG16: call {{.*}}@_ZN5test21lIvEEvz( l(ai); } } namespace test3 { // Unconstrained auto. template void d() {} template void d<0>(); // CHECK: define {{.*}}@_ZN5test31dITnDaLi0EEEvv( // CLANG16: define {{.*}}@_ZN5test31dILi0EEEvv( template void e() {} template void e<0>(); // CHECK: define {{.*}}@_ZN5test31eITnDcLi0EEEvv( // CLANG16: define {{.*}}@_ZN5test31eILi0EEEvv( // Constrained auto. template void f() {} template void f<0>(); // CHECK: define {{.*}}@_ZN5test31fITnDk1CLi0EEEvv( // CLANG16: define {{.*}}@_ZN5test31fILi0EEEvv( template auto> void g() {} template void g<0>(); // CHECK: define {{.*}}@_ZN5test31gITnDk1DIiELi0EEEvv( // CLANG16: define {{.*}}@_ZN5test31gILi0EEEvv( template auto> void h() {} template void h(); // CHECK: define {{.*}}@_ZN5test31hIiTnDk1DIT_ELi0EEEvv( // CLANG16: define {{.*}}@_ZN5test31hIiLi0EEEvv( template void i(decltype(new C auto(T()))) {} template void i(int*); // CHECK: define {{.*}}@_ZN5test31iIiEEvDTnw_Dk1CpicvT__EEE( // CLANG16: define {{.*}}@_ZN5test31iIiEEvDTnw_DapicvT__EEE( template void j(decltype(new C decltype(auto)(T()))) {} template void j(int*); // CHECK: define {{.*}}@_ZN5test31jIiEEvDTnw_DK1CpicvT__EEE( // CLANG16: define {{.*}}@_ZN5test31jIiEEvDTnw_DcpicvT__EEE( } namespace test4 { // Constrained type parameters. template void f() {} template void f(); // CHECK: define {{.*}}@_ZN5test41fITk1CiEEvv( // CLANG16: define {{.*}}@_ZN5test41fIiEEvv( template> void g() {} template void g(); // CHECK: define {{.*}}@_ZN5test41gITk1DIiEiEEvv( // CLANG16: define {{.*}}@_ZN5test41gIiEEvv( } namespace test5 { // Exact-match vs non-exact-match template template parameters. template struct X {}; template requires C struct Y {}; template struct Z {}; template typename> void f() {} // CHECK: define {{.*}}@_ZN5test51fINS_1XEEEvv( template void f(); // CHECK: define {{.*}}@_ZN5test51fITtTyTnTL0__ENS_1YEEEvv( template void f(); // CHECK: define {{.*}}@_ZN5test51fITtTyTnTL0__ENS_1ZEEEvv( template void f(); template requires C typename> void g() {} // CHECK: define {{.*}}@_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1XEEEvv( template void g(); // CHECK: define {{.*}}@_ZN5test51gINS_1YEEEvv( template void g(); // CHECK: define {{.*}}@_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1ZEEEvv( template void g(); template typename> void h() {} // CHECK: define {{.*}}@_ZN5test51hITtTk1CTnTL0__ENS_1XEEEvv( template void h(); // CHECK: define {{.*}}@_ZN5test51hITtTk1CTnTL0__ENS_1YEEEvv( template void h(); // CHECK: define {{.*}}@_ZN5test51hINS_1ZEEEvv( template void h(); // Packs must match the first argument. template typename...> void i() {} // CHECK: define {{.*}}@_ZN5test51iITpTtTk1CTnTL0__EJNS_1XENS_1YENS_1ZEEEEvv( template void i(); // CHECK: define {{.*}}@_ZN5test51iITpTtTk1CTnTL0__EJNS_1YENS_1ZENS_1XEEEEvv( template void i(); // CHECK: define {{.*}}@_ZN5test51iIJNS_1ZENS_1XENS_1YEEEEvv( template void i(); template struct A {}; template struct B {}; template typename> void p() {} // CHECK: define {{.*}}@_ZN5test51pINS_1AEEEvv( // CLANG16: define {{.*}}@_ZN5test51pINS_1AEEEvv( template void p(); // CHECK: define {{.*}}@_ZN5test51pITtTpTyENS_1BEEEvv( // CLANG16: define {{.*}}@_ZN5test51pINS_1BEEEvv( template void p(); template typename> void q() {} // CHECK: define {{.*}}@_ZN5test51qITtTyTyENS_1AEEEvv( // CLANG16: define {{.*}}@_ZN5test51qINS_1AEEEvv( template void q(); // CHECK: define {{.*}}@_ZN5test51qINS_1BEEEvv( // CLANG16: define {{.*}}@_ZN5test51qINS_1BEEEvv( template void q(); } namespace test6 { // Abbreviated function templates. void f(C auto) {} // CHECK: define {{.*}}@_ZN5test61fITk1CiEEvT_( // CLANG16: define {{.*}}@_ZN5test61fIiEEvT_( template void f(int); template void g(D auto) {} // CHECK: define {{.*}}@_ZN5test61gIiTk1DIT_EiEEvT0_( // CLANG16: define {{.*}}@_ZN5test61gIiiEEvT0_( template void g(int); } namespace test7 { // Constrained lambdas. template void f() { // Ensure that requires-clauses affect lambda numbering. // CHECK-LABEL: define {{.*}}@_ZN5test71fIiEEvv( // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E_clIiiEEDaS3_Q1CIDtfp_EE( ([] requires C && C (auto x) requires C {}).template operator()(0); // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E0_clIiiEEDaS3_Qaa1CIDtfp_EELb1E( ([] requires C && C (auto x) requires C && true {}).template operator()(0); // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E1_clIiiEEDaS3_Q1CIDtfp_EE( ([] requires C && C (auto x) requires C {}).template operator()(0); // CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyT0_E_clIiiEEDaS1_( ([] (auto x){}).template operator()(0); } template void f(); } namespace gh67244 { template constexpr bool B = true; template concept C = B; template T> void f(T) {} // CHECK: define {{.*}} @_ZN7gh672441fITkNS_1CIifEEiEEvT_( template void f(int); } namespace gh67356 { template concept C = true; template void f(T t, C auto) {} // CHECK: define {{.*}} @_ZN7gh673561fIiTkNS_1CIDtfL0p_EEEiEEvT_T0_( template void f(int, int); // Note, we use `fL0p` not `fp` above because: template void g(T t, C decltype(f(t, u))> auto) {} // CHECK: define {{.*}} @_ZN7gh673561gIiTkNS_1CIFDTcl1ffL0p_fp_EET_EEEiEEvS3_T0_( template void g(int, int); }