1// RUN: clang-tidy %s -checks="-*,cert-err58-cpp" -- -std=c++17 -target x86_64-pc-linux-gnu \
2// RUN: | FileCheck %s -check-prefix=CHECK-EXCEPTIONS \
3// RUN: -implicit-check-not="{{warning|error}}:"
4// RUN: clang-tidy %s -checks="-*,cert-err58-cpp" -- -DNONEXCEPTIONS -fno-exceptions -std=c++17 -target x86_64-pc-linux-gnu \
5// RUN: | FileCheck %s -allow-empty -check-prefix=CHECK-NONEXCEPTIONS \
6// RUN: -implicit-check-not="{{warning|error}}:"
7
8struct S {
9 S() noexcept(false);
10};
11
12struct T {
13 T() noexcept;
14};
15
16struct U {
17 U() {}
18};
19
20struct V {
21 explicit V(const char *) {} // Can throw
22};
23
24struct Cleanup {
25 ~Cleanup() {}
26};
27
28struct W {
29 W(Cleanup c = {}) noexcept(false);
30};
31
32struct X {
33 X(S = {}) noexcept;
34};
35
36struct Y {
37 S s;
38};
39
40struct Z {
41 T t;
42};
43
44int f();
45int g() noexcept(false);
46int h() noexcept(true);
47
48struct UserConv_Bad {
49 operator int() noexcept(false);
50};
51
52struct UserConv_Good {
53 operator int() noexcept;
54};
55
56UserConv_Bad some_bad_func() noexcept;
57UserConv_Good some_good_func() noexcept;
58
59S s;
60// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
61// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
62// CHECK-NONEXCEPTIONS-NOT: warning:
63T t; // ok
64U u;
65// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
66// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
67// CHECK-NONEXCEPTIONS-NOT: warning:
68V v("v");
69// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
70// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
71// CHECK-NONEXCEPTIONS-NOT: warning:
72W w;
73// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
74// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
75// CHECK-NONEXCEPTIONS-NOT: warning:
76X x1(S{});
77// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'x1' with static storage duration may throw an exception that cannot be caught
78// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
79// CHECK-NONEXCEPTIONS-NOT: warning:
80X x2;
81// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'x2' with static storage duration may throw an exception that cannot be caught
82// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
83// CHECK-NONEXCEPTIONS-NOT: warning:
84Y y;
85// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'y' with static storage duration may throw an exception that cannot be caught
86// CHECK-EXCEPTIONS: 36:8: note: possibly throwing constructor declared here
87// CHECK-NONEXCEPTIONS-NOT: warning:
88Z z;
89
90int i = f();
91// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'i' with static storage duration may throw an exception that cannot be caught
92// CHECK-EXCEPTIONS: 44:5: note: possibly throwing function declared here
93// CHECK-NONEXCEPTIONS-NOT: warning:
94int j = g();
95// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'j' with static storage duration may throw an exception that cannot be caught
96// CHECK-EXCEPTIONS: 45:5: note: possibly throwing function declared here
97// CHECK-NONEXCEPTIONS-NOT: warning:
98int k = h();
99int l = some_bad_func();
100// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'l' with static storage duration may throw an exception that cannot be caught
101// CHECK-EXCEPTIONS: 49:3: note: possibly throwing function declared here
102// CHECK-NONEXCEPTIONS-NOT: warning:
103int m = some_good_func();
104
105typedef decltype(sizeof(int)) size_t;
106inline void *operator new(size_t sz, void *here) noexcept { return here; }
107char n[sizeof(int)];
108int *o = new (n) int();
109int *p = new int();
110// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'p' with static storage duration may throw an exception that cannot be caught
111// CHECK-NONEXCEPTIONS-NOT: warning:
112
113thread_local S s3;
114// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 's3' with thread_local storage duration may throw an exception that cannot be caught
115// CHECK-NONEXCEPTIONS-NOT: warning:
116thread_local T t3; // ok
117thread_local U u3;
118// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'u3' with thread_local storage duration may throw an exception that cannot be caught
119// CHECK-NONEXCEPTIONS-NOT: warning:
120thread_local V v3("v");
121// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'v3' with thread_local storage duration may throw an exception that cannot be caught
122// CHECK-NONEXCEPTIONS-NOT: warning:
123thread_local W w3;
124// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'w3' with thread_local storage duration may throw an exception that cannot be caught
125// CHECK-NONEXCEPTIONS-NOT: warning:
126
127void f(S s1, T t1, U u1, V v1, W w1) { // ok, ok, ok, ok, ok
128 S s2; // ok
129 T t2; // ok
130 U u2; // ok
131 V v2("v"); // ok
132 W w2; // ok
133
134 thread_local S s3; // ok
135 thread_local T t3; // ok
136 thread_local U u3; // ok
137 thread_local V v3("v"); // ok
138 thread_local W w3; // ok
139
140 static S s4; // ok
141 static T t4; // ok
142 static U u4; // ok
143 static V v4("v"); // ok
144 static W w4; // ok
145}
146
147namespace {
148S s;
149// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
150// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
151// CHECK-NONEXCEPTIONS-NOT: warning:
152T t; // ok
153U u;
154// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
155// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
156// CHECK-NONEXCEPTIONS-NOT: warning:
157V v("v");
158// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
159// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
160// CHECK-NONEXCEPTIONS-NOT: warning:
161W w;
162// CHECK-EXCEPTIONS: :[[@LINE-1]]:3: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
163// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
164// CHECK-NONEXCEPTIONS-NOT: warning:
165
166thread_local S s3;
167// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 's3' with thread_local storage duration may throw an exception that cannot be caught
168// CHECK-NONEXCEPTIONS-NOT: warning:
169thread_local T t3; // ok
170thread_local U u3;
171// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'u3' with thread_local storage duration may throw an exception that cannot be caught
172// CHECK-NONEXCEPTIONS-NOT: warning:
173thread_local V v3("v");
174// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'v3' with thread_local storage duration may throw an exception that cannot be caught
175// CHECK-NONEXCEPTIONS-NOT: warning:
176thread_local W w3;
177// CHECK-EXCEPTIONS: :[[@LINE-1]]:16: warning: initialization of 'w3' with thread_local storage duration may throw an exception that cannot be caught
178// CHECK-NONEXCEPTIONS-NOT: warning:
179}; // namespace
180
181class Statics {
182 static S s; // warn when initialized
183 static T t; // ok
184 static U u; // warn when initialized
185 static V v; // warn when initialized
186 static W w; // warn when initialized
187
188 void f(S s, T t, U u, V v) {
189 S s2; // ok
190 T t2; // ok
191 U u2; // ok
192 V v2("v"); // ok
193 W w2; // ok
194
195 thread_local S s3; // ok
196 thread_local T t3; // ok
197 thread_local U u3; // ok
198 thread_local V v3("v"); // ok
199 thread_local W w3; // ok
200
201 static S s4; // ok
202 static T t4; // ok
203 static U u4; // ok
204 static V v4("v"); // ok
205 static W w4; // ok
206 }
207};
208
209S Statics::s;
210// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 's' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
211// CHECK-EXCEPTIONS: 9:3: note: possibly throwing constructor declared here
212// CHECK-NONEXCEPTIONS-NOT: warning:
213T Statics::t;
214U Statics::u;
215// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'u' with static storage duration may throw an exception that cannot be caught
216// CHECK-EXCEPTIONS: 17:3: note: possibly throwing constructor declared here
217// CHECK-NONEXCEPTIONS-NOT: warning:
218V Statics::v("v");
219// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'v' with static storage duration may throw an exception that cannot be caught
220// CHECK-EXCEPTIONS: 21:12: note: possibly throwing constructor declared here
221// CHECK-NONEXCEPTIONS-NOT: warning:
222W Statics::w;
223// CHECK-EXCEPTIONS: :[[@LINE-1]]:12: warning: initialization of 'w' with static storage duration may throw an exception that cannot be caught
224// CHECK-EXCEPTIONS: 29:3: note: possibly throwing constructor declared here
225// CHECK-NONEXCEPTIONS-NOT: warning:
226
227#ifndef NONEXCEPTIONS
228namespace pr35457 {
229constexpr int foo(int x) { if (x <= 0) throw 12; return x; }
230
231constexpr int bar = foo(x: 1); // OK
232// CHECK-EXCEPTIONS-NOT: warning: initialization of 'bar' with static storage
233int baz = foo(x: 0); // Not OK; throws at runtime when exceptions are enabled.
234// CHECK-EXCEPTIONS: :[[@LINE-1]]:5: warning: initialization of 'baz' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
235// CHECK-EXCEPTIONS: :[[@LINE-6]]:15: note: possibly throwing function declared here
236} // namespace pr35457
237#endif // NONEXCEPTIONS
238
239namespace pr39777 {
240struct S { S(); };
241struct T { T() noexcept; };
242
243auto Okay1 = []{ S s; };
244auto Okay2 = []{ (void)new int; };
245auto NotOkay1 = []{ S s; return 12; }(); // Because the lambda call is not noexcept
246// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'NotOkay1' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
247// CHECK-EXCEPTIONS: :[[@LINE-7]]:12: note: possibly throwing constructor declared here
248auto NotOkay2 = []() noexcept { S s; return 12; }(); // Because S::S() is not noexcept
249// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'NotOkay2' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
250// CHECK-EXCEPTIONS: :[[@LINE-10]]:12: note: possibly throwing constructor declared here
251auto Okay3 = []() noexcept { T t; return t; }();
252
253struct U {
254 U() noexcept;
255 auto getBadLambda() const noexcept {
256 return []{ S s; return s; };
257 }
258};
259auto Okay4 = []{ U u; return u.getBadLambda(); }();
260auto NotOkay3 = []() noexcept { U u; return u.getBadLambda(); }()(); // Because the lambda returned and called is not noexcept
261// CHECK-EXCEPTIONS: :[[@LINE-1]]:6: warning: initialization of 'NotOkay3' with static storage duration may throw an exception that cannot be caught [cert-err58-cpp]
262// CHECK-EXCEPTIONS: :[[@LINE-6]]:12: note: possibly throwing function declared here
263
264#ifndef NONEXCEPTIONS
265struct Bad {
266 Bad() {
267 throw 12;
268 }
269};
270
271static auto NotOkay4 = [bad = Bad{}](){};
272// FIXME: the above should be diagnosed because the capture init can trigger
273// an exception when constructing the Bad object.
274#endif // NONEXCEPTIONS
275}
276

source code of clang-tools-extra/test/clang-tidy/checkers/cert/static-object-exception.cpp