| 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 | |