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. 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); +} -- 2.39.2 (Apple Git-143)