// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing namespace class_implicit_ctor { template class CRTP {}; // 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] // CHECK-FIXES: CRTP() = default; // CHECK-FIXES: friend T; class A : CRTP {}; } // namespace class_implicit_ctor namespace class_unconstructible { template class CRTP { // 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] // CHECK-FIXES: friend T; CRTP() = default; }; class A : CRTP {}; } // namespace class_unconstructible namespace class_public_default_ctor { template class CRTP { public: CRTP() = default; // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: // CHECK-FIXES: friend T; }; class A : CRTP {}; } // namespace class_public_default_ctor namespace class_public_user_provided_ctor { template class CRTP { public: CRTP(int) {} // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: // CHECK-FIXES: friend T; }; class A : CRTP {}; } // namespace class_public_user_provided_ctor namespace class_public_multiple_user_provided_ctors { template class CRTP { public: CRTP(int) {} // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}public: CRTP(float) {} // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}public: // CHECK-FIXES: friend T; // CHECK-FIXES: friend T; }; class A : CRTP {}; } // namespace class_public_multiple_user_provided_ctors namespace class_protected_ctors { template class CRTP { protected: CRTP(int) {} // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(int) {}{{[[:space:]]*}}protected: CRTP() = default; // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}protected: CRTP(float) {} // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP(float) {}{{[[:space:]]*}}protected: // CHECK-FIXES: friend T; // CHECK-FIXES: friend T; // CHECK-FIXES: friend T; }; class A : CRTP {}; } // namespace class_protected_ctors namespace struct_implicit_ctor { template struct CRTP {}; // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: // CHECK-FIXES: friend T; class A : CRTP {}; } // namespace struct_implicit_ctor namespace struct_default_ctor { template struct CRTP { CRTP() = default; // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: // CHECK-FIXES: friend T; }; class A : CRTP {}; } // namespace struct_default_ctor namespace same_class_multiple_crtps { template struct CRTP {}; // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP() = default;{{[[:space:]]*}}public: // CHECK-FIXES: friend T; template struct CRTP2 {}; // 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] // CHECK-FIXES: private:{{[[:space:]]*}}CRTP2() = default;{{[[:space:]]*}}public: // CHECK-FIXES: friend T; class A : CRTP, CRTP2 {}; } // namespace same_class_multiple_crtps namespace same_crtp_multiple_classes { template class CRTP { // 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] // CHECK-FIXES: friend T; CRTP() = default; }; class A : CRTP {}; class B : CRTP {}; } // namespace same_crtp_multiple_classes namespace crtp_template { template class CRTP { // 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] // CHECK-FIXES: friend U; CRTP() = default; }; class A : CRTP {}; } // namespace crtp_template namespace crtp_template2 { template class CRTP { // 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] // CHECK-FIXES: friend T; CRTP() = default; }; class A : CRTP {}; } // namespace crtp_template2 namespace template_derived { template class CRTP {}; // 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] // CHECK-FIXES: CRTP() = default; // CHECK-FIXES: friend T; template class A : CRTP> {}; // FIXME: Ideally the warning should be triggered without instantiation. void foo() { A A; (void) A; } } // namespace template_derived namespace template_derived_explicit_specialization { template class CRTP {}; // 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] // CHECK-FIXES: CRTP() = default; // CHECK-FIXES: friend T; template class A : CRTP> {}; template<> class A : CRTP> {}; } // namespace template_derived_explicit_specialization namespace explicit_derived_friend { class A; template class CRTP { CRTP() = default; friend A; }; class A : CRTP {}; } // namespace explicit_derived_friend namespace explicit_derived_friend_multiple { class A; template class CRTP { // 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] // CHECK-FIXES: friend T; CRTP() = default; friend A; }; class A : CRTP {}; class B : CRTP {}; } // namespace explicit_derived_friend_multiple namespace no_need_for_friend { class A; template class CRTP { // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: the implicit default constructor of the CRTP is publicly accessible; consider making it private [bugprone-crtp-constructor-accessibility] // CHECK-FIXES: CRTP() = default; friend A; }; class A : CRTP {}; } // namespace no_need_for_friend namespace no_warning { template class CRTP { CRTP() = default; friend T; }; class A : CRTP {}; } // namespace no_warning namespace no_warning_unsupported { template class CRTP {}; class A : CRTP {}; void foo() { A A; (void) A; } } // namespace no_warning_unsupported