llvm / llvm/llvm-project

[clang]Clang assertion failure after diagnosing missing `promise_type::final_suspend` in coroutine template instantiation

Open
#175,720 2 comments 0 reactions 0 assignees View on GitHub
c++20 clang:frontend crash-on-invalid regression:14
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Clang **14.0.0 and later** (assertions enabled) crashes when compiling this code in **C++20 mode or later** (`-std=c++20` or newer).

```cpp
#include

struct Tag {};

struct Y {
bool await_ready() const;
void await_suspend(...) const;
void await_resume() const;
};

struct Promise {
Tag get_return_object();
std::suspend_always initial_suspend();
//std::suspend_always final_suspend() noexcept;
void unhandled_exception();
Y yield_value(int);
void return_void();
};

template
struct std::coroutine_traits {
using promise_type = Promise;
};

template
struct S {
template
static Tag f() { co_yield 0; }
};

Tag g() { return S::f(); }
```
**https://godbolt.org/z/qvjK84f6h**

It first emits the expected diagnostic (`no member named 'final_suspend' in 'Promise'`) for an ill-formed coroutine, but then hits an assertion failure during template instantiation while transforming the coroutine body (`TransformCoyieldExpr`), ending in `LocalInstantiationScope::findInstantiationOf` in `SemaTemplateInstantiate.cpp`. The compiler should diagnose the missing `final_suspend` and recover.

# Output:

```
:28:14: error: no member named 'final_suspend' in 'Promise'
28 | static Tag f() { co_yield 0; }
| ^
clang++: /root/llvm-project/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp:4632: llvm::PointerUnion*>* clang::LocalInstantiationScope::findInstantiationOf(const clang::Decl*): Assertion `isa(D) && "declaration not instantiated in this scope"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -g -o /app/output.s -mllvm --x86-asm-syntax=intel -fno-verbose-asm -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -std=c++20
1. parser at end of file
2. :28:14: instantiating function definition 'S::f'
#0 0x00000000042fea18 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x42fea18)
#1 0x00000000042fbe54 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x42fbe54)
#2 0x000000000423e748 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x00007fe4ae642520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00007fe4ae6969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
#5 0x00007fe4ae642476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
#6 0x00007fe4ae6287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
#7 0x00007fe4ae62871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
#8 0x00007fe4ae639e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#9 0x000000000758598d clang::LocalInstantiationScope::findInstantiationOf(clang::Decl const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x758598d)
#10 0x000000000766d017 clang::Sema::FindInstantiatedDecl(clang::SourceLocation, clang::NamedDecl*, clang::MultiLevelTemplateArgumentList const&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x766d017)
#11 0x00000000075ac9f3 (anonymous namespace)::TemplateInstantiator::TransformDecl(clang::SourceLocation, clang::Decl*) SemaTemplateInstantiate.cpp:0:0
#12 0x00000000075c2190 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#13 0x00000000075c269b (anonymous namespace)::TemplateInstantiator::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#14 0x0000000007592283 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#15 0x00000000075c14e0 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformMemberExpr(clang::MemberExpr*) SemaTemplateInstantiate.cpp:0:0
#16 0x00000000075923c7 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#17 0x00000000075b53d6 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCallExpr(clang::CallExpr*) SemaTemplateInstantiate.cpp:0:0
#18 0x000000000759217c clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#19 0x00000000075b1f15 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformInitializer(clang::Expr*, bool) (.part.0) SemaTemplateInstantiate.cpp:0:0
#20 0x00000000075b257c clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCoyieldExpr(clang::CoyieldExpr*) SemaTemplateInstantiate.cpp:0:0
#21 0x000000000759226b clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#22 0x00000000075922f0 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#23 0x00000000075cf3b7 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformStmt(clang::Stmt*, clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::StmtDiscardKind) SemaTemplateInstantiate.cpp:0:0
#24 0x00000000075cfa65 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformCompoundStmt(clang::CompoundStmt*, bool) SemaTemplateInstantiate.cpp:0:0
#25 0x00000000075d8e9d clang::Sema::SubstStmt(clang::Stmt*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x75d8e9d)
#26 0x00000000076751d0 clang::Sema::InstantiateFunctionDefinition(clang::SourceLocation, clang::FunctionDecl*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x76751d0)
#27 0x0000000007672d96 clang::Sema::PerformPendingInstantiations(bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7672d96)
#28 0x0000000006bee482 clang::Sema::ActOnEndOfTranslationUnitFragment(clang::TUFragmentKind) (.part.0) Sema.cpp:0:0
#29 0x0000000006bee802 clang::Sema::ActOnEndOfTranslationUnit() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6bee802)
#30 0x0000000006a597d5 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6a597d5)
#31 0x0000000006a3a78a clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6a3a78a)
#32 0x0000000004c66488 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c66488)
#33 0x0000000004f60135 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4f60135)
#34 0x0000000004edff0e clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4edff0e)
#35 0x000000000505a7cd clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x505a7cd)
#36 0x0000000000dce92e cc1_main(llvm::ArrayRef, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdce92e)
#37 0x0000000000dc52fa ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr) driver.cpp:0:0
#38 0x0000000000dc547d int llvm::function_ref&)>::callback_fn&)>(long, llvm::SmallVectorImpl&) driver.cpp:0:0
#39 0x0000000004cd96e9 void llvm::function_ref::callback_fn>, std::__cxx11::basic_string, std::allocator>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#40 0x000000000423ebe4 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x423ebe4)
#41 0x0000000004cd9cff clang::driver::CC1Command::Execute(llvm::ArrayRef>, std::__cxx11::basic_string, std::allocator>*, bool*) const (.part.0) Job.cpp:0:0
#42 0x0000000004c9a692 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c9a692)
#43 0x0000000004c9b63e clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4c9b63e)
#44 0x0000000004ca2a95 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4ca2a95)
#45 0x0000000000dcaca1 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdcaca1)
#46 0x0000000000c88434 main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xc88434)
#47 0x00007fe4ae629d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#48 0x00007fe4ae629e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#49 0x0000000000dc4d95 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdc4d95)
clang++: error: clang frontend command failed with exit code 134 (use -v to see invocation)
Compiler returned: 134
```

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the reduced C++20 example from the issue with an assertions-enabled Clang build. Read SemaTemplateInstantiate.cpp around TransformCoyieldExpr and LocalInstantiationScope::findInstantiationOf, then trace how the missing final_suspend diagnostic is handled during template instantiation. Done means the diagnostic is emitted without an assertion or compiler crash.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.