18e56fb82Sisuckatcs // RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing 28e56fb82Sisuckatcs 38e56fb82Sisuckatcs namespace class_implicit_ctor { 48e56fb82Sisuckatcs template <typename T> 58e56fb82Sisuckatcs class CRTP {}; 68e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 78e56fb82Sisuckatcs // CHECK-FIXES: CRTP() = default; 88e56fb82Sisuckatcs // CHECK-FIXES: friend T; 98e56fb82Sisuckatcs 108e56fb82Sisuckatcs class A : CRTP<A> {}; 118e56fb82Sisuckatcs } // namespace class_implicit_ctor 128e56fb82Sisuckatcs 138e56fb82Sisuckatcs namespace class_unconstructible { 148e56fb82Sisuckatcs template <typename T> 158e56fb82Sisuckatcs class CRTP { 168e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 178e56fb82Sisuckatcs // CHECK-FIXES: friend T; 188e56fb82Sisuckatcs CRTP() = default; 198e56fb82Sisuckatcs }; 208e56fb82Sisuckatcs 218e56fb82Sisuckatcs class A : CRTP<A> {}; 228e56fb82Sisuckatcs } // namespace class_unconstructible 238e56fb82Sisuckatcs 248e56fb82Sisuckatcs namespace class_public_default_ctor { 258e56fb82Sisuckatcs template <typename T> 268e56fb82Sisuckatcs class CRTP { 278e56fb82Sisuckatcs public: 288e56fb82Sisuckatcs CRTP() = default; 29*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 308e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: 318e56fb82Sisuckatcs // CHECK-FIXES: friend T; 328e56fb82Sisuckatcs }; 338e56fb82Sisuckatcs 348e56fb82Sisuckatcs class A : CRTP<A> {}; 358e56fb82Sisuckatcs } // namespace class_public_default_ctor 368e56fb82Sisuckatcs 378e56fb82Sisuckatcs namespace class_public_user_provided_ctor { 388e56fb82Sisuckatcs template <typename T> 398e56fb82Sisuckatcs class CRTP { 408e56fb82Sisuckatcs public: 418e56fb82Sisuckatcs CRTP(int) {} 42*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 438e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: 448e56fb82Sisuckatcs // CHECK-FIXES: friend T; 458e56fb82Sisuckatcs }; 468e56fb82Sisuckatcs 478e56fb82Sisuckatcs class A : CRTP<A> {}; 488e56fb82Sisuckatcs } // namespace class_public_user_provided_ctor 498e56fb82Sisuckatcs 508e56fb82Sisuckatcs namespace class_public_multiple_user_provided_ctors { 518e56fb82Sisuckatcs template <typename T> 528e56fb82Sisuckatcs class CRTP { 538e56fb82Sisuckatcs public: 548e56fb82Sisuckatcs CRTP(int) {} 55*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 568e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: 578e56fb82Sisuckatcs CRTP(float) {} 58*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 598e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public: 608e56fb82Sisuckatcs 618e56fb82Sisuckatcs // CHECK-FIXES: friend T; 628e56fb82Sisuckatcs // CHECK-FIXES: friend T; 638e56fb82Sisuckatcs }; 648e56fb82Sisuckatcs 658e56fb82Sisuckatcs class A : CRTP<A> {}; 668e56fb82Sisuckatcs } // namespace class_public_multiple_user_provided_ctors 678e56fb82Sisuckatcs 688e56fb82Sisuckatcs namespace class_protected_ctors { 698e56fb82Sisuckatcs template <typename T> 708e56fb82Sisuckatcs class CRTP { 718e56fb82Sisuckatcs protected: 728e56fb82Sisuckatcs CRTP(int) {} 73*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected constructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 748e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected: 758e56fb82Sisuckatcs CRTP() = default; 76*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected constructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 778e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected: 788e56fb82Sisuckatcs CRTP(float) {} 79*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: protected constructor allows the CRTP to be inherited from as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 808e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected: 818e56fb82Sisuckatcs 828e56fb82Sisuckatcs // CHECK-FIXES: friend T; 838e56fb82Sisuckatcs // CHECK-FIXES: friend T; 848e56fb82Sisuckatcs // CHECK-FIXES: friend T; 858e56fb82Sisuckatcs }; 868e56fb82Sisuckatcs 878e56fb82Sisuckatcs class A : CRTP<A> {}; 888e56fb82Sisuckatcs } // namespace class_protected_ctors 898e56fb82Sisuckatcs 908e56fb82Sisuckatcs namespace struct_implicit_ctor { 918e56fb82Sisuckatcs template <typename T> 928e56fb82Sisuckatcs struct CRTP {}; 938e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 948e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: 958e56fb82Sisuckatcs // CHECK-FIXES: friend T; 968e56fb82Sisuckatcs 978e56fb82Sisuckatcs class A : CRTP<A> {}; 988e56fb82Sisuckatcs } // namespace struct_implicit_ctor 998e56fb82Sisuckatcs 1008e56fb82Sisuckatcs namespace struct_default_ctor { 1018e56fb82Sisuckatcs template <typename T> 1028e56fb82Sisuckatcs struct CRTP { 1038e56fb82Sisuckatcs CRTP() = default; 104*57d109c4SKonstantin Bogdanov // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: public constructor allows the CRTP to be constructed as a regular template class; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1058e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: 1068e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1078e56fb82Sisuckatcs }; 1088e56fb82Sisuckatcs 1098e56fb82Sisuckatcs class A : CRTP<A> {}; 1108e56fb82Sisuckatcs } // namespace struct_default_ctor 1118e56fb82Sisuckatcs 1128e56fb82Sisuckatcs namespace same_class_multiple_crtps { 1138e56fb82Sisuckatcs template <typename T> 1148e56fb82Sisuckatcs struct CRTP {}; 1158e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1168e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: 1178e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1188e56fb82Sisuckatcs 1198e56fb82Sisuckatcs template <typename T> 1208e56fb82Sisuckatcs struct CRTP2 {}; 1218e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1228e56fb82Sisuckatcs // CHECK-FIXES: private:{{[[:space:]]*}}CRTP2() = default;{{[[:space:]]*}}public: 1238e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1248e56fb82Sisuckatcs 1258e56fb82Sisuckatcs class A : CRTP<A>, CRTP2<A> {}; 1268e56fb82Sisuckatcs } // namespace same_class_multiple_crtps 1278e56fb82Sisuckatcs 1288e56fb82Sisuckatcs namespace same_crtp_multiple_classes { 1298e56fb82Sisuckatcs template <typename T> 1308e56fb82Sisuckatcs class CRTP { 1318e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1328e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1338e56fb82Sisuckatcs CRTP() = default; 1348e56fb82Sisuckatcs }; 1358e56fb82Sisuckatcs 1368e56fb82Sisuckatcs class A : CRTP<A> {}; 1378e56fb82Sisuckatcs class B : CRTP<B> {}; 1388e56fb82Sisuckatcs } // namespace same_crtp_multiple_classes 1398e56fb82Sisuckatcs 1408e56fb82Sisuckatcs namespace crtp_template { 1418e56fb82Sisuckatcs template <typename T, typename U> 1428e56fb82Sisuckatcs class CRTP { 1438e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1448e56fb82Sisuckatcs // CHECK-FIXES: friend U; 1458e56fb82Sisuckatcs CRTP() = default; 1468e56fb82Sisuckatcs }; 1478e56fb82Sisuckatcs 1488e56fb82Sisuckatcs class A : CRTP<int, A> {}; 1498e56fb82Sisuckatcs } // namespace crtp_template 1508e56fb82Sisuckatcs 1518e56fb82Sisuckatcs namespace crtp_template2 { 1528e56fb82Sisuckatcs template <typename T, typename U> 1538e56fb82Sisuckatcs class CRTP { 1548e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1558e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1568e56fb82Sisuckatcs CRTP() = default; 1578e56fb82Sisuckatcs }; 1588e56fb82Sisuckatcs 1598e56fb82Sisuckatcs class A : CRTP<A, A> {}; 1608e56fb82Sisuckatcs } // namespace crtp_template2 1618e56fb82Sisuckatcs 1628e56fb82Sisuckatcs namespace template_derived { 1638e56fb82Sisuckatcs template <typename T> 1648e56fb82Sisuckatcs class CRTP {}; 1658e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1668e56fb82Sisuckatcs // CHECK-FIXES: CRTP() = default; 1678e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1688e56fb82Sisuckatcs 1698e56fb82Sisuckatcs template<typename T> 1708e56fb82Sisuckatcs class A : CRTP<A<T>> {}; 1718e56fb82Sisuckatcs 1728e56fb82Sisuckatcs // FIXME: Ideally the warning should be triggered without instantiation. 1738e56fb82Sisuckatcs void foo() { 1748e56fb82Sisuckatcs A<int> A; 1758e56fb82Sisuckatcs (void) A; 1768e56fb82Sisuckatcs } 1778e56fb82Sisuckatcs } // namespace template_derived 1788e56fb82Sisuckatcs 1798e56fb82Sisuckatcs namespace template_derived_explicit_specialization { 1808e56fb82Sisuckatcs template <typename T> 1818e56fb82Sisuckatcs class CRTP {}; 1828e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private and declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 1838e56fb82Sisuckatcs // CHECK-FIXES: CRTP() = default; 1848e56fb82Sisuckatcs // CHECK-FIXES: friend T; 1858e56fb82Sisuckatcs 1868e56fb82Sisuckatcs template<typename T> 1878e56fb82Sisuckatcs class A : CRTP<A<T>> {}; 1888e56fb82Sisuckatcs 1898e56fb82Sisuckatcs template<> 1908e56fb82Sisuckatcs class A<int> : CRTP<A<int>> {}; 1918e56fb82Sisuckatcs } // namespace template_derived_explicit_specialization 1928e56fb82Sisuckatcs 1938e56fb82Sisuckatcs namespace explicit_derived_friend { 1948e56fb82Sisuckatcs class A; 1958e56fb82Sisuckatcs 1968e56fb82Sisuckatcs template <typename T> 1978e56fb82Sisuckatcs class CRTP { 1988e56fb82Sisuckatcs CRTP() = default; 1998e56fb82Sisuckatcs friend A; 2008e56fb82Sisuckatcs }; 2018e56fb82Sisuckatcs 2028e56fb82Sisuckatcs class A : CRTP<A> {}; 2038e56fb82Sisuckatcs } // namespace explicit_derived_friend 2048e56fb82Sisuckatcs 2058e56fb82Sisuckatcs namespace explicit_derived_friend_multiple { 2068e56fb82Sisuckatcs class A; 2078e56fb82Sisuckatcs 2088e56fb82Sisuckatcs template <typename T> 2098e56fb82Sisuckatcs class CRTP { 2108e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the CRTP cannot be constructed from the derived class; consider declaring the derived class as friend [bugprone-crtp-constructor-accessibility] 2118e56fb82Sisuckatcs // CHECK-FIXES: friend T; 2128e56fb82Sisuckatcs CRTP() = default; 2138e56fb82Sisuckatcs friend A; 2148e56fb82Sisuckatcs }; 2158e56fb82Sisuckatcs 2168e56fb82Sisuckatcs class A : CRTP<A> {}; 2178e56fb82Sisuckatcs class B : CRTP<B> {}; 2188e56fb82Sisuckatcs } // namespace explicit_derived_friend_multiple 2198e56fb82Sisuckatcs 2208e56fb82Sisuckatcs namespace no_need_for_friend { 2218e56fb82Sisuckatcs class A; 2228e56fb82Sisuckatcs 2238e56fb82Sisuckatcs template <typename T> 2248e56fb82Sisuckatcs class CRTP { 2258e56fb82Sisuckatcs // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private [bugprone-crtp-constructor-accessibility] 2268e56fb82Sisuckatcs // CHECK-FIXES: CRTP() = default; 2278e56fb82Sisuckatcs friend A; 2288e56fb82Sisuckatcs }; 2298e56fb82Sisuckatcs 2308e56fb82Sisuckatcs class A : CRTP<A> {}; 2318e56fb82Sisuckatcs } // namespace no_need_for_friend 2328e56fb82Sisuckatcs 2338e56fb82Sisuckatcs namespace no_warning { 2348e56fb82Sisuckatcs template <typename T> 2358e56fb82Sisuckatcs class CRTP 2368e56fb82Sisuckatcs { 2378e56fb82Sisuckatcs CRTP() = default; 2388e56fb82Sisuckatcs friend T; 2398e56fb82Sisuckatcs }; 2408e56fb82Sisuckatcs 2418e56fb82Sisuckatcs class A : CRTP<A> {}; 2428e56fb82Sisuckatcs } // namespace no_warning 2438e56fb82Sisuckatcs 2448e56fb82Sisuckatcs namespace no_warning_unsupported { 2458e56fb82Sisuckatcs template<typename... Types> 2468e56fb82Sisuckatcs class CRTP 2478e56fb82Sisuckatcs {}; 2488e56fb82Sisuckatcs 2498e56fb82Sisuckatcs class A : CRTP<A> {}; 2508e56fb82Sisuckatcs 2518e56fb82Sisuckatcs void foo() { 2528e56fb82Sisuckatcs A A; 2538e56fb82Sisuckatcs (void) A; 2548e56fb82Sisuckatcs } 2558e56fb82Sisuckatcs } // namespace no_warning_unsupported 256