llvm / llvm/llvm-project

clang crashes instead of diagnosing error when a non-type template parameter of a CRTP base's member template has a type that depends on the incomplete derived class

Open
#220,031 3 comments 0 reactions 1 assignee Claimed by @zyn0217 View on GitHub
clang:frontend confirmed crash-on-valid regression:23
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

clang crashes in CodeGen on programs that should be rejected with a clean diagnostic.

```c++
template
struct enable_if {};
template <>
struct enable_if { using type = int; };

template
struct integral_constant { static constexpr T value = V; };

template
struct Trait : integral_constant {};

template
struct CRTP
{
template ::value>::type = 0>
void fn() const {}
};

struct Derived : CRTP
{
static constexpr bool flag = true;
};

void f()
{
Derived d;
d.fn();
}
```

```
:15:59: error: internal error: could not emit constant value "abstractly"
15 | template ::value>::type = 0>
| ^
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-trunk/bin/clang++ -g -o /app/output.s -fno-verbose-asm -S -target aarch64-linux-gnu --gcc-toolchain=/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu --sysroot=/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot -fcolor-diagnostics -fno-crash-diagnostics -std=c++20
1. parser at end of file
2. Per-file LLVM IR generation
3. :16:10: Generating code for declaration 'CRTP::fn'
#0 0x0000000003cc7fd8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3cc7fd8)
#1 0x0000000003cc591c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3cc591c)
#2 0x0000000003c08798 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
#3 0x000076d744c45330 (/lib/x86_64-linux-gnu/libc.so.6+0x45330)
#4 0x000000000439922b clang::CodeGen::CodeGenTypes::ConvertTypeForMem(clang::QualType) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x439922b)
#5 0x0000000004142327 clang::CodeGen::CodeGenModule::EmitNullConstant(clang::QualType) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4142327)
#6 0x000000000414d14a clang::CodeGen::ConstantEmitter::emitAbstract(clang::Expr const*, clang::QualType) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x414d14a)
#7 0x00000000040a50b8 clang::CodeGen::CGDebugInfo::CollectTemplateParams(std::optional, llvm::DIFile*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x40a50b8)
#8 0x00000000040b04c0 clang::CodeGen::CGDebugInfo::collectFunctionDeclProps(clang::GlobalDecl, llvm::DIFile*, llvm::StringRef&, llvm::StringRef&, llvm::DIScope*&, llvm::MDTupleTypedArrayWrapper&, llvm::DINode::DIFlags&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x40b04c0)
#9 0x00000000040b0e6a clang::CodeGen::CGDebugInfo::emitFunctionStart(clang::GlobalDecl, clang::SourceLocation, clang::SourceLocation, clang::QualType, llvm::Function*, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x40b0e6a)
#10 0x00000000042eb123 clang::CodeGen::CodeGenFunction::StartFunction(clang::GlobalDecl, clang::QualType, llvm::Function*, clang::CodeGen::CGFunctionInfo const&, clang::CodeGen::FunctionArgList const&, clang::SourceLocation, clang::SourceLocation) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x42eb123)
#11 0x00000000042efd95 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x42efd95)
#12 0x000000000434655a clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x434655a)
#13 0x000000000433fba4 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x433fba4)
#14 0x000000000434e05f clang::CodeGen::CodeGenModule::EmitDeferred() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x434e05f)
#15 0x00000000043513c3 clang::CodeGen::CodeGenModule::Release() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x43513c3)
#16 0x00000000046a8dbe (anonymous namespace)::CodeGeneratorImpl::HandleTranslationUnit(clang::ASTContext&) ModuleBuilder.cpp:0:0
#17 0x00000000046a671d clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x46a671d)
#18 0x0000000006328fbc clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x6328fbc)
#19 0x00000000046a73e5 clang::CodeGenAction::ExecuteAction() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x46a73e5)
#20 0x00000000049e0671 clang::FrontendAction::Execute() (/opt/compiler-explorer/clang-trunk/bin/clang+++0x49e0671)
#21 0x0000000004972e35 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4972e35)
#22 0x0000000004ab322b clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x4ab322b)
#23 0x0000000000dcb258 cc1_main(llvm::ArrayRef, char const*, void*) (/opt/compiler-explorer/clang-trunk/bin/clang+++0xdcb258)
#24 0x0000000000dc309b ExecuteCC1Tool(llvm::SmallVectorImpl&, llvm::ToolContext const&, llvm::IntrusiveRefCntPtr) driver.cpp:0:0
#25 0x0000000000dc313d int llvm::function_ref&)>::callback_fn&)>(long, llvm::SmallVectorImpl&) driver.cpp:0:0
#26 0x0000000004722e59 void llvm::function_ref::callback_fn>, std::__cxx11::basic_string, std::allocator>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#27 0x0000000003c08b53 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x3c08b53)
#28 0x000000000472389d clang::driver::CC1Command::Execute(llvm::ArrayRef>, std::__cxx11::basic_string, std::allocator>*, bool*) const (.part.0) Job.cpp:0:0
#29 0x00000000046dda72 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x46dda72)
#30 0x00000000046e1dd5 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl>&, bool) const (/opt/compiler-explorer/clang-trunk/bin/clang+++0x46e1dd5)
#31 0x00000000046ed16c clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl>&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0x46ed16c)
#32 0x0000000000dc7bd1 clang_main(int, char**, llvm::ToolContext const&) (/opt/compiler-explorer/clang-trunk/bin/clang+++0xdc7bd1)
#33 0x0000000000d0e20a main (/opt/compiler-explorer/clang-trunk/bin/clang+++0xd0e20a)
#34 0x000076d744c2a1ca (/lib/x86_64-linux-gnu/libc.so.6+0x2a1ca)
#35 0x000076d744c2a28b __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2a28b)
#36 0x0000000000dc2b45 _start (/opt/compiler-explorer/clang-trunk/bin/clang+++0xdc2b45)
clang++: error: clang frontend command failed due to signal (use -v to see invocation)
Compiler returned: 139
```

https://godbolt.org/z/cvzMYxhdW

According to `[temp.inst]`, implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions. clang should reject the code as instantiation of `Trait`, triggered by evaluating `Trait::value` as part of instantiating `fn`'s declaration, fails. However, compilation proceeds as if the program were well formed until it crashes later in CodeGen.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.