forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This implements my latest proposed wording for P2927, namely: > Mandates: E is a cv-unqualified complete object type. E is not an array type. > E is not a pointer or pointer-to-member type. [Note: When E is a pointer or > pointer-to-member type, a handler of type const E& can match without binding > to the exception object itself. —end note] > Returns: A pointer to the exception object referred to by p, if p is not null > and a handler of type const E& would be a match [except.handle] for that > exception object. Otherwise, nullptr.
- Loading branch information
1 parent
3f549be
commit 6e20a0b
Showing
4 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
libcxx/test/std/language.support/support.exception/propagation/try_cast.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: no-exceptions | ||
// <exception> | ||
|
||
// template<class E> const E* try_cast(const exception_ptr& p); | ||
|
||
#include <exception> | ||
#include <cassert> | ||
|
||
#include "test_macros.h" | ||
|
||
struct A | ||
{ | ||
static int constructed; | ||
int data_; | ||
|
||
A(int data = 0) : data_(data) {++constructed;} | ||
~A() {--constructed;} | ||
A(const A& a) : data_(a.data_) {++constructed;} | ||
}; | ||
|
||
int A::constructed = 0; | ||
|
||
struct Abstract { | ||
explicit Abstract() = default; | ||
Abstract(const Abstract&) = default; | ||
virtual int f() const = 0; | ||
virtual ~Abstract() = default; | ||
}; | ||
struct Concrete : Abstract { | ||
int f() const override { return 42; }; | ||
}; | ||
struct Incomplete; | ||
|
||
int main(int, char**) | ||
{ | ||
{ | ||
std::exception_ptr p = std::make_exception_ptr(A(5)); | ||
int cted = A::constructed; | ||
#ifdef _LIBCPP_ABI_MICROSOFT | ||
// On Windows exception_ptr copies the exception | ||
assert(cted == 2); | ||
#else | ||
assert(cted == 1); | ||
#endif | ||
ASSERT_SAME_TYPE(decltype(std::try_cast<A>(p)), const A*); | ||
ASSERT_SAME_TYPE(decltype(std::try_cast<A>(nullptr)), const A*); | ||
const auto *pa = std::try_cast<A>(p); | ||
// The in-flight exception object is not copied | ||
assert(A::constructed == cted); | ||
const auto *pb = std::try_cast<A>(p); | ||
assert(A::constructed == cted); | ||
// The in-flight exception object's address doesn't change | ||
assert(pa == pb); | ||
assert(pa->data_ == 5); | ||
} | ||
assert(A::constructed == 0); | ||
|
||
{ | ||
std::exception_ptr p; | ||
assert(std::try_cast<A>(p) == nullptr); | ||
assert(std::try_cast<A>(nullptr) == nullptr); | ||
} | ||
|
||
// Try modifying an object in flight | ||
{ | ||
try { | ||
try { | ||
throw A(1); | ||
} catch (const A& a) { | ||
std::exception_ptr p = std::current_exception(); | ||
const auto *pa = std::try_cast<A>(p); | ||
assert(pa == &a); | ||
assert(pa->data_ == 1); | ||
const_cast<A*>(pa)->data_ = 2; | ||
std::rethrow_exception(p); | ||
assert(false); | ||
} | ||
} catch (const A& a2) { | ||
assert(a2.data_ == 2); | ||
} | ||
assert(A::constructed == 0); | ||
} | ||
|
||
// Try catching some exotic types | ||
{ | ||
std::exception_ptr p = std::make_exception_ptr(1); | ||
assert(std::try_cast<int>(p) != nullptr); | ||
assert(*std::try_cast<int>(p) == 1); | ||
assert(std::try_cast<long>(p) == nullptr); | ||
assert(std::try_cast<unsigned int>(p) == nullptr); | ||
|
||
p = std::make_exception_ptr(Concrete()); | ||
assert(std::try_cast<Abstract>(p) != nullptr); | ||
assert(std::try_cast<Abstract>(p)->f() == 42); | ||
} | ||
return 0; | ||
} |
52 changes: 52 additions & 0 deletions
52
libcxx/test/std/language.support/support.exception/propagation/try_cast.verify.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: no-exceptions | ||
// <exception> | ||
|
||
// template<class E> const E* try_cast(const exception_ptr& p); | ||
// Mandates: | ||
// - T is a complete object type. | ||
// - T is not cv-qualified. | ||
// - T is not an array type. | ||
|
||
#include <exception> | ||
|
||
struct Incomplete; | ||
struct Base { int x; int f(); }; | ||
|
||
int main(int, char**) | ||
{ | ||
std::exception_ptr p; | ||
(void)std::try_cast<void>(p); //expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'void'}} | ||
(void)std::try_cast<int&>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type, and not an array type}} | ||
(void)std::try_cast<int&&>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type, and not an array type}} | ||
(void)std::try_cast<int*&>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type, and not an array type}} | ||
(void)std::try_cast<const int>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type, and not an array type}} | ||
(void)std::try_cast<volatile int>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type, and not an array type}} | ||
//expected-error@*:* {{cannot initialize return object}} | ||
(void)std::try_cast<Incomplete>(p); //expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'Incomplete'}} | ||
(void)std::try_cast<int()>(p); //expected-error@*:* {{invalid application of 'sizeof' to a function type}} | ||
(void)std::try_cast<int[]>(p); //expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'int[]'}} | ||
(void)std::try_cast<int[5]>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type, and not an array type}} | ||
(void)std::try_cast<int(&)()>(p); //expected-error@*:* {{invalid application of 'sizeof' to a function type}} | ||
(void)std::try_cast<int(&)[]>(p); //expected-error@*:* {{invalid application of 'sizeof' to an incomplete type 'int[]'}} | ||
(void)std::try_cast<int(&)[5]>(p); //expected-error@*:* {{E must be a complete cv-unqualified object type}} | ||
|
||
(void)std::try_cast<void*>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<int*>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<int(*)[5]>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<Base*>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<const Base*>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<Incomplete*>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<int(*)()>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<int Base::*>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
(void)std::try_cast<int (Base::*)()>(p); //expected-error@*:* {{E must not be a pointer or pointer-to-member type}} | ||
|
||
return 0; | ||
} |