diff options
Diffstat (limited to 'test/SemaCXX')
-rw-r--r-- | test/SemaCXX/co_await-range-for.cpp | 165 | ||||
-rw-r--r-- | test/SemaCXX/cxx1z-decomposition.cpp | 6 | ||||
-rw-r--r-- | test/SemaCXX/nested-name-spec.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/warn-unused-lambda-capture.cpp | 5 |
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; }; |