aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2022-04-18 09:21:52 +0100
committerIain Sandoe <iain@sandoe.co.uk>2022-04-28 13:52:23 +0100
commit6cae3bb65c873a2191613f7888fe949553a21f9e (patch)
tree57fc31ddc4712f710143fc12674510239e551fd2
parent15a176a833f23e64ad38690a678bf938227ce46f (diff)
downloadgcc-6cae3bb65c873a2191613f7888fe949553a21f9e.zip
gcc-6cae3bb65c873a2191613f7888fe949553a21f9e.tar.gz
gcc-6cae3bb65c873a2191613f7888fe949553a21f9e.tar.bz2
c++, coroutines: Account for overloaded promise return_value() [PR105301].
Whether it was intended or not, it is possible to define a coroutine promise with multiple return_value() methods [which need not even have the same type]. We were not accounting for this possibility in the check to see whether both return_value and return_void are specifier (which is prohibited by the standard). Fixed thus and provided an adjusted diagnostic for the case that multiple return_value() methods are present. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR c++/105301 gcc/cp/ChangeLog: * coroutines.cc (coro_promise_type_found_p): Account for possible mutliple overloads of the promise return_value() method. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr105301.C: New test.
-rw-r--r--gcc/cp/coroutines.cc10
-rw-r--r--gcc/testsuite/g++.dg/coroutines/pr105301.C49
2 files changed, 57 insertions, 2 deletions
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 9b651b8..7f23776 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -513,8 +513,14 @@ coro_promise_type_found_p (tree fndecl, location_t loc)
coro_info->promise_type);
inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void)),
"%<return_void%> declared here");
- inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_val)),
- "%<return_value%> declared here");
+ has_ret_val = BASELINK_FUNCTIONS (has_ret_val);
+ const char *message = "%<return_value%> declared here";
+ if (TREE_CODE (has_ret_val) == OVERLOAD)
+ {
+ has_ret_val = OVL_FIRST (has_ret_val);
+ message = "%<return_value%> first declared here";
+ }
+ inform (DECL_SOURCE_LOCATION (has_ret_val), message);
coro_info->coro_co_return_error_emitted = true;
return false;
}
diff --git a/gcc/testsuite/g++.dg/coroutines/pr105301.C b/gcc/testsuite/g++.dg/coroutines/pr105301.C
new file mode 100644
index 0000000..33a0b03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr105301.C
@@ -0,0 +1,49 @@
+// { dg-additional-options "-fsyntax-only" }
+namespace std {
+template <class T, class = void>
+struct traits_sfinae_base {};
+
+template <class Ret, class... Args>
+struct coroutine_traits : public traits_sfinae_base<Ret> {};
+}
+
+template<typename Promise> struct coro {};
+template <typename Promise, typename... Ps>
+struct std::coroutine_traits<coro<Promise>, Ps...> {
+ using promise_type = Promise;
+};
+
+struct awaitable {
+ bool await_ready() noexcept;
+ template <typename F>
+ void await_suspend(F) noexcept;
+ void await_resume() noexcept;
+} a;
+
+struct suspend_always {
+ bool await_ready() noexcept { return false; }
+ template <typename F>
+ void await_suspend(F) noexcept;
+ void await_resume() noexcept {}
+};
+
+namespace std {
+template <class PromiseType = void>
+struct coroutine_handle {};
+}
+
+struct bad_promise_6 {
+ coro<bad_promise_6> get_return_object();
+ suspend_always initial_suspend();
+ suspend_always final_suspend() noexcept;
+ void unhandled_exception();
+ void return_void();
+ void return_value(int) const;
+ void return_value(int);
+};
+
+coro<bad_promise_6>
+bad_implicit_return() // { dg-error {.aka 'bad_promise_6'. declares both 'return_value' and 'return_void'} }
+{
+ co_await a;
+}