1 // RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing 2 3 namespace class_implicit_ctor { 4 template <typename T> 5 class 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 10 class A : CRTP<A> {}; 11 } // namespace class_implicit_ctor 12 13 namespace class_unconstructible { 14 template <typename T> 15 class 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 21 class A : CRTP<A> {}; 22 } // namespace class_unconstructible 23 24 namespace class_public_default_ctor { 25 template <typename T> 26 class CRTP { 27 public: 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 34 class A : CRTP<A> {}; 35 } // namespace class_public_default_ctor 36 37 namespace class_public_user_provided_ctor { 38 template <typename T> 39 class CRTP { 40 public: 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 47 class A : CRTP<A> {}; 48 } // namespace class_public_user_provided_ctor 49 50 namespace class_public_multiple_user_provided_ctors { 51 template <typename T> 52 class CRTP { 53 public: 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 65 class A : CRTP<A> {}; 66 } // namespace class_public_multiple_user_provided_ctors 67 68 namespace class_protected_ctors { 69 template <typename T> 70 class CRTP { 71 protected: 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 87 class A : CRTP<A> {}; 88 } // namespace class_protected_ctors 89 90 namespace struct_implicit_ctor { 91 template <typename T> 92 struct 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 97 class A : CRTP<A> {}; 98 } // namespace struct_implicit_ctor 99 100 namespace struct_default_ctor { 101 template <typename T> 102 struct 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 109 class A : CRTP<A> {}; 110 } // namespace struct_default_ctor 111 112 namespace same_class_multiple_crtps { 113 template <typename T> 114 struct 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 119 template <typename T> 120 struct 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 125 class A : CRTP<A>, CRTP2<A> {}; 126 } // namespace same_class_multiple_crtps 127 128 namespace same_crtp_multiple_classes { 129 template <typename T> 130 class 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 136 class A : CRTP<A> {}; 137 class B : CRTP<B> {}; 138 } // namespace same_crtp_multiple_classes 139 140 namespace crtp_template { 141 template <typename T, typename U> 142 class 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 148 class A : CRTP<int, A> {}; 149 } // namespace crtp_template 150 151 namespace crtp_template2 { 152 template <typename T, typename U> 153 class 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 159 class A : CRTP<A, A> {}; 160 } // namespace crtp_template2 161 162 namespace template_derived { 163 template <typename T> 164 class 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 169 template<typename T> 170 class A : CRTP<A<T>> {}; 171 172 // FIXME: Ideally the warning should be triggered without instantiation. 173 void foo() { 174 A<int> A; 175 (void) A; 176 } 177 } // namespace template_derived 178 179 namespace template_derived_explicit_specialization { 180 template <typename T> 181 class 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 186 template<typename T> 187 class A : CRTP<A<T>> {}; 188 189 template<> 190 class A<int> : CRTP<A<int>> {}; 191 } // namespace template_derived_explicit_specialization 192 193 namespace explicit_derived_friend { 194 class A; 195 196 template <typename T> 197 class CRTP { 198 CRTP() = default; 199 friend A; 200 }; 201 202 class A : CRTP<A> {}; 203 } // namespace explicit_derived_friend 204 205 namespace explicit_derived_friend_multiple { 206 class A; 207 208 template <typename T> 209 class 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 216 class A : CRTP<A> {}; 217 class B : CRTP<B> {}; 218 } // namespace explicit_derived_friend_multiple 219 220 namespace no_need_for_friend { 221 class A; 222 223 template <typename T> 224 class 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 230 class A : CRTP<A> {}; 231 } // namespace no_need_for_friend 232 233 namespace no_warning { 234 template <typename T> 235 class CRTP 236 { 237 CRTP() = default; 238 friend T; 239 }; 240 241 class A : CRTP<A> {}; 242 } // namespace no_warning 243 244 namespace no_warning_unsupported { 245 template<typename... Types> 246 class CRTP 247 {}; 248 249 class A : CRTP<A> {}; 250 251 void foo() { 252 A A; 253 (void) A; 254 } 255 } // namespace no_warning_unsupported 256