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