1 // RUN: %clang_cc1 %s  -fdelayed-template-parsing -fcxx-exceptions -fsyntax-only -Wexceptions -verify -fdeclspec -std=c++11
2 struct A_ShouldDiag {
3   ~A_ShouldDiag(); // implicitly noexcept(true)
4 };
5 A_ShouldDiag::~A_ShouldDiag() { // expected-note {{destructor has a implicit non-throwing exception specification}}
6   throw 1; // expected-warning {{has a non-throwing exception specification but can still throw}}
7 }
8 struct B_ShouldDiag {
9   int i;
10   ~B_ShouldDiag() noexcept(true) {} //no disg, no throw stmt
11 };
12 struct R_ShouldDiag : A_ShouldDiag {
13   B_ShouldDiag b;
14   ~R_ShouldDiag() { // expected-note  {{destructor has a implicit non-throwing exception specification}}
15     throw 1; // expected-warning {{has a non-throwing exception specification but}}
16   }
17   __attribute__((nothrow)) R_ShouldDiag() {// expected-note {{function declared non-throwing here}}
18     throw 1;// expected-warning {{has a non-throwing exception specification but}}
19   }
20   void __attribute__((nothrow)) SomeThrow() {// expected-note {{function declared non-throwing here}}
21    throw 1; // expected-warning {{has a non-throwing exception specification but}}
22   }
23   void __declspec(nothrow) SomeDeclspecThrow() {// expected-note {{function declared non-throwing here}}
24    throw 1; // expected-warning {{has a non-throwing exception specification but}}
25   }
26 };
27 
28 struct M_ShouldNotDiag {
29   B_ShouldDiag b;
30   ~M_ShouldNotDiag() noexcept(false);
31 };
32 
33 M_ShouldNotDiag::~M_ShouldNotDiag() noexcept(false) {
34   throw 1;
35 }
36 
37 struct N_ShouldDiag {
38   B_ShouldDiag b;
39   ~N_ShouldDiag(); //implicitly noexcept(true)
40 };
41 
42 N_ShouldDiag::~N_ShouldDiag() { // expected-note  {{destructor has a implicit non-throwing exception specification}}
43   throw 1; // expected-warning {{has a non-throwing exception specification but}}
44 }
45 struct X_ShouldDiag {
46   B_ShouldDiag b;
47   ~X_ShouldDiag() noexcept { // expected-note  {{destructor has a non-throwing exception}}
48     throw 1; // expected-warning {{has a non-throwing exception specification but}}
49   }
50 };
51 struct Y_ShouldDiag : A_ShouldDiag {
52   ~Y_ShouldDiag() noexcept(true) { // expected-note  {{destructor has a non-throwing exception specification}}
53     throw 1; // expected-warning {{has a non-throwing exception specification but}}
54   }
55 };
56 struct C_ShouldNotDiag {
57   int i;
58   ~C_ShouldNotDiag() noexcept(false) {}
59 };
60 struct D_ShouldNotDiag {
61   C_ShouldNotDiag c;
62   ~D_ShouldNotDiag() { //implicitly noexcept(false)
63     throw 1;
64   }
65 };
66 struct E_ShouldNotDiag {
67   C_ShouldNotDiag c;
68   ~E_ShouldNotDiag(); //implicitly noexcept(false)
69 };
70 E_ShouldNotDiag::~E_ShouldNotDiag() //implicitly noexcept(false)
71 {
72   throw 1;
73 }
74 
75 template <typename T>
76 class A1_ShouldDiag {
77   T b;
78 
79 public:
80   ~A1_ShouldDiag() { // expected-note  {{destructor has a implicit non-throwing exception specification}}
81     throw 1; // expected-warning {{has a non-throwing exception specification but}}
82   }
83 };
84 template <typename T>
85 struct B1_ShouldDiag {
86   T i;
87   ~B1_ShouldDiag() noexcept(true) {}
88 };
89 template <typename T>
90 struct R1_ShouldDiag : A1_ShouldDiag<T> //expected-note {{in instantiation of member function}}
91 {
92   B1_ShouldDiag<T> b;
93   ~R1_ShouldDiag() { // expected-note  {{destructor has a implicit non-throwing exception specification}}
94     throw 1; // expected-warning {{has a non-throwing exception specification but}}
95   }
96 };
97 template <typename T>
98 struct S1_ShouldDiag : A1_ShouldDiag<T> {
99   B1_ShouldDiag<T> b;
100   ~S1_ShouldDiag() noexcept { // expected-note  {{destructor has a non-throwing exception specification}}
101     throw 1; // expected-warning {{has a non-throwing exception specification but}}
102   }
103 };
104 void operator delete(void *ptr) noexcept { // expected-note  {{deallocator has a non-throwing exception specification}}
105   throw 1; // expected-warning {{has a non-throwing exception specification but}}
106 }
107 struct except_fun {
108   static const bool i = false;
109 };
110 struct noexcept_fun {
111   static const bool i = true;
112 };
113 template <typename T>
114 struct dependent_warn {
115   ~dependent_warn() noexcept(T::i) {
116     throw 1;
117   }
118 };
119 template <typename T>
120 struct dependent_warn_noexcept {
121   ~dependent_warn_noexcept() noexcept(T::i) { // expected-note  {{destructor has a non-throwing exception specification}}
122     throw 1; // expected-warning {{has a non-throwing exception specification but}}
123   }
124 };
125 template <typename T>
126 struct dependent_warn_both {
127   ~dependent_warn_both() noexcept(T::i) { // expected-note  {{destructor has a non-throwing exception specification}}
128     throw 1; // expected-warning {{has a non-throwing exception specification but}}
129   }
130 };
131 void foo() noexcept { //expected-note {{function declared non-throwing here}}
132   throw 1; // expected-warning {{has a non-throwing exception specification but}}
133 }
134 struct Throws {
135   ~Throws() noexcept(false);
136 };
137 
138 struct ShouldDiagnose {
139   Throws T;
140   ~ShouldDiagnose() noexcept { //expected-note {{destructor has a non-throwing exception specification}}
141     throw; // expected-warning {{has a non-throwing exception specification but}}
142   }
143 };
144 struct ShouldNotDiagnose {
145   Throws T;
146   ~ShouldNotDiagnose() {
147     throw;
148   }
149 };
150 
151 void bar_ShouldNotDiag() noexcept {
152   try {
153     throw 1;
154   } catch (...) {
155   }
156 }
157 void f_ShouldNotDiag() noexcept {
158   try {
159     throw 12;
160   } catch (int) {
161   }
162 }
163 void g_ShouldNotDiag() noexcept {
164   try {
165     throw 12;
166   } catch (...) {
167   }
168 }
169 
170 void h_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
171   try {
172     throw 12; // expected-warning {{has a non-throwing exception specification but}}
173   } catch (const char *) {
174   }
175 }
176 
177 void i_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
178   try {
179     throw 12;
180   } catch (int) {
181     throw; // expected-warning {{has a non-throwing exception specification but}}
182   }
183 }
184 void j_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
185   try {
186     throw 12;
187   } catch (int) {
188     throw "haha"; // expected-warning {{has a non-throwing exception specification but}}
189   }
190 }
191 
192 void k_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
193   try {
194     throw 12;
195   } catch (...) {
196     throw; // expected-warning {{has a non-throwing exception specification but}}
197   }
198 }
199 
200 void loo_ShouldDiag(int i) noexcept { //expected-note {{function declared non-throwing here}}
201   if (i)
202     try {
203       throw 12;
204     } catch (int) {
205       throw "haha"; //expected-warning {{has a non-throwing exception specification but}}
206     }
207   i = 10;
208 }
209 
210 void loo1_ShouldNotDiag() noexcept {
211   if (0)
212     throw 12;
213 }
214 
215 void loo2_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
216   if (1)
217     throw 12; // expected-warning {{has a non-throwing exception specification but}}
218 }
219 struct S {};
220 
221 void l_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
222   try {
223     throw S{}; //expected-warning {{has a non-throwing exception specification but}}
224   } catch (S *s) {
225   }
226 }
227 
228 void m_ShouldNotDiag() noexcept {
229   try {
230     const S &s = S{};
231     throw s;
232   } catch (S s) {
233   }
234 }
235 void n_ShouldNotDiag() noexcept {
236   try {
237     S s = S{};
238     throw s;
239   } catch (const S &s) {
240   }
241 }
242 // As seen in p34973, this should not throw the warning.  If there is an active
243 // exception, catch(...) catches everything.
244 void o_ShouldNotDiag() noexcept {
245   try {
246     throw;
247   } catch (...) {
248   }
249 }
250 
251 void p_ShouldDiag() noexcept { //expected-note {{function declared non-throwing here}}
252   try {
253     throw; //expected-warning {{has a non-throwing exception specification but}}
254   } catch (int){
255   }
256 }
257 
258 void q_ShouldNotDiag() noexcept {
259   try {
260     throw;
261   } catch (int){
262   } catch (...){
263   }
264 }
265 
266 #define NOEXCEPT noexcept
267 void with_macro() NOEXCEPT { //expected-note {{function declared non-throwing here}}
268   throw 1; // expected-warning {{has a non-throwing exception specification but}}
269 }
270 
271 void with_try_block() try {
272   throw 2;
273 } catch (...) {
274 }
275 
276 void with_try_block1() noexcept try { //expected-note {{function declared non-throwing here}}
277   throw 2; // expected-warning {{has a non-throwing exception specification but}}
278 } catch (char *) {
279 }
280 
281 namespace derived {
282 struct B {};
283 struct D: B {};
284 void goodPlain() noexcept {
285   try {
286     throw D();
287   } catch (B) {}
288 }
289 void goodReference() noexcept {
290   try {
291     throw D();
292   } catch (B &) {}
293 }
294 void goodPointer() noexcept {
295   D d;
296   try {
297     throw &d;
298   } catch (B *) {}
299 }
300 void badPlain() noexcept { //expected-note {{function declared non-throwing here}}
301   try {
302     throw B(); // expected-warning {{'badPlain' has a non-throwing exception specification but can still throw}}
303   } catch (D) {}
304 }
305 void badReference() noexcept { //expected-note {{function declared non-throwing here}}
306   try {
307     throw B(); // expected-warning {{'badReference' has a non-throwing exception specification but can still throw}}
308   } catch (D &) {}
309 }
310 void badPointer() noexcept { //expected-note {{function declared non-throwing here}}
311   B b;
312   try {
313     throw &b; // expected-warning {{'badPointer' has a non-throwing exception specification but can still throw}}
314   } catch (D *) {}
315 }
316 }
317 
318 int main() {
319   R1_ShouldDiag<int> o; //expected-note {{in instantiation of member function}}
320   S1_ShouldDiag<int> b; //expected-note {{in instantiation of member function}}
321   dependent_warn<except_fun> f;
322   dependent_warn_noexcept<noexcept_fun> f1; //expected-note {{in instantiation of member function}}
323   dependent_warn_both<except_fun> f2;
324   dependent_warn_both<noexcept_fun> f3; //expected-note {{in instantiation of member function}}
325   ShouldDiagnose obj;
326   ShouldNotDiagnose obj1;
327 }
328