[clang]Clang crash when comparing constraints on friend function template redeclarations
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Clang crashes (assertions build) on the following code starting from **17.0.1**(with **-std=c++23**), and it is still reproducible on trunk:
```cpp
template
struct A {
A() = default;
A(T){}
template
friend void f(int x)
requires(sizeof(x) > 1);
};
A a(0);
template
void f(int x)
requires(sizeof(x) > 1) {}
```
https://godbolt.org/z/qc3zjW37n
### Both _GCC_ and _EDG_ accept this code!
## 🔍 Suspected root cause
The crash appears to be triggered during **constraint comparison for redeclarations of a friend function template**.
Based on the stack trace and reduction, it is likely that:
- Clang attempts to compare the requires-clauses of the friend declaration and the out-of-class definition
- During this process, it performs substitution or structural comparison of the constraint expression
- The expression `sizeof(x) > 1` involves a parameter from a function template declared in a friend context
- This may lead to an invalid lookup or instantiation mapping (e.g. via `LocalInstantiationScope`)
In particular, the issue seems related to:
> incorrect handling of parameter references inside constraint expressions when comparing friend function template redeclarations
### Output:
```
clang++: /root/llvm-project/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp:4725: 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 and dumped files.
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++23
1. :15:29: current parser token '{'
#0 0x00000000043599b8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x43599b8)
#1 0x00000000043568e4 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x43568e4)
#2 0x0000000004356f04 llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4356f04)
#3 0x0000000004294908 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#4 0x00007af36d045330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#5 0x00007af36d09eb2c pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x9eb2c)
#6 0x00007af36d04527e raise (/lib/x86_64-linux-gnu/libc.so.6+0x4527e)
#7 0x00007af36d0288ff abort (/lib/x86_64-linux-gnu/libc.so.6+0x288ff)
#8 0x00007af36d02881b (/lib/x86_64-linux-gnu/libc.so.6+0x2881b)
#9 0x00007af36d03b517 (/lib/x86_64-linux-gnu/libc.so.6+0x3b517)
#10 0x000000000778aa65 clang::LocalInstantiationScope::findInstantiationOf(clang::Decl const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x778aa65)
#11 0x0000000007876776 clang::Sema::FindInstantiatedDecl(clang::SourceLocation, clang::NamedDecl*, clang::MultiLevelTemplateArgumentList const&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7876776)
#12 0x00000000077b3376 (anonymous namespace)::TemplateInstantiator::TransformDecl(clang::SourceLocation, clang::Decl*) SemaTemplateInstantiate.cpp:0:0
#13 0x00000000077c93b0 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#14 0x00000000077c98bf (anonymous namespace)::TemplateInstantiator::TransformDeclRefExpr(clang::DeclRefExpr*) SemaTemplateInstantiate.cpp:0:0
#15 0x0000000007797760 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#16 0x000000000779f858 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformParenExpr(clang::ParenExpr*) SemaTemplateInstantiate.cpp:0:0
#17 0x00000000077979f3 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#18 0x00000000077c6add clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr*) SemaTemplateInstantiate.cpp:0:0
#19 0x0000000007797c73 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#20 0x00000000077b8fb8 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformBinaryOperator(clang::BinaryOperator*) SemaTemplateInstantiate.cpp:0:0
#21 0x00000000077973ac clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#22 0x000000000779f858 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformParenExpr(clang::ParenExpr*) SemaTemplateInstantiate.cpp:0:0
#23 0x00000000077979f3 clang::TreeTransform<(anonymous namespace)::TemplateInstantiator>::TransformExpr(clang::Expr*) SemaTemplateInstantiate.cpp:0:0
#24 0x00000000077a2338 clang::Sema::SubstConstraintExprWithoutSatisfaction(clang::Expr*, clang::MultiLevelTemplateArgumentList const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x77a2338)
#25 0x0000000006f1e8d3 SubstituteConstraintExpressionWithoutSatisfaction(clang::Sema&, clang::Sema::TemplateCompareNewDeclInfo const&, clang::Expr const*) SemaConcept.cpp:0:0
#26 0x0000000006f22ecb clang::Sema::AreConstraintExpressionsEqual(clang::NamedDecl const*, clang::Expr const*, clang::Sema::TemplateCompareNewDeclInfo const&, clang::Expr const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6f22ecb)
#27 0x0000000007547e49 IsOverloadOrOverrideImpl(clang::Sema&, clang::FunctionDecl*, clang::FunctionDecl*, bool, bool, bool) SemaOverload.cpp:0:0
#28 0x00000000075489c3 clang::Sema::CheckOverload(clang::Scope*, clang::FunctionDecl*, clang::LookupResult const&, clang::NamedDecl*&, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x75489c3)
#29 0x000000000703b2a6 clang::Sema::CheckFunctionDeclaration(clang::Scope*, clang::FunctionDecl*, clang::LookupResult&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x703b2a6)
#30 0x0000000007040f89 clang::Sema::ActOnFunctionDeclarator(clang::Scope*, clang::Declarator&, clang::DeclContext*, clang::TypeSourceInfo*, clang::LookupResult&, llvm::MutableArrayRef, bool&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7040f89)
#31 0x0000000007045f5b clang::Sema::HandleDeclarator(clang::Scope*, clang::Declarator&, llvm::MutableArrayRef) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7045f5b)
#32 0x0000000007046be8 clang::Sema::ActOnStartOfFunctionDef(clang::Scope*, clang::Declarator&, llvm::MutableArrayRef, clang::SkipBodyInfo*, clang::Sema::FnBodyKind) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x7046be8)
#33 0x0000000006c4df4a clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::LateParsedAttrList*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c4df4a)
#34 0x0000000006c853b6 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::ParsedAttributes&, clang::Parser::ParsedTemplateInfo&, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c853b6)
#35 0x0000000006d56c70 clang::Parser::ParseDeclarationAfterTemplate(clang::DeclaratorContext, clang::Parser::ParsedTemplateInfo&, clang::ParsingDeclRAIIObject&, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6d56c70)
#36 0x0000000006d644d9 clang::Parser::ParseTemplateDeclarationOrSpecialization(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::AccessSpecifier) (.part.0) ParseTemplate.cpp:0:0
#37 0x0000000006d648ea clang::Parser::ParseDeclarationStartingWithTemplate(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6d648ea)
#38 0x0000000006c8df10 clang::Parser::ParseDeclaration(clang::DeclaratorContext, clang::SourceLocation&, clang::ParsedAttributes&, clang::ParsedAttributes&, clang::SourceLocation*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c8df10)
#39 0x0000000006c49f96 clang::Parser::ParseExternalDeclaration(clang::ParsedAttributes&, clang::ParsedAttributes&, clang::ParsingDeclSpec*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c49f96)
#40 0x0000000006c4ae85 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr&, clang::Sema::ModuleImportState&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c4ae85)
#41 0x0000000006c2be0a clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x6c2be0a)
#42 0x0000000004e49098 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4e49098)
#43 0x0000000005176388 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x5176388)
#44 0x00000000050ff8ad clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x50ff8ad)
#45 0x00000000052740fd clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x52740fd)
#46 0x0000000000dcf28c cc1_main(llvm::ArrayRef, char const*, void*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdcf28c)
#47 0x0000000000dc5eca ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr) driver.cpp:0:0
#48 0x0000000000dc604d int llvm::function_ref&)>::callback_fn&)>(long, llvm::SmallVectorImpl&) driver.cpp:0:0
#49 0x0000000004ebb939 void llvm::function_ref::callback_fn>, std::__cxx11::basic_string, std::allocator>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#50 0x0000000004294d44 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4294d44)
#51 0x0000000004ebbf86 clang::driver::CC1Command::Execute(llvm::ArrayRef>, std::__cxx11::basic_string, std::allocator>*, bool*) const (.part.0) Job.cpp:0:0
#52 0x0000000004e780b2 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4e780b2)
#53 0x0000000004e7905e clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl>&, bool) const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4e7905e)
#54 0x0000000004e807a5 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x4e807a5)
#55 0x0000000000dcb772 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdcb772)
#56 0x0000000000ccae2a main (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xccae2a)
#57 0x00007af36d02a1ca (/lib/x86_64-linux-gnu/libc.so.6+0x2a1ca)
#58 0x00007af36d02a28b __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28b)
#59 0x0000000000dc5875 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0xdc5875)
clang++: error: clang frontend command failed due to signal (use -v to see invocation)
Compiler returned: 134
```
Contributor guide
Research direction
Start by reproducing the C++23 example with an assertions build, then trace constraint comparison through SemaConcept.cpp and SemaOverload.cpp into LocalInstantiationScope::findInstantiationOf in SemaTemplateInstantiate.cpp. Done means the friend function template redeclaration no longer triggers the assertion when compiling the reported reproducer, with coverage for this case added to the relevant compiler tests.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100