Hi Jason,

>>+     point to the closing brace.  */
>>+  input_location = fn_end;

>If we're going to have the loc variable at all, how about adjusting it here...

Done.

>>                          resume_fn_ptr, zero_resume);

>...so you don't need to change these uses...

>>   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));

>...and use it here as well.

Done here too - now adjusted to use 'loc' consistently.  We still have
to reset input_location, because of other code that might refer to it
directly.
OK for trunk now?
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                          | 22 ++++---
 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, 77 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/pr120273.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 1fbdee1b4f6..6518e9202d0 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -4307,8 +4307,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
@@ -4450,7 +4449,7 @@ cp_coroutine_transform::wrap_original_function_body ()
 
   /* If the coroutine has a frame that needs to be freed, this will be set by
      the ramp.  */
-  var = coro_build_artificial_var (fn_start, coro_frame_needs_free_id,
+  var = coro_build_artificial_var (loc, coro_frame_needs_free_id,
                                   boolean_type_node, orig_fn_decl, NULL_TREE);
   DECL_CHAIN (var) = var_list;
   var_list = var;
@@ -4462,7 +4461,7 @@ cp_coroutine_transform::wrap_original_function_body ()
       tree ueh
        = coro_build_promise_expression (orig_fn_decl, promise,
                                         coro_unhandled_exception_identifier,
-                                        fn_start, NULL, /*musthave=*/true);
+                                        loc, NULL, /*musthave=*/true);
       /* Create and initialize the initial-await-resume-called variable per
         [dcl.fct.def.coroutine] / 5.3.  */
       tree i_a_r_c
@@ -4524,9 +4523,9 @@ cp_coroutine_transform::wrap_original_function_body ()
          tree ueh_meth
            = lookup_promise_method (orig_fn_decl,
                                     coro_unhandled_exception_identifier,
-                                    fn_start, /*musthave=*/false);
+                                    loc, /*musthave=*/false);
          if (!ueh_meth || ueh_meth == error_mark_node)
-           warning_at (fn_start, 0, "no member named %qE in %qT",
+           warning_at (loc, 0, "no member named %qE in %qT",
                        coro_unhandled_exception_identifier,
                        get_coroutine_promise_type (orig_fn_decl));
        }
@@ -4539,6 +4538,10 @@ 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 = loc = 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);
@@ -4550,7 +4553,7 @@ cp_coroutine_transform::wrap_original_function_body ()
   zero_resume = build2_loc (loc, 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 (loc, 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);
@@ -5207,9 +5210,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