287 lines · cpp
1// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing2 3namespace class_implicit_ctor {4template <typename T>5class CRTP {};6// 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]7// CHECK-FIXES: CRTP() = default;8// CHECK-FIXES: friend T;9 10class A : CRTP<A> {};11} // namespace class_implicit_ctor12 13namespace class_unconstructible {14template <typename T>15class CRTP {16// 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]17// CHECK-FIXES: friend T;18 CRTP() = default;19};20 21class A : CRTP<A> {};22} // namespace class_unconstructible23 24namespace class_public_default_ctor {25template <typename T>26class CRTP {27public:28 CRTP() = default;29 // 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]30 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:31 // CHECK-FIXES: friend T;32};33 34class A : CRTP<A> {};35} // namespace class_public_default_ctor36 37namespace class_public_user_provided_ctor {38template <typename T>39class CRTP {40public:41 CRTP(int) {}42 // 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]43 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public:44 // CHECK-FIXES: friend T;45};46 47class A : CRTP<A> {};48} // namespace class_public_user_provided_ctor49 50namespace class_public_multiple_user_provided_ctors {51template <typename T>52class CRTP {53public:54 CRTP(int) {}55 // 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]56 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public:57 CRTP(float) {}58 // 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]59 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public:60 61 // CHECK-FIXES: friend T;62 // CHECK-FIXES: friend T;63};64 65class A : CRTP<A> {};66} // namespace class_public_multiple_user_provided_ctors67 68namespace class_protected_ctors {69template <typename T>70class CRTP {71protected:72 CRTP(int) {}73 // 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]74 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected:75 CRTP() = default;76 // 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]77 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected:78 CRTP(float) {}79 // 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]80 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected:81 82 // CHECK-FIXES: friend T;83 // CHECK-FIXES: friend T;84 // CHECK-FIXES: friend T;85};86 87class A : CRTP<A> {};88} // namespace class_protected_ctors89 90namespace struct_implicit_ctor {91template <typename T>92struct CRTP {};93// 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]94// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:95// CHECK-FIXES: friend T;96 97class A : CRTP<A> {};98} // namespace struct_implicit_ctor99 100namespace struct_default_ctor {101template <typename T>102struct CRTP {103 CRTP() = default;104 // 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]105 // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:106 // CHECK-FIXES: friend T;107};108 109class A : CRTP<A> {};110} // namespace struct_default_ctor111 112namespace same_class_multiple_crtps {113template <typename T>114struct CRTP {};115// 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]116// CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public:117// CHECK-FIXES: friend T;118 119template <typename T>120struct CRTP2 {};121// 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]122// CHECK-FIXES: private:{{[[:space:]]*}}CRTP2() = default;{{[[:space:]]*}}public:123// CHECK-FIXES: friend T;124 125class A : CRTP<A>, CRTP2<A> {};126} // namespace same_class_multiple_crtps127 128namespace same_crtp_multiple_classes {129template <typename T>130class CRTP {131// 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]132// CHECK-FIXES: friend T;133 CRTP() = default;134};135 136class A : CRTP<A> {};137class B : CRTP<B> {};138} // namespace same_crtp_multiple_classes139 140namespace crtp_template {141template <typename T, typename U>142class CRTP {143// 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]144// CHECK-FIXES: friend U;145 CRTP() = default;146};147 148class A : CRTP<int, A> {};149} // namespace crtp_template150 151namespace crtp_template2 {152template <typename T, typename U>153class CRTP {154// 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]155// CHECK-FIXES: friend T;156 CRTP() = default;157};158 159class A : CRTP<A, A> {};160} // namespace crtp_template2161 162namespace template_derived {163template <typename T>164class CRTP {};165// 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]166// CHECK-FIXES: CRTP() = default;167// CHECK-FIXES: friend T;168 169template<typename T>170class A : CRTP<A<T>> {};171 172// FIXME: Ideally the warning should be triggered without instantiation.173void foo() {174 A<int> A;175 (void) A;176}177} // namespace template_derived178 179namespace template_derived_explicit_specialization {180template <typename T>181class CRTP {};182// 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]183// CHECK-FIXES: CRTP() = default;184// CHECK-FIXES: friend T;185 186template<typename T>187class A : CRTP<A<T>> {};188 189template<>190class A<int> : CRTP<A<int>> {};191} // namespace template_derived_explicit_specialization192 193namespace explicit_derived_friend {194class A;195 196template <typename T>197class CRTP {198 CRTP() = default;199 friend A;200};201 202class A : CRTP<A> {};203} // namespace explicit_derived_friend204 205namespace explicit_derived_friend_multiple {206class A;207 208template <typename T>209class CRTP {210// 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]211// CHECK-FIXES: friend T;212 CRTP() = default;213 friend A;214};215 216class A : CRTP<A> {};217class B : CRTP<B> {};218} // namespace explicit_derived_friend_multiple219 220namespace no_need_for_friend {221class A;222 223template <typename T>224class CRTP {225// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private [bugprone-crtp-constructor-accessibility]226// CHECK-FIXES: CRTP() = default;227 friend A;228};229 230class A : CRTP<A> {};231} // namespace no_need_for_friend232 233namespace no_warning {234template <typename T>235class CRTP236{237 CRTP() = default;238 friend T;239};240 241class A : CRTP<A> {};242} // namespace no_warning243 244namespace no_warning_unsupported {245template<typename... Types>246class CRTP247{};248 249class A : CRTP<A> {};250 251void foo() {252 A A;253 (void) A;254}255} // namespace no_warning_unsupported256 257namespace public_copy_move_constructors_deleted {258template <typename T>259class CRTP260{261 CRTP() = default;262 friend T;263 public:264 CRTP(const CRTP&) = delete;265 CRTP(CRTP&&) = delete;266};267 268class A : CRTP<A> {};269 270} // namespace public_copy_move_constructors_deleted271 272namespace public_copy_protected_move_constructor_deleted {273template <typename T>274class CRTP275{276 CRTP() = default;277 friend T;278 public:279 CRTP(const CRTP&) = delete;280 protected:281 CRTP(CRTP&&) = delete;282};283 284class A : CRTP<A> {};285 286} // namespace public_copy_protected_move_constructor_deleted287