Hi Jason,

This replaces "c-lex: Handle NULL filenames from UNKNOWN_LOCATION" as
we discussed off-list, you prefer a solution that has valid locations
during the synthesis.  I have reverted to using the function location
for code that represents start-up and the closing brace for code that
represents shut-down.  Note that we do not have (and cannot easily get)
the position of the opening brace.

Tested on x86_64 darwin and powerpc64le linux, OK for trunk?
thanks
Iain

--- 8< ---


Some of the lookup code is expecting to find a valid (not UNKNOWN)
location, which triggers in the reported case.  To avoid this, we are
reverting the change to use UNKNOWN_LOCATION for synthesizing the
wrapper, and instead using the start and end locations of the original
function.

        PR c++/120273

gcc/cp/ChangeLog:

        * coroutines.cc
        (cp_coroutine_transform::wrap_original_function_body): Use
        function start and end locations when synthesizing code.
        (cp_coroutine_transform::cp_coroutine_transform): Set the
        function end location.
        * coroutines.h: Add the function end location.

gcc/testsuite/ChangeLog:

        * g++.dg/coroutines/coro-missing-final-suspend.C: Adjust for
        changed final suspend diagnostics line number change.
        * g++.dg/coroutines/coro1-missing-await-method.C: Likewise.
        * g++.dg/coroutines/pr104051.C: Likewise.
        * g++.dg/coroutines/pr120273.C: New test.

Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
---
 gcc/cp/coroutines.cc                          | 18 +++---
 gcc/cp/coroutines.h                           |  1 +
 .../coroutines/coro-missing-final-suspend.C   |  4 +-
 .../coroutines/coro1-missing-await-method.C   |  2 +-
 gcc/testsuite/g++.dg/coroutines/pr104051.C    |  4 +-
 gcc/testsuite/g++.dg/coroutines/pr120273.C    | 58 +++++++++++++++++++
 6 files changed, 75 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr120273.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 97eee6e8ea4..d482f52fefa 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4281,8 +4281,7 @@ cp_coroutine_transform::wrap_original_function_body ()
 {
   /* Avoid the code here attaching a location that makes the debugger jump.  */
   iloc_sentinel stable_input_loc (fn_start);
-  location_t loc = UNKNOWN_LOCATION;
-  input_location = loc;
+  location_t loc = fn_start;
 
   /* This will be our new outer scope.  */
   tree update_body
@@ -4513,18 +4512,22 @@ cp_coroutine_transform::wrap_original_function_body ()
        add_stmt (return_void);
     }
 
+  /* We are now doing actions associated with the end of the function, so
+     point to the closing brace.  */
+  input_location = fn_end;
+
   /* co_return branches to the final_suspend label, so declare that now.  */
   fs_label
     = create_named_label_with_ctx (loc, "final.suspend", NULL_TREE);
-  add_stmt (build_stmt (loc, LABEL_EXPR, fs_label));
+  add_stmt (build_stmt (fn_end, LABEL_EXPR, fs_label));
 
   /* Before entering the final suspend point, we signal that this point has
      been reached by setting the resume function pointer to zero (this is
      what the 'done()' builtin tests) as per the current ABI.  */
-  zero_resume = build2_loc (loc, MODIFY_EXPR, act_des_fn_ptr_type,
+  zero_resume = build2_loc (fn_end, MODIFY_EXPR, act_des_fn_ptr_type,
                            resume_fn_ptr, zero_resume);
   finish_expr_stmt (zero_resume);
-  finish_expr_stmt (build_init_or_final_await (fn_start, true));
+  finish_expr_stmt (build_init_or_final_await (fn_end, true));
   BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
   BIND_EXPR_VARS (update_body) = nreverse (var_list);
   BLOCK_VARS (top_block) = BIND_EXPR_VARS (update_body);
@@ -5181,9 +5184,10 @@ cp_coroutine_transform::cp_coroutine_transform (tree 
_orig_fn, bool _inl)
       }
 
     /* We don't have the locus of the opening brace - it's filled in later (and
-       there doesn't really seem to be any easy way to get at it).
-       The closing brace is assumed to be input_location.  */
+       there doesn't really seem to be any easy way to get at it).  */
     fn_start = DECL_SOURCE_LOCATION (orig_fn_decl);
+    /* The closing brace is assumed to be input_location.  */
+    fn_end = input_location;
 
     /* Build types we need.  */
     tree fr_name = get_fn_local_identifier (orig_fn_decl, "Frame");
diff --git a/gcc/cp/coroutines.h b/gcc/cp/coroutines.h
index 55caa6e61e3..cb5d5572733 100644
--- a/gcc/cp/coroutines.h
+++ b/gcc/cp/coroutines.h
@@ -102,6 +102,7 @@ private:
   tree orig_fn_decl;            /* The original function decl.  */
   tree orig_fn_body = NULL_TREE; /* The original function body.  */
   location_t fn_start = UNKNOWN_LOCATION;
+  location_t fn_end = UNKNOWN_LOCATION;
   tree resumer = error_mark_node;
   tree destroyer = error_mark_node;
   tree coroutine_body = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-missing-final-suspend.C 
b/gcc/testsuite/g++.dg/coroutines/coro-missing-final-suspend.C
index 6a0878c1269..b2522311a49 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro-missing-final-suspend.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro-missing-final-suspend.C
@@ -7,10 +7,10 @@
 #include "coro1-ret-int-yield-int.h"
 
 coro1
-my_coro () // { dg-error {no member named 'final_suspend' in} }
+my_coro ()
 {
   co_return 0;
-}
+} // { dg-error {no member named 'final_suspend' in} }
 
 // check we have not messed up continuation of the compilation.
 template <class... Args>
diff --git a/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C 
b/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C
index c1869e0654c..93b6159216f 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C
@@ -13,7 +13,7 @@ bar0 () // { dg-error {no member named 'await_suspend' in 
'coro1::suspend_always
   co_yield 5; // { dg-error {no member named 'await_suspend' in 
'coro1::suspend_always_prt'} }
   co_await coro1::suspend_always_intprt(5); // { dg-error {no member named 
'await_resume' in 'coro1::suspend_always_intprt'} }
   co_return 0;
-}
+} // { dg-error {no member named 'await_suspend' in 
'coro1::suspend_always_prt'} }
 
 int main (int ac, char *av[]) {
   struct coro1 x0 = bar0 ();
diff --git a/gcc/testsuite/g++.dg/coroutines/pr104051.C 
b/gcc/testsuite/g++.dg/coroutines/pr104051.C
index f77a915af74..cd69877361d 100644
--- a/gcc/testsuite/g++.dg/coroutines/pr104051.C
+++ b/gcc/testsuite/g++.dg/coroutines/pr104051.C
@@ -24,7 +24,7 @@ template <typename T> struct task {
   std::coroutine_handle<> await_suspend(std::coroutine_handle<>);
   T await_resume();
 };
-task<std::vector<int>> foo() { // { dg-error {awaitable type 'bool' is not a 
structure} }
+task<std::vector<int>> foo() {
   while ((co_await foo()).empty())
     ;
-}
+} // { dg-error {awaitable type 'bool' is not a structure} }
diff --git a/gcc/testsuite/g++.dg/coroutines/pr120273.C 
b/gcc/testsuite/g++.dg/coroutines/pr120273.C
new file mode 100644
index 00000000000..19b9e51b9fa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/pr120273.C
@@ -0,0 +1,58 @@
+// PR120273
+// { dg-additional-options "-Wno-literal-suffix" }
+namespace std {
+void declval();
+template < typename > struct invoke_result;
+template < typename _Fn > using invoke_result_t = invoke_result< _Fn >;
+template < typename _Derived, typename _Base >
+concept derived_from = __is_base_of(_Base, _Derived);
+template < typename, typename >
+concept convertible_to = requires { declval; };
+template < char... > int operator""ms();
+template < typename _Result, typename > struct coroutine_traits : _Result {};
+template < typename = void > struct coroutine_handle {
+  static coroutine_handle from_address(void *);
+  operator coroutine_handle<>();
+  void *address();
+};
+}
+
+using namespace std;
+
+template < class > using CoroutineHandle = coroutine_handle<>;
+
+template < class Callable >
+  requires(derived_from< invoke_result_t< Callable >, int >)
+Callable operator co_await(Callable);
+
+struct FinalSuspendProxy {
+  bool await_ready() noexcept;
+  void await_suspend(CoroutineHandle< void >) noexcept ;
+  void await_resume() noexcept;
+};
+
+struct Task {
+  struct Promise;
+  using promise_type = Promise;
+
+  struct Promise {
+    auto initial_suspend() { return FinalSuspendProxy(); }
+    auto final_suspend () noexcept  { return FinalSuspendProxy(); }
+    void unhandled_exception () {}
+    Task get_return_object () { return {}; }
+  };
+} ;
+
+struct TestEventLoop {
+  struct Sleep {
+    Sleep(TestEventLoop, int);
+    bool await_ready();
+    void await_suspend(CoroutineHandle< void >);
+    void await_resume();
+  };
+  auto sleep(int tm) { return Sleep(*this, tm); }
+};
+
+Task test_body_11(TestEventLoop t) {
+  co_await t.sleep(5ms);
+}
-- 
2.39.2 (Apple Git-143)

Reply via email to