> On 3 Jun 2025, at 17:03, Jason Merrill <ja...@redhat.com> wrote:
> 
> On 5/29/25 8:29 AM, Iain Sandoe wrote:
>> To trigger this involves somewhat tortuous pathways through the
>> c++ requires code.  I did consider the alternative of putting in
>> an assert and then checking every call-site, but that seemed to
>> be a much larger change.
>> tested on x86_64-darwin and powerpc64le-linux, OK for trunk?
>> thanks
>> Iain
>> --- 8< ---
>> This was reported against the coroutines implementation, but could
>> affect other code.
>> We intentionally synthesize code with UNKNOWN_LOCATIONs in the
>> implementation to avoid the effect of the code position jumping
>> around in debug sessions.
> 
> It seems like we're doing that too broadly if it means we get classes with no 
> location.

Not 100% sure what you mean here;
We are only synthesizing the extra code specified in the std. with 
UKNOWN_LOCATION, the user-defined awaiters (and the user’s function body) etc 
would have their actual locations.

>  Here we're building the initial co_await, which seems like it should have 
> the location of the open brace of the function?

Unfortunately, we do not have the location of the open brace, that gets set 
after finish_function, but we do have the function location.

I did originally associate the startup code with the function location and the 
shutdown code with ‘input_location’ which is at the closing brace when we reach 
finish_function, so we could return to that mechanism, if preferred ( I am not 
sure how serious the unstable debug locations is when in code that has no 
source equivalent ).

Iain


>> The location expansion of fileinfo is not expecting to deal with
>> NULL name pointers.  The patch here checks this case and adds a
>> "<unknown file>" as the name, avoiding the ICE and providing at
>> least a basic indication to the end-user.
>>      PR c++/120273
>> gcc/c-family/ChangeLog:
>>      * c-lex.cc (get_fileinfo): When presented with a NULL
>>      name pointer, report "<unknown file>".
>> gcc/testsuite/ChangeLog:
>>      * g++.dg/coroutines/pr120273.C: New test.
>> Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>
>> ---
>>  gcc/c-family/c-lex.cc                      |  4 ++
>>  gcc/testsuite/g++.dg/coroutines/pr120273.C | 58 ++++++++++++++++++++++
>>  2 files changed, 62 insertions(+)
>>  create mode 100644 gcc/testsuite/g++.dg/coroutines/pr120273.C
>> diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc
>> index fef6ae6f457..43054f105ea 100644
>> --- a/gcc/c-family/c-lex.cc
>> +++ b/gcc/c-family/c-lex.cc
>> @@ -109,6 +109,10 @@ get_fileinfo (const char *name)
>>                                   0,
>>                                   splay_tree_delete_pointers);
>>  +  /* If we have an UNKOWN_LOCATION, it has no filename.  */
>> +  if (!name)
>> +    name = "<unknown file>";
>> +
>>    n = splay_tree_lookup (file_info_tree, (splay_tree_key) name);
>>    if (n)
>>      return (struct c_fileinfo *) n->value;
>> 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);
>> +}

Reply via email to