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