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