1// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-crtp-constructor-accessibility %t -- -- -fno-delayed-template-parsing
2
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_ctor
12
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_unconstructible
23
24namespace class_public_default_ctor {
25template <typename T>
26class CRTP {
27public:
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
34class A : CRTP<A> {};
35} // namespace class_public_default_ctor
36
37namespace class_public_user_provided_ctor {
38template <typename T>
39class CRTP {
40public:
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
47class A : CRTP<A> {};
48} // namespace class_public_user_provided_ctor
49
50namespace class_public_multiple_user_provided_ctors {
51template <typename T>
52class CRTP {
53public:
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
65class A : CRTP<A> {};
66} // namespace class_public_multiple_user_provided_ctors
67
68namespace class_protected_ctors {
69template <typename T>
70class CRTP {
71protected:
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
87class A : CRTP<A> {};
88} // namespace class_protected_ctors
89
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_ctor
99
100namespace struct_default_ctor {
101template <typename T>
102struct 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
109class A : CRTP<A> {};
110} // namespace struct_default_ctor
111
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_crtps
127
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_classes
139
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_template
150
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_template2
161
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_derived
178
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_specialization
192
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_friend
204
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_multiple
219
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_friend
232
233namespace no_warning {
234template <typename T>
235class CRTP
236{
237 CRTP() = default;
238 friend T;
239};
240
241class A : CRTP<A> {};
242} // namespace no_warning
243
244namespace no_warning_unsupported {
245template<typename... Types>
246class CRTP
247{};
248
249class A : CRTP<A> {};
250
251void foo() {
252 A A;
253 (void) A;
254}
255} // namespace no_warning_unsupported
256

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/crtp-constructor-accessibility.cpp