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 
8 struct S {
9   S() noexcept(false);
10 };
11 
12 struct T {
13   T() noexcept;
14 };
15 
16 struct U {
UU17   U() {}
18 };
19 
20 struct V {
VV21   explicit V(const char *) {} // Can throw
22 };
23 
24 struct Cleanup {
~CleanupCleanup25   ~Cleanup() {}
26 };
27 
28 struct W {
29   W(Cleanup c = {}) noexcept(false);
30 };
31 
32 struct X {
33   X(S = {}) noexcept;
34 };
35 
36 struct Y {
37   S s;
38 };
39 
40 struct Z {
41   T t;
42 };
43 
44 int f();
45 int g() noexcept(false);
46 int h() noexcept(true);
47 
48 struct UserConv_Bad {
49   operator int() noexcept(false);
50 };
51 
52 struct UserConv_Good {
53   operator int() noexcept;
54 };
55 
56 UserConv_Bad some_bad_func() noexcept;
57 UserConv_Good some_good_func() noexcept;
58 
59 S 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:
63 T t; // ok
64 U 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:
68 V 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:
72 W 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:
76 X 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:
80 X 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:
84 Y 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:
88 Z z;
89 
90 int 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:
94 int 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:
98 int k = h();
99 int 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:
103 int m = some_good_func();
104 
105 typedef decltype(sizeof(int)) size_t;
operator new(size_t sz,void * here)106 inline void *operator new(size_t sz, void *here) noexcept { return here; }
107 char n[sizeof(int)];
108 int *o = new (n) int();
109 int *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 
113 thread_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:
116 thread_local T t3; // ok
117 thread_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:
120 thread_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:
123 thread_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 
f(S s1,T t1,U u1,V v1,W w1)127 void 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 
147 namespace {
148 S 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:
152 T t; // ok
153 U 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:
157 V 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:
161 W 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 
166 thread_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:
169 thread_local T t3; // ok
170 thread_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:
173 thread_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:
176 thread_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 
181 class 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 
f(S s,T t,U u,V v)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 
209 S 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:
213 T Statics::t;
214 U 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:
218 V 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:
222 W 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
228 namespace pr35457 {
foo(int x)229 constexpr int foo(int x) { if (x <= 0) throw 12; return x; }
230 
231 constexpr int bar = foo(1); // OK
232 // CHECK-EXCEPTIONS-NOT: warning: initialization of 'bar' with static storage
233 int baz = foo(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 
239 namespace pr39777 {
240 struct S { S(); };
241 struct T { T() noexcept; };
242 
__anona0f32d9d0202null243 auto Okay1 = []{ S s; };
__anona0f32d9d0302null244 auto Okay2 = []{ (void)new int; };
__anona0f32d9d0402null245 auto 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
__anona0f32d9d0502() 248 auto 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
__anona0f32d9d0602() 251 auto Okay3 = []() noexcept { T t; return t; }();
252 
253 struct U {
254   U() noexcept;
getBadLambdapr39777::U255   auto getBadLambda() const noexcept {
256     return []{ S s; return s; };
257   }
258 };
__anona0f32d9d0802null259 auto Okay4 = []{ U u; return u.getBadLambda(); }();
__anona0f32d9d0902() 260 auto 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
265 struct Bad {
Badpr39777::Bad266   Bad() {
267     throw 12;
268   }
269 };
270 
__anona0f32d9d0a02()271 static 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