summaryrefslogtreecommitdiff
path: root/test/SemaCXX
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-29 16:25:46 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-29 16:25:46 +0000
commitb5aee35cc5d62f11d98539f62e4fe63f0ac9edc6 (patch)
tree3e6ab962dbc73cfe1445a60d2eb4dfba7c939a22 /test/SemaCXX
parentaa803409c3bd3930126db630c29f63d42f255153 (diff)
Notes
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/coreturn.cpp89
-rw-r--r--test/SemaCXX/coroutine-seh.cpp37
-rw-r--r--test/SemaCXX/coroutine-unhandled_exception-warning.cpp4
-rw-r--r--test/SemaCXX/coroutines.cpp134
-rw-r--r--test/SemaCXX/default-assignment-operator.cpp2
-rw-r--r--test/SemaCXX/deprecated.cpp8
-rw-r--r--test/SemaCXX/null-cast.cpp8
-rw-r--r--test/SemaCXX/uninitialized.cpp2
-rw-r--r--test/SemaCXX/virtual-base-used.cpp22
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