summaryrefslogtreecommitdiff
path: root/test/SemaCXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX')
-rw-r--r--test/SemaCXX/co_await-range-for.cpp165
-rw-r--r--test/SemaCXX/cxx1z-decomposition.cpp6
-rw-r--r--test/SemaCXX/nested-name-spec.cpp7
-rw-r--r--test/SemaCXX/warn-unused-lambda-capture.cpp5
4 files changed, 183 insertions, 0 deletions
diff --git a/test/SemaCXX/co_await-range-for.cpp b/test/SemaCXX/co_await-range-for.cpp
new file mode 100644
index 000000000000..4d999ea7db5e
--- /dev/null
+++ b/test/SemaCXX/co_await-range-for.cpp
@@ -0,0 +1,165 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin9 %s -std=c++14 -fcoroutines-ts \
+// RUN: -fsyntax-only -Wignored-qualifiers -Wno-error=return-type -verify \
+// RUN: -fblocks
+#include "Inputs/std-coroutine.h"
+
+using namespace std::experimental;
+
+
+template <class Begin>
+struct Awaiter {
+ bool await_ready();
+ void await_suspend(coroutine_handle<>);
+ Begin await_resume();
+};
+
+template <class Iter> struct BeginTag { BeginTag() = delete; };
+template <class Iter> struct IncTag { IncTag() = delete; };
+
+template <class Iter, bool Delete = false>
+struct CoawaitTag { CoawaitTag() = delete; };
+
+template <class T>
+struct Iter {
+ using value_type = T;
+ using reference = T &;
+ using pointer = T *;
+
+ IncTag<Iter> operator++();
+ reference operator*();
+ pointer operator->();
+};
+template <class T> bool operator==(Iter<T>, Iter<T>);
+template <class T> bool operator!=(Iter<T>, Iter<T>);
+
+template <class T>
+struct Range {
+ BeginTag<Iter<T>> begin();
+ Iter<T> end();
+};
+
+struct MyForLoopArrayAwaiter {
+ struct promise_type {
+ MyForLoopArrayAwaiter get_return_object() { return {}; }
+ void return_void();
+ void unhandled_exception();
+ suspend_never initial_suspend();
+ suspend_never final_suspend();
+ template <class T>
+ Awaiter<T *> await_transform(T *) = delete; // expected-note {{explicitly deleted}}
+ };
+};
+MyForLoopArrayAwaiter g() {
+ int arr[10] = {0};
+ for co_await(auto i : arr) {}
+ // expected-error@-1 {{call to deleted member function 'await_transform'}}
+ // expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
+}
+
+struct ForLoopAwaiterBadBeginTransform {
+ struct promise_type {
+ ForLoopAwaiterBadBeginTransform get_return_object();
+ void return_void();
+ void unhandled_exception();
+ suspend_never initial_suspend();
+ suspend_never final_suspend();
+
+ template <class T>
+ Awaiter<T> await_transform(BeginTag<T>) = delete; // expected-note 1+ {{explicitly deleted}}
+
+ template <class T>
+ CoawaitTag<T> await_transform(IncTag<T>); // expected-note 1+ {{candidate}}
+ };
+};
+ForLoopAwaiterBadBeginTransform bad_begin() {
+ Range<int> R;
+ for co_await(auto i : R) {}
+ // expected-error@-1 {{call to deleted member function 'await_transform'}}
+ // expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
+}
+template <class Dummy>
+ForLoopAwaiterBadBeginTransform bad_begin_template(Dummy) {
+ Range<Dummy> R;
+ for co_await(auto i : R) {}
+ // expected-error@-1 {{call to deleted member function 'await_transform'}}
+ // expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
+}
+template ForLoopAwaiterBadBeginTransform bad_begin_template(int); // expected-note {{requested here}}
+
+template <class Iter>
+Awaiter<Iter> operator co_await(CoawaitTag<Iter, true>) = delete;
+// expected-note@-1 1+ {{explicitly deleted}}
+
+struct ForLoopAwaiterBadIncTransform {
+ struct promise_type {
+ ForLoopAwaiterBadIncTransform get_return_object();
+ void return_void();
+ void unhandled_exception();
+ suspend_never initial_suspend();
+ suspend_never final_suspend();
+
+ template <class T>
+ Awaiter<T> await_transform(BeginTag<T> e);
+
+ template <class T>
+ CoawaitTag<T, true> await_transform(IncTag<T>);
+ };
+};
+ForLoopAwaiterBadIncTransform bad_inc_transform() {
+ Range<float> R;
+ for co_await(auto i : R) {}
+ // expected-error@-1 {{overload resolution selected deleted operator 'co_await'}}
+ // expected-note@-2 {{in implicit call to 'operator++' for iterator of type 'Range<float>'}}
+}
+
+template <class Dummy>
+ForLoopAwaiterBadIncTransform bad_inc_transform_template(Dummy) {
+ Range<Dummy> R;
+ for co_await(auto i : R) {}
+ // expected-error@-1 {{overload resolution selected deleted operator 'co_await'}}
+ // expected-note@-2 {{in implicit call to 'operator++' for iterator of type 'Range<long>'}}
+}
+template ForLoopAwaiterBadIncTransform bad_inc_transform_template(long); // expected-note {{requested here}}
+
+// Ensure we mark and check the function as a coroutine even if it's
+// never instantiated.
+template <class T>
+constexpr void never_instant(T) {
+ static_assert(sizeof(T) != sizeof(T), "function should not be instantiated");
+ for co_await(auto i : foo(T{})) {}
+ // expected-error@-1 {{'co_await' cannot be used in a constexpr function}}
+}
+
+namespace NS {
+struct ForLoopAwaiterCoawaitLookup {
+ struct promise_type {
+ ForLoopAwaiterCoawaitLookup get_return_object();
+ void return_void();
+ void unhandled_exception();
+ suspend_never initial_suspend();
+ suspend_never final_suspend();
+ template <class T>
+ CoawaitTag<T, false> await_transform(BeginTag<T> e);
+ template <class T>
+ Awaiter<T> await_transform(IncTag<T>);
+ };
+};
+} // namespace NS
+using NS::ForLoopAwaiterCoawaitLookup;
+
+template <class T>
+ForLoopAwaiterCoawaitLookup test_coawait_lookup(T) {
+ Range<T> R;
+ for co_await(auto i : R) {}
+ // expected-error@-1 {{no member named 'await_ready' in 'CoawaitTag<Iter<int>, false>'}}
+}
+template ForLoopAwaiterCoawaitLookup test_coawait_lookup(int); // expected-note {{requested here}}
+
+// FIXME: This test should fail as well since the newly declared operator co_await
+// should not be found by lookup.
+namespace NS2 {
+template <class Iter>
+Awaiter<Iter> operator co_await(CoawaitTag<Iter, false>);
+}
+using NS2::operator co_await;
+template ForLoopAwaiterCoawaitLookup test_coawait_lookup(long);
diff --git a/test/SemaCXX/cxx1z-decomposition.cpp b/test/SemaCXX/cxx1z-decomposition.cpp
index d457ace5d844..7a4221784ad3 100644
--- a/test/SemaCXX/cxx1z-decomposition.cpp
+++ b/test/SemaCXX/cxx1z-decomposition.cpp
@@ -70,4 +70,10 @@ int error_recovery() {
return foobar_; // expected-error {{undeclared identifier 'foobar_'}}
}
+// PR32172
+template <class T> void dependent_foreach(T t) {
+ for (auto [a,b,c] : t)
+ a,b,c;
+}
+
// FIXME: by-value array copies
diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp
index 6ae45ff63332..725ac64cedb7 100644
--- a/test/SemaCXX/nested-name-spec.cpp
+++ b/test/SemaCXX/nested-name-spec.cpp
@@ -169,6 +169,13 @@ void N::f() { } // okay
struct Y; // expected-note{{forward declaration of 'Y'}}
Y::foo y; // expected-error{{incomplete type 'Y' named in nested name specifier}}
+namespace PR25156 {
+struct Y; // expected-note{{forward declaration of 'PR25156::Y'}}
+void foo() {
+ Y::~Y(); // expected-error{{incomplete type 'PR25156::Y' named in nested name specifier}}
+}
+}
+
X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}}
struct foo_S {
diff --git a/test/SemaCXX/warn-unused-lambda-capture.cpp b/test/SemaCXX/warn-unused-lambda-capture.cpp
index 48f8bfea7e9a..6ad8e26604a4 100644
--- a/test/SemaCXX/warn-unused-lambda-capture.cpp
+++ b/test/SemaCXX/warn-unused-lambda-capture.cpp
@@ -142,11 +142,14 @@ void test_templated() {
auto implicit_by_reference = [&] { i++; };
auto explicit_by_value_used = [i] { return i + 1; };
+ auto explicit_by_value_used_generic = [i](auto c) { return i + 1; };
auto explicit_by_value_used_void = [i] { (void)i; };
+
auto explicit_by_value_unused = [i] {}; // expected-warning{{lambda capture 'i' is not used}}
auto explicit_by_value_unused_sizeof = [i] { return sizeof(i); }; // expected-warning{{lambda capture 'i' is not required to be captured for this use}}
auto explicit_by_value_unused_decltype = [i] { decltype(i) j = 0; }; // expected-warning{{lambda capture 'i' is not used}}
auto explicit_by_value_unused_const = [k] { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
+ auto explicit_by_value_unused_const_generic = [k](auto c) { return k + 1; }; // expected-warning{{lambda capture 'k' is not required to be captured for this use}}
auto explicit_by_reference_used = [&i] { i++; };
auto explicit_by_reference_unused = [&i] {}; // expected-warning{{lambda capture 'i' is not used}}
@@ -161,6 +164,8 @@ void test_templated() {
auto explicit_initialized_value_trivial_init = [j = Trivial()]{}; // expected-warning{{lambda capture 'j' is not used}}
auto explicit_initialized_value_non_trivial_init = [j = Trivial(42)]{};
auto explicit_initialized_value_with_side_effect = [j = side_effect()]{};
+ auto explicit_initialized_value_generic_used = [i = 1](auto c) mutable { i++; };
+ auto explicit_initialized_value_generic_unused = [i = 1](auto c) mutable {}; // expected-warning{{lambda capture 'i' is not used}}
auto nested = [&i] {
auto explicit_by_value_used = [i] { return i + 1; };