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 contructor 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 contructor 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 contructor 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 contructor 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 contructor 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 contructor 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 contructor 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 contructor 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 | |