OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2013 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <setjmp.h> | 8 #include <setjmp.h> |
9 #include <stdio.h> | 9 #include <stdio.h> |
10 | 10 |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 // where the return address has been overwritten with | 321 // where the return address has been overwritten with |
322 // longjmp()'s return address, so we return here. | 322 // longjmp()'s return address, so we return here. |
323 assert(false); | 323 assert(false); |
324 } | 324 } |
325 } catch (...) { | 325 } catch (...) { |
326 assert(false); | 326 assert(false); |
327 } | 327 } |
328 } | 328 } |
329 | 329 |
330 | 330 |
| 331 void allowed_exception_spec() throw(MyException) { |
| 332 throw MyException(600); |
| 333 } |
| 334 |
| 335 // Test a case in which an exception propagates through an exception |
| 336 // spec which allows the exception type. |
| 337 void test_exception_spec_allowed() { |
| 338 bool caught = false; |
| 339 try { |
| 340 allowed_exception_spec(); |
| 341 } catch (MyException &exc) { |
| 342 assert(exc.value == 600); |
| 343 caught = true; |
| 344 } |
| 345 assert(caught); |
| 346 } |
| 347 |
| 348 |
| 349 class VirtualBase { |
| 350 public: |
| 351 VirtualBase() : value(321) {} |
| 352 int value; |
| 353 }; |
| 354 |
| 355 class VirtualDerived : virtual public VirtualBase {}; |
| 356 |
| 357 void allowed_exception_spec_virtual_base() throw(VirtualBase) { |
| 358 throw VirtualDerived(); |
| 359 } |
| 360 |
| 361 // Test that exception types with virtual base classes work when the |
| 362 // base class appears in an exception spec. |
| 363 // |
| 364 // In this case, the C++ runtime library must dereference the |
| 365 // exception's vtable to find the offset of VirtualBase within |
| 366 // VirtualDerived. That is not the case with non-virtual bases, for |
| 367 // which the std::type_info data is enough to adjust the pointer to |
| 368 // the exception without dereferencing it. |
| 369 void test_exception_spec_allowed_with_virtual_base() { |
| 370 bool caught = false; |
| 371 try { |
| 372 allowed_exception_spec_virtual_base(); |
| 373 } catch (VirtualBase &exc) { |
| 374 assert(exc.value == 321); |
| 375 caught = true; |
| 376 } |
| 377 assert(caught); |
| 378 } |
| 379 |
| 380 |
331 class RethrowExc {}; | 381 class RethrowExc {}; |
332 | 382 |
333 bool g_dtor_called; | 383 bool g_dtor_called; |
334 | 384 |
335 void rethrow_unexpected_handler() { | 385 void rethrow_unexpected_handler() { |
336 // func_with_exception_spec()'s destructors should be run before the | 386 // func_with_exception_spec()'s destructors should be run before the |
337 // exception spec (a "filter" clause in LLVM) is checked and we are | 387 // exception spec (a "filter" clause in LLVM) is checked and we are |
338 // called. | 388 // called. |
339 // | 389 // |
340 // This means that the std::set_unexpected() handler should be | 390 // This means that the std::set_unexpected() handler should be |
(...skipping 11 matching lines...) Expand all Loading... |
352 void func_with_exception_spec() throw(RethrowExc) { | 402 void func_with_exception_spec() throw(RethrowExc) { |
353 Dtor dtor(&g_dtor_called); | 403 Dtor dtor(&g_dtor_called); |
354 throw MyException(100); | 404 throw MyException(100); |
355 } | 405 } |
356 | 406 |
357 // Test that exception specs work. Test that if an exception doesn't | 407 // Test that exception specs work. Test that if an exception doesn't |
358 // match the exception spec of a function, the current | 408 // match the exception spec of a function, the current |
359 // std::set_unexpected() handler is called. The handler is allowed to | 409 // std::set_unexpected() handler is called. The handler is allowed to |
360 // throw a new exception that matches the exception spec -- we test | 410 // throw a new exception that matches the exception spec -- we test |
361 // this case to avoid aborting execution. | 411 // this case to avoid aborting execution. |
362 void test_exception_spec() { | 412 void test_exception_spec_calls_handler() { |
363 g_dtor_called = false; | 413 g_dtor_called = false; |
364 std::unexpected_handler old_unexpected_handler = | 414 std::unexpected_handler old_unexpected_handler = |
365 std::set_unexpected(rethrow_unexpected_handler); | 415 std::set_unexpected(rethrow_unexpected_handler); |
366 bool caught = false; | 416 bool caught = false; |
367 try { | 417 try { |
368 func_with_exception_spec(); | 418 func_with_exception_spec(); |
369 } catch (RethrowExc &) { | 419 } catch (RethrowExc &) { |
370 caught = true; | 420 caught = true; |
371 } | 421 } |
372 assert(caught); | 422 assert(caught); |
373 // Clean up. | 423 // Clean up. |
374 std::set_unexpected(old_unexpected_handler); | 424 std::set_unexpected(old_unexpected_handler); |
375 } | 425 } |
376 | 426 |
377 | 427 |
| 428 void unexpected_handler_throwing_virtual_base() { |
| 429 throw VirtualDerived(); |
| 430 } |
| 431 |
| 432 void disallowed_exception_spec_virtual_base() throw(VirtualBase) { |
| 433 throw MyException(0); |
| 434 } |
| 435 |
| 436 // Test that if a std::set_unexpected() handler throws an exception |
| 437 // with a virtual base class, this new exception is checked against |
| 438 // the original exception spec correctly. |
| 439 void test_exception_spec_handler_throws_virtual_base() { |
| 440 std::unexpected_handler old_unexpected_handler = |
| 441 std::set_unexpected(unexpected_handler_throwing_virtual_base); |
| 442 bool caught = false; |
| 443 try { |
| 444 disallowed_exception_spec_virtual_base(); |
| 445 } catch (VirtualBase &exc) { |
| 446 assert(exc.value == 321); |
| 447 caught = true; |
| 448 } |
| 449 assert(caught); |
| 450 // Clean up. |
| 451 std::set_unexpected(old_unexpected_handler); |
| 452 } |
| 453 |
| 454 |
378 void rethrowing_unexpected_handler() { | 455 void rethrowing_unexpected_handler() { |
379 try { | 456 try { |
380 throw; | 457 throw; |
381 } catch (MyException &exc) { | 458 } catch (MyException &exc) { |
382 assert(exc.value == 100); | 459 assert(exc.value == 100); |
383 } | 460 } |
384 throw RethrowExc(); | 461 throw RethrowExc(); |
385 } | 462 } |
386 | 463 |
387 // Test that the "current exception" inside the std::set_unexpected() | 464 // Test that the "current exception" inside the std::set_unexpected() |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 RUN_TEST(test_catch_all()); | 646 RUN_TEST(test_catch_all()); |
570 RUN_TEST(test_nested_try_blocks()); | 647 RUN_TEST(test_nested_try_blocks()); |
571 RUN_TEST(test_throw_in_catch_block()); | 648 RUN_TEST(test_throw_in_catch_block()); |
572 RUN_TEST(test_dtor()); | 649 RUN_TEST(test_dtor()); |
573 RUN_TEST(test_rethrow()); | 650 RUN_TEST(test_rethrow()); |
574 RUN_TEST(test_stack_of_exceptions()); | 651 RUN_TEST(test_stack_of_exceptions()); |
575 RUN_TEST(test_multiple_inheritance_exception()); | 652 RUN_TEST(test_multiple_inheritance_exception()); |
576 RUN_TEST(test_multiple_inheritance_exception_ptr()); | 653 RUN_TEST(test_multiple_inheritance_exception_ptr()); |
577 RUN_TEST(test_throw_catch_nested_in_dtor()); | 654 RUN_TEST(test_throw_catch_nested_in_dtor()); |
578 RUN_TEST(test_setjmp_called_via_invoke()); | 655 RUN_TEST(test_setjmp_called_via_invoke()); |
579 RUN_TEST(test_exception_spec()); | 656 RUN_TEST(test_exception_spec_allowed()); |
| 657 RUN_TEST(test_exception_spec_allowed_with_virtual_base()); |
| 658 RUN_TEST(test_exception_spec_calls_handler()); |
| 659 RUN_TEST(test_exception_spec_handler_throws_virtual_base()); |
580 RUN_TEST(test_exception_spec_rethrow_inside_unexpected_handler()); | 660 RUN_TEST(test_exception_spec_rethrow_inside_unexpected_handler()); |
581 RUN_TEST(test_exception_spec_convert_to_bad_exception()); | 661 RUN_TEST(test_exception_spec_convert_to_bad_exception()); |
582 #if SUPPORTS_CXX11 | 662 #if SUPPORTS_CXX11 |
583 RUN_TEST(test_dependent_exception()); | 663 RUN_TEST(test_dependent_exception()); |
584 RUN_TEST(test_dependent_exception_and_dtor()); | 664 RUN_TEST(test_dependent_exception_and_dtor()); |
585 RUN_TEST(test_dependent_exception_and_exception_spec()); | 665 RUN_TEST(test_dependent_exception_and_exception_spec()); |
586 #endif | 666 #endif |
587 // This leaves behind an active exception because of its use of | 667 // This leaves behind an active exception because of its use of |
588 // longjmp() to exit from a std::set_terminate() handler, so put it | 668 // longjmp() to exit from a std::set_terminate() handler, so put it |
589 // last, just in case that accidentally affects other tests. | 669 // last, just in case that accidentally affects other tests. |
590 RUN_TEST(test_exception_spec_bad_throw_from_unexpected_handler()); | 670 RUN_TEST(test_exception_spec_bad_throw_from_unexpected_handler()); |
591 | 671 |
592 // Indicate success. | 672 // Indicate success. |
593 return 55; | 673 return 55; |
594 } | 674 } |
OLD | NEW |