1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | |
3 | // Reachability tests have to come first because they get suppressed |
4 | // if any errors have occurred. |
5 | namespace test5 { |
6 | struct A { |
7 | __attribute__((noreturn)) void fail(); |
8 | void nofail(); |
9 | } a; |
10 | |
11 | int &test1() { |
12 | a.nofail(); |
13 | } // expected-warning {{control reaches end of non-void function}} |
14 | |
15 | int &test2() { |
16 | a.fail(); |
17 | } |
18 | } |
19 | |
20 | namespace destructor_tests { |
21 | __attribute__((noreturn)) void fail(); |
22 | |
23 | struct A { |
24 | ~A() __attribute__((noreturn)) { fail(); } |
25 | }; |
26 | struct B { |
27 | B() {} |
28 | ~B() __attribute__((noreturn)) { fail(); } |
29 | }; |
30 | struct C : A {}; |
31 | struct D : B {}; |
32 | struct E : virtual A {}; |
33 | struct F : A, virtual B {}; |
34 | struct G : E {}; |
35 | struct H : virtual D {}; |
36 | struct I : A {}; |
37 | struct J : I {}; |
38 | struct K : virtual A {}; |
39 | struct L : K {}; |
40 | struct M : virtual C {}; |
41 | struct N : M {}; |
42 | struct O { N n; }; |
43 | |
44 | __attribute__((noreturn)) void test_1() { A a; } |
45 | __attribute__((noreturn)) void test_2() { B b; } |
46 | __attribute__((noreturn)) void test_3() { C c; } |
47 | __attribute__((noreturn)) void test_4() { D d; } |
48 | __attribute__((noreturn)) void test_5() { E e; } |
49 | __attribute__((noreturn)) void test_6() { F f; } |
50 | __attribute__((noreturn)) void test_7() { G g; } |
51 | __attribute__((noreturn)) void test_8() { H h; } |
52 | __attribute__((noreturn)) void test_9() { I i; } |
53 | __attribute__((noreturn)) void test_10() { J j; } |
54 | __attribute__((noreturn)) void test_11() { K k; } |
55 | __attribute__((noreturn)) void test_12() { L l; } |
56 | __attribute__((noreturn)) void test_13() { M m; } |
57 | __attribute__((noreturn)) void test_14() { N n; } |
58 | __attribute__((noreturn)) void test_15() { O o; } |
59 | |
60 | __attribute__((noreturn)) void test_16() { const A& a = A(); } |
61 | __attribute__((noreturn)) void test_17() { const B& b = B(); } |
62 | __attribute__((noreturn)) void test_18() { const C& c = C(); } |
63 | __attribute__((noreturn)) void test_19() { const D& d = D(); } |
64 | __attribute__((noreturn)) void test_20() { const E& e = E(); } |
65 | __attribute__((noreturn)) void test_21() { const F& f = F(); } |
66 | __attribute__((noreturn)) void test_22() { const G& g = G(); } |
67 | __attribute__((noreturn)) void test_23() { const H& h = H(); } |
68 | __attribute__((noreturn)) void test_24() { const I& i = I(); } |
69 | __attribute__((noreturn)) void test_25() { const J& j = J(); } |
70 | __attribute__((noreturn)) void test_26() { const K& k = K(); } |
71 | __attribute__((noreturn)) void test_27() { const L& l = L(); } |
72 | __attribute__((noreturn)) void test_28() { const M& m = M(); } |
73 | __attribute__((noreturn)) void test_29() { const N& n = N(); } |
74 | __attribute__((noreturn)) void test_30() { const O& o = O(); } |
75 | |
76 | struct AA {}; |
77 | struct BB { BB() {} ~BB() {} }; |
78 | struct CC : AA {}; |
79 | struct DD : BB {}; |
80 | struct EE : virtual AA {}; |
81 | struct FF : AA, virtual BB {}; |
82 | struct GG : EE {}; |
83 | struct HH : virtual DD {}; |
84 | struct II : AA {}; |
85 | struct JJ : II {}; |
86 | struct KK : virtual AA {}; |
87 | struct LL : KK {}; |
88 | struct MM : virtual CC {}; |
89 | struct NN : MM {}; |
90 | struct OO { NN n; }; |
91 | |
92 | __attribute__((noreturn)) void test_31() { |
93 | AA a; |
94 | BB b; |
95 | CC c; |
96 | DD d; |
97 | EE e; |
98 | FF f; |
99 | GG g; |
100 | HH h; |
101 | II i; |
102 | JJ j; |
103 | KK k; |
104 | LL l; |
105 | MM m; |
106 | NN n; |
107 | OO o; |
108 | |
109 | const AA& aa = AA(); |
110 | const BB& bb = BB(); |
111 | const CC& cc = CC(); |
112 | const DD& dd = DD(); |
113 | const EE& ee = EE(); |
114 | const FF& ff = FF(); |
115 | const GG& gg = GG(); |
116 | const HH& hh = HH(); |
117 | const II& ii = II(); |
118 | const JJ& jj = JJ(); |
119 | const KK& kk = KK(); |
120 | const LL& ll = LL(); |
121 | const MM& mm = MM(); |
122 | const NN& nn = NN(); |
123 | const OO& oo = OO(); |
124 | } // expected-warning {{function declared 'noreturn' should not return}} |
125 | |
126 | struct P { |
127 | ~P() __attribute__((noreturn)) { fail(); } |
128 | void foo() {} |
129 | }; |
130 | struct Q : P { }; |
131 | __attribute__((noreturn)) void test31() { |
132 | P().foo(); |
133 | } |
134 | __attribute__((noreturn)) void test32() { |
135 | Q().foo(); |
136 | } |
137 | |
138 | struct R { |
139 | A a[5]; |
140 | }; |
141 | __attribute__((noreturn)) void test33() { |
142 | R r; |
143 | } |
144 | |
145 | // FIXME: Code flow analysis does not preserve information about non-null |
146 | // pointers, so it can't determine that this function is noreturn. |
147 | __attribute__((noreturn)) void test34() { |
148 | A *a = new A; |
149 | delete a; |
150 | } // expected-warning {{function declared 'noreturn' should not return}} |
151 | |
152 | struct S { |
153 | virtual ~S(); |
154 | }; |
155 | struct T : S { |
156 | __attribute__((noreturn)) ~T(); |
157 | }; |
158 | |
159 | // FIXME: Code flow analysis does not preserve information about non-null |
160 | // pointers or derived class pointers, so it can't determine that this |
161 | // function is noreturn. |
162 | __attribute__((noreturn)) void test35() { |
163 | S *s = new T; |
164 | delete s; |
165 | } // expected-warning {{function declared 'noreturn' should not return}} |
166 | } |
167 | |
168 | // PR5620 |
169 | void f0() __attribute__((__noreturn__)); |
170 | void f1(void (*)()); |
171 | void f2() { f1(f0); } |
172 | |
173 | // Taking the address of a noreturn function |
174 | void test_f0a() { |
175 | void (*fp)() = f0; |
176 | void (*fp1)() __attribute__((noreturn)) = f0; |
177 | } |
178 | |
179 | // Taking the address of an overloaded noreturn function |
180 | void f0(int) __attribute__((__noreturn__)); |
181 | |
182 | void test_f0b() { |
183 | void (*fp)() = f0; |
184 | void (*fp1)() __attribute__((noreturn)) = f0; |
185 | } |
186 | |
187 | // No-returned function pointers |
188 | typedef void (* noreturn_fp)() __attribute__((noreturn)); |
189 | |
190 | void f3(noreturn_fp); // expected-note{{candidate function}} |
191 | |
192 | void test_f3() { |
193 | f3(f0); // okay |
194 | f3(f2); // expected-error{{no matching function for call}} |
195 | } |
196 | |
197 | |
198 | class xpto { |
199 | int blah() __attribute__((noreturn)); |
200 | }; |
201 | |
202 | int xpto::blah() { |
203 | return 3; // expected-warning {{function 'blah' declared 'noreturn' should not return}} |
204 | } |
205 | |
206 | // PR12948 |
207 | |
208 | namespace PR12948 { |
209 | template<int> |
210 | void foo() __attribute__((__noreturn__)); |
211 | |
212 | template<int> |
213 | void foo() { |
214 | while (1) continue; |
215 | } |
216 | |
217 | void bar() __attribute__((__noreturn__)); |
218 | |
219 | void bar() { |
220 | foo<0>(); |
221 | } |
222 | |
223 | |
224 | void baz() __attribute__((__noreturn__)); |
225 | typedef void voidfn(); |
226 | voidfn baz; |
227 | |
228 | template<typename> void wibble() __attribute__((__noreturn__)); |
229 | template<typename> voidfn wibble; |
230 | } |
231 | |
232 | // PR15291 |
233 | // Overload resolution per over.over should allow implicit noreturn adjustment. |
234 | namespace PR15291 { |
235 | __attribute__((noreturn)) void foo(int) {} |
236 | __attribute__((noreturn)) void foo(double) {} |
237 | |
238 | template <typename T> |
239 | __attribute__((noreturn)) void bar(T) {} |
240 | |
241 | void baz(int) {} |
242 | void baz(double) {} |
243 | |
244 | template <typename T> |
245 | void qux(T) {} |
246 | |
247 | // expected-note@+5 {{candidate function template not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} |
248 | // expected-note@+4 {{candidate function template not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} |
249 | // expected-note@+3 {{candidate function template not viable: no overload of 'bar' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} |
250 | // expected-note@+2 {{candidate function template not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} |
251 | // expected-note@+1 {{candidate function template not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} |
252 | template <typename T> void accept_T(T) {} |
253 | |
254 | // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'void (*)(int)' for 1st argument}} |
255 | void accept_fptr(void (*f)(int)) { |
256 | f(42); |
257 | } |
258 | |
259 | // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} |
260 | // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'void (*)(int) __attribute__((noreturn))' for 1st argument}} |
261 | void accept_noreturn_fptr(void __attribute__((noreturn)) (*f)(int)) { |
262 | f(42); |
263 | } |
264 | |
265 | typedef void (*fptr_t)(int); |
266 | typedef void __attribute__((noreturn)) (*fptr_noreturn_t)(int); |
267 | |
268 | // expected-note@+1 {{candidate function not viable: no overload of 'bar' matching 'PR15291::fptr_t' (aka 'void (*)(int)') for 1st argument}} |
269 | void accept_fptr_t(fptr_t f) { |
270 | f(42); |
271 | } |
272 | |
273 | // expected-note@+2 {{candidate function not viable: no overload of 'baz' matching 'PR15291::fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}} |
274 | // expected-note@+1 {{candidate function not viable: no overload of 'qux' matching 'PR15291::fptr_noreturn_t' (aka 'void (*)(int) __attribute__((noreturn))') for 1st argument}} |
275 | void accept_fptr_noreturn_t(fptr_noreturn_t f) { |
276 | f(42); |
277 | } |
278 | |
279 | // Stripping noreturn should work if everything else is correct. |
280 | void strip_noreturn() { |
281 | accept_fptr(foo); |
282 | accept_fptr(bar<int>); |
283 | accept_fptr(bar<double>); // expected-error {{no matching function for call to 'accept_fptr'}} |
284 | |
285 | accept_fptr_t(foo); |
286 | accept_fptr_t(bar<int>); |
287 | accept_fptr_t(bar<double>); // expected-error {{no matching function for call to 'accept_fptr_t'}} |
288 | |
289 | accept_T<void __attribute__((noreturn)) (*)(int)>(foo); |
290 | accept_T<void __attribute__((noreturn)) (*)(int)>(bar<int>); |
291 | accept_T<void __attribute__((noreturn)) (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}} |
292 | |
293 | accept_T<void (*)(int)>(foo); |
294 | accept_T<void (*)(int)>(bar<int>); |
295 | accept_T<void (*)(int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}} |
296 | |
297 | accept_T<void (int)>(foo); |
298 | accept_T<void (int)>(bar<int>); |
299 | accept_T<void (int)>(bar<double>); // expected-error {{no matching function for call to 'accept_T'}} |
300 | } |
301 | |
302 | // Introducing noreturn should not work. |
303 | void introduce_noreturn() { |
304 | accept_noreturn_fptr(baz); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}} |
305 | accept_noreturn_fptr(qux<int>); // expected-error {{no matching function for call to 'accept_noreturn_fptr'}} |
306 | |
307 | accept_fptr_noreturn_t(baz); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}} |
308 | accept_fptr_noreturn_t(qux<int>); // expected-error {{no matching function for call to 'accept_fptr_noreturn_t'}} |
309 | |
310 | accept_T<void __attribute__((noreturn)) (*)(int)>(baz); // expected-error {{no matching function for call to 'accept_T'}} |
311 | accept_T<void __attribute__((noreturn)) (*)(int)>(qux<int>); // expected-error {{no matching function for call to 'accept_T'}} |
312 | } |
313 | } |
314 | |