diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-29 16:25:46 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-29 16:25:46 +0000 |
commit | b5aee35cc5d62f11d98539f62e4fe63f0ac9edc6 (patch) | |
tree | 3e6ab962dbc73cfe1445a60d2eb4dfba7c939a22 /test/SemaCXX | |
parent | aa803409c3bd3930126db630c29f63d42f255153 (diff) |
Notes
Diffstat (limited to 'test/SemaCXX')
-rw-r--r-- | test/SemaCXX/coreturn.cpp | 89 | ||||
-rw-r--r-- | test/SemaCXX/coroutine-seh.cpp | 37 | ||||
-rw-r--r-- | test/SemaCXX/coroutine-unhandled_exception-warning.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/coroutines.cpp | 134 | ||||
-rw-r--r-- | test/SemaCXX/default-assignment-operator.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/deprecated.cpp | 8 | ||||
-rw-r--r-- | test/SemaCXX/null-cast.cpp | 8 | ||||
-rw-r--r-- | test/SemaCXX/uninitialized.cpp | 2 | ||||
-rw-r--r-- | test/SemaCXX/virtual-base-used.cpp | 22 |
9 files changed, 280 insertions, 26 deletions
diff --git a/test/SemaCXX/coreturn.cpp b/test/SemaCXX/coreturn.cpp index bdad227ea4469..0ec94d1b59971 100644 --- a/test/SemaCXX/coreturn.cpp +++ b/test/SemaCXX/coreturn.cpp @@ -18,6 +18,43 @@ struct promise_void { void unhandled_exception(); }; +struct promise_void_return_value { + void get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); + void return_value(int); +}; + +struct VoidTagNoReturn { + struct promise_type { + VoidTagNoReturn get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); + }; +}; + +struct VoidTagReturnValue { + struct promise_type { + VoidTagReturnValue get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); + void return_value(int); + }; +}; + +struct VoidTagReturnVoid { + struct promise_type { + VoidTagReturnVoid get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); + void return_void(); + }; +}; + struct promise_float { float get_return_object(); suspend_always initial_suspend(); @@ -34,8 +71,11 @@ struct promise_int { void unhandled_exception(); }; -template <typename... T> -struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise_void; }; +template <> +struct std::experimental::coroutine_traits<void> { using promise_type = promise_void; }; + +template <typename T1> +struct std::experimental::coroutine_traits<void, T1> { using promise_type = promise_void_return_value; }; template <typename... T> struct std::experimental::coroutine_traits<float, T...> { using promise_type = promise_float; }; @@ -48,10 +88,53 @@ float test1() { co_await a; } int test2() { co_await a; -} // expected-warning {{control reaches end of non-void coroutine}} +} // expected-warning {{control reaches end of coroutine; which is undefined behavior because the promise type 'std::experimental::coroutine_traits<int>::promise_type' (aka 'promise_int') does not declare 'return_void()'}} + +int test2a(bool b) { + if (b) + co_return 42; +} // expected-warning {{control may reach end of coroutine; which is undefined behavior because the promise type 'std::experimental::coroutine_traits<int, bool>::promise_type' (aka 'promise_int') does not declare 'return_void()'}} int test3() { co_await a; b: goto b; } + +int test4() { + co_return 42; +} + +void test5(int) { + co_await a; +} // expected-warning {{control reaches end of coroutine; which is undefined behavior because}} + +void test6(int x) { + if (x) + co_return 42; +} // expected-warning {{control may reach end of coroutine; which is undefined behavior because}} + +void test7(int y) { + if (y) + co_return 42; + else + co_return 101; +} + +VoidTagReturnVoid test8() { + co_await a; +} + +VoidTagReturnVoid test9(bool b) { + if (b) + co_return; +} + +VoidTagReturnValue test10() { + co_await a; +} // expected-warning {{control reaches end of coroutine}} + +VoidTagReturnValue test11(bool b) { + if (b) + co_return 42; +} // expected-warning {{control may reach end of coroutine}} diff --git a/test/SemaCXX/coroutine-seh.cpp b/test/SemaCXX/coroutine-seh.cpp new file mode 100644 index 0000000000000..647bb68b31857 --- /dev/null +++ b/test/SemaCXX/coroutine-seh.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -triple x86_64-windows-msvc -fms-extensions +namespace std::experimental { +template <typename... T> struct coroutine_traits; + +template <class Promise = void> struct coroutine_handle { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; +template <> struct coroutine_handle<void> { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template <class PromiseType> + coroutine_handle(coroutine_handle<PromiseType>) noexcept; +}; +} + +struct suspend_always { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +template <> struct std::experimental::coroutine_traits<void> { + struct promise_type { + void get_return_object() noexcept; + suspend_always initial_suspend() noexcept; + suspend_always final_suspend() noexcept; + void return_void() noexcept; + void unhandled_exception() noexcept; + }; +}; + +void SEH_used() { + __try { // expected-error {{cannot use SEH '__try' in a coroutine when C++ exceptions are enabled}} + co_return; // expected-note {{function is a coroutine due to use of 'co_return' here}} + } __except(0) {} +} diff --git a/test/SemaCXX/coroutine-unhandled_exception-warning.cpp b/test/SemaCXX/coroutine-unhandled_exception-warning.cpp index d7f6066109a5f..d819580462c8e 100644 --- a/test/SemaCXX/coroutine-unhandled_exception-warning.cpp +++ b/test/SemaCXX/coroutine-unhandled_exception-warning.cpp @@ -16,7 +16,11 @@ using std::experimental::suspend_always; using std::experimental::suspend_never; +#ifndef DISABLE_WARNING +struct promise_void { // expected-note {{defined here}} +#else struct promise_void { +#endif void get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); diff --git a/test/SemaCXX/coroutines.cpp b/test/SemaCXX/coroutines.cpp index 856110333d376..47ad86e5b02f8 100644 --- a/test/SemaCXX/coroutines.cpp +++ b/test/SemaCXX/coroutines.cpp @@ -347,6 +347,7 @@ namespace dependent_operator_co_await_lookup { ::adl_ns::coawait_arg_type final_suspend(); transformed await_transform(transform_awaitable); void unhandled_exception(); + void return_void(); }; template <class AwaitArg> struct basic_promise { @@ -355,6 +356,7 @@ namespace dependent_operator_co_await_lookup { awaitable initial_suspend(); awaitable final_suspend(); void unhandled_exception(); + void return_void(); }; awaitable operator co_await(await_arg_1); @@ -473,6 +475,7 @@ struct bad_promise_1 { suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception(); + void return_void(); }; coro<bad_promise_1> missing_get_return_object() { // expected-error {{no member named 'get_return_object' in 'bad_promise_1'}} co_await a; @@ -483,6 +486,7 @@ struct bad_promise_2 { // FIXME: We shouldn't offer a typo-correction here! suspend_always final_suspend(); // expected-note {{here}} void unhandled_exception(); + void return_void(); }; // FIXME: This shouldn't happen twice coro<bad_promise_2> missing_initial_suspend() { // expected-error {{no member named 'initial_suspend' in 'bad_promise_2'}} @@ -494,6 +498,7 @@ struct bad_promise_3 { // FIXME: We shouldn't offer a typo-correction here! suspend_always initial_suspend(); // expected-note {{here}} void unhandled_exception(); + void return_void(); }; coro<bad_promise_3> missing_final_suspend() { // expected-error {{no member named 'final_suspend' in 'bad_promise_3'}} co_await a; @@ -503,6 +508,7 @@ struct bad_promise_4 { coro<bad_promise_4> get_return_object(); not_awaitable initial_suspend(); suspend_always final_suspend(); + void return_void(); }; // FIXME: This diagnostic is terrible. coro<bad_promise_4> bad_initial_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} @@ -514,6 +520,7 @@ struct bad_promise_5 { coro<bad_promise_5> get_return_object(); suspend_always initial_suspend(); not_awaitable final_suspend(); + void return_void(); }; // FIXME: This diagnostic is terrible. coro<bad_promise_5> bad_final_suspend() { // expected-error {{no member named 'await_ready' in 'not_awaitable'}} @@ -526,8 +533,8 @@ struct bad_promise_6 { suspend_always initial_suspend(); suspend_always final_suspend(); void unhandled_exception(); - void return_void(); - void return_value(int) const; + void return_void(); // expected-note 2 {{member 'return_void' first declared here}} + void return_value(int) const; // expected-note 2 {{member 'return_value' first declared here}} void return_value(int); }; coro<bad_promise_6> bad_implicit_return() { // expected-error {{'bad_promise_6' declares both 'return_value' and 'return_void'}} @@ -540,7 +547,7 @@ coro<T> bad_implicit_return_dependent(T) { // expected-error {{'bad_promise_6' d } template coro<bad_promise_6> bad_implicit_return_dependent(bad_promise_6); // expected-note {{in instantiation}} -struct bad_promise_7 { +struct bad_promise_7 { // expected-note 2 {{defined here}} coro<bad_promise_7> get_return_object(); suspend_always initial_suspend(); suspend_always final_suspend(); @@ -746,3 +753,124 @@ coro<T> dependent_uses_nothrow_new(T) { co_return; } template coro<good_promise_13> dependent_uses_nothrow_new(good_promise_13); + +struct mismatch_gro_type_tag1 {}; +template<> +struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag1> { + struct promise_type { + void get_return_object() {} //expected-note {{member 'get_return_object' declared here}} + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + void unhandled_exception(); + }; +}; + +extern "C" int f(mismatch_gro_type_tag1) { + // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}} + co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} +} + +struct mismatch_gro_type_tag2 {}; +template<> +struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag2> { + struct promise_type { + void *get_return_object() {} //expected-note {{member 'get_return_object' declared here}} + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + void unhandled_exception(); + }; +}; + +extern "C" int f(mismatch_gro_type_tag2) { + // expected-error@-1 {{cannot initialize return object of type 'int' with an lvalue of type 'void *'}} + co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} +} + +struct mismatch_gro_type_tag3 {}; +template<> +struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag3> { + struct promise_type { + int get_return_object() {} + static void get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared here}} + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + void unhandled_exception(); + }; +}; + +extern "C" int f(mismatch_gro_type_tag3) { + // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'void'}} + co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} +} + + +struct mismatch_gro_type_tag4 {}; +template<> +struct std::experimental::coroutine_traits<int, mismatch_gro_type_tag4> { + struct promise_type { + int get_return_object() {} + static char *get_return_object_on_allocation_failure() {} //expected-note {{member 'get_return_object_on_allocation_failure' declared}} + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + void unhandled_exception(); + }; +}; + +extern "C" int f(mismatch_gro_type_tag4) { + // expected-error@-1 {{cannot initialize return object of type 'int' with an rvalue of type 'char *'}} + co_return; //expected-note {{function is a coroutine due to use of 'co_return' here}} +} + +struct bad_promise_no_return_func { // expected-note {{'bad_promise_no_return_func' defined here}} + coro<bad_promise_no_return_func> get_return_object(); + suspend_always initial_suspend(); + suspend_always final_suspend(); + void unhandled_exception(); +}; +// FIXME: The PDTS currently specifies this as UB, technically forbidding a +// diagnostic. +coro<bad_promise_no_return_func> no_return_value_or_return_void() { + // expected-error@-1 {{'bad_promise_no_return_func' must declare either 'return_value' or 'return_void'}} + co_await a; +} + +struct bad_await_suspend_return { + bool await_ready(); + // expected-error@+1 {{the return type of 'await_suspend' is required to be 'void' or 'bool' (have 'char')}} + char await_suspend(std::experimental::coroutine_handle<>); + void await_resume(); +}; +struct bad_await_ready_return { + // expected-note@+1 {{the return type of 'await_ready' is required to be contextually convertible to 'bool'}} + void await_ready(); + bool await_suspend(std::experimental::coroutine_handle<>); + void await_resume(); +}; +struct await_ready_explicit_bool { + struct BoolT { + explicit operator bool() const; + }; + BoolT await_ready(); + void await_suspend(std::experimental::coroutine_handle<>); + void await_resume(); +}; +void test_bad_suspend() { + { + // FIXME: The actual error emitted here is terrible, and no number of notes can save it. + bad_await_ready_return a; + // expected-error@+1 {{value of type 'void' is not contextually convertible to 'bool'}} + co_await a; // expected-note {{call to 'await_ready' implicitly required by coroutine function here}} + } + { + bad_await_suspend_return b; + co_await b; // expected-note {{call to 'await_suspend' implicitly required by coroutine function here}} + } + { + await_ready_explicit_bool c; + co_await c; // OK + } +} diff --git a/test/SemaCXX/default-assignment-operator.cpp b/test/SemaCXX/default-assignment-operator.cpp index 80ceb3768d9ed..57cb77d6cb461 100644 --- a/test/SemaCXX/default-assignment-operator.cpp +++ b/test/SemaCXX/default-assignment-operator.cpp @@ -48,7 +48,7 @@ Z z2; void f(X x, const X cx) { x = cx; #if __cplusplus <= 199711L - // expected-note@-2 {{assignment operator for 'X' first required here}} + // expected-note@-2 2{{assignment operator for 'X' first required here}} #else // expected-error@-4 {{object of type 'X' cannot be assigned because its copy assignment operator is implicitly deleted}} #endif diff --git a/test/SemaCXX/deprecated.cpp b/test/SemaCXX/deprecated.cpp index 0fd275e2cec64..ac477d4b66bc6 100644 --- a/test/SemaCXX/deprecated.cpp +++ b/test/SemaCXX/deprecated.cpp @@ -75,21 +75,21 @@ namespace DeprecatedCopy { struct Assign { Assign &operator=(const Assign&); // expected-warning {{definition of implicit copy constructor for 'Assign' is deprecated because it has a user-declared copy assignment operator}} }; - Assign a1, a2(a1); // expected-note {{implicit copy constructor for 'Assign' first required here}} + Assign a1, a2(a1); // expected-note {{implicit copy constructor for 'DeprecatedCopy::Assign' first required here}} struct Ctor { Ctor(); Ctor(const Ctor&); // expected-warning {{definition of implicit copy assignment operator for 'Ctor' is deprecated because it has a user-declared copy constructor}} }; Ctor b1, b2; - void f() { b1 = b2; } // expected-note {{implicit copy assignment operator for 'Ctor' first required here}} + void f() { b1 = b2; } // expected-note {{implicit copy assignment operator for 'DeprecatedCopy::Ctor' first required here}} struct Dtor { ~Dtor(); // expected-warning@-1 {{definition of implicit copy constructor for 'Dtor' is deprecated because it has a user-declared destructor}} // expected-warning@-2 {{definition of implicit copy assignment operator for 'Dtor' is deprecated because it has a user-declared destructor}} }; - Dtor c1, c2(c1); // expected-note {{implicit copy constructor for 'Dtor' first required here}} - void g() { c1 = c2; } // expected-note {{implicit copy assignment operator for 'Dtor' first required here}} + Dtor c1, c2(c1); // expected-note {{implicit copy constructor for 'DeprecatedCopy::Dtor' first required here}} + void g() { c1 = c2; } // expected-note {{implicit copy assignment operator for 'DeprecatedCopy::Dtor' first required here}} } #endif diff --git a/test/SemaCXX/null-cast.cpp b/test/SemaCXX/null-cast.cpp new file mode 100644 index 0000000000000..c80ab8fced1e0 --- /dev/null +++ b/test/SemaCXX/null-cast.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct A {}; +struct B : virtual A {}; + +void foo() { + (void)static_cast<A&>(*(B *)0); // expected-warning {{binding dereferenced null pointer to reference has undefined behavior}} +} diff --git a/test/SemaCXX/uninitialized.cpp b/test/SemaCXX/uninitialized.cpp index e4928b8566c69..92f1c1472caf5 100644 --- a/test/SemaCXX/uninitialized.cpp +++ b/test/SemaCXX/uninitialized.cpp @@ -955,7 +955,7 @@ namespace record_fields { A a13 = rref(std::move(a13)); // expected-warning {{uninitialized}} A a14 = std::move(x ? a13 : (22, a14)); // expected-warning {{uninitialized}} }; - D d; + D d; // expected-note {{in implicit default constructor for 'record_fields::D' first required here}} struct E { A a1 = a1; A a2 = a2.get(); diff --git a/test/SemaCXX/virtual-base-used.cpp b/test/SemaCXX/virtual-base-used.cpp index f0dcc969e8da0..583923b927d01 100644 --- a/test/SemaCXX/virtual-base-used.cpp +++ b/test/SemaCXX/virtual-base-used.cpp @@ -65,7 +65,7 @@ struct D : public virtual B { #ifdef MSABI D d; #if __cplusplus <= 199711L -// expected-note@-2 {{implicit default constructor for 'D' first required here}} +// expected-note@-2 2{{implicit default constructor for 'D' first required here}} #else // expected-error@-4 {{call to implicitly-deleted default constructor of 'D'}} #endif @@ -118,8 +118,9 @@ struct G : public virtual F { #ifdef MSABI #if __cplusplus <= 199711L // expected-note@-3 {{implicit default constructor for 'F' first required here}} +// expected-note@-4 {{implicit destructor for 'F' first required here}} #else -// expected-note@-5 {{default constructor of 'G' is implicitly deleted because base class 'F' has a deleted default constructor}} +// expected-note@-6 {{default constructor of 'G' is implicitly deleted because base class 'F' has a deleted default constructor}} #endif #endif @@ -133,7 +134,7 @@ struct G : public virtual F { #ifdef MSABI G g; #if __cplusplus <= 199711L -// expected-note@-2 {{implicit default constructor for 'G' first required here}} +// expected-note@-2 2{{implicit default constructor for 'G' first required here}} #else // expected-error@-4 {{call to implicitly-deleted default constructor of 'G'}} #endif @@ -149,10 +150,6 @@ struct H : public virtual A { #if __cplusplus >= 201103L // expected-error@-2 {{deleted function '~H' cannot override a non-deleted function}} // expected-note@-3 {{overridden virtual function is here}} -#else -#ifdef MSABI -// expected-note@-6 {{'H' declared here}} -#endif #endif NoDestroy x; @@ -171,11 +168,8 @@ struct H : public virtual A { struct I : public virtual H { #ifdef MSABI -#if __cplusplus <= 199711L -// expected-error@-3 {{implicit default constructor for 'I' must explicitly initialize the base class 'H' which does not have a default constructor}} -// expected-note@-4 {{implicit destructor for 'H' first required here}} -#else -// expected-note@-6 {{default constructor of 'I' is implicitly deleted because base class 'H' has a deleted default constructor}} +#if __cplusplus > 199711L +// expected-note@-3 {{default constructor of 'I' is implicitly deleted because base class 'H' has a deleted default constructor}} #endif #endif @@ -189,7 +183,7 @@ struct J : public I { #ifdef MSABI #if __cplusplus <= 199711L // expected-note@-3 {{implicit default constructor for 'H' first required here}} -// expected-note@-4 {{implicit default constructor for 'I' first required here}} +// expected-note@-4 {{implicit destructor for 'H' first required here}} #else // expected-note@-6 {{default constructor of 'J' is implicitly deleted because base class 'I' has a deleted default constructor}} #endif @@ -202,7 +196,7 @@ struct J : public I { #ifdef MSABI J j; #if __cplusplus <= 199711L -// expected-note@-2 {{implicit default constructor for 'J' first required here}} +// expected-note@-2 2{{implicit default constructor for 'J' first required here}} #else // expected-error@-4 {{call to implicitly-deleted default constructor of 'J'}} #endif |