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