Closed Equidamoid closed 4 days ago
@llvm/issue-subscribers-clang-frontend
Author: None (Equidamoid)
@llvm/issue-subscribers-clangd
Author: None (Equidamoid)
clangd log and stack trace alone are not nearly enough for us to reproduce this
@ChuanqiXu9 The assertion there is probably wrong. hasTypeConstraint() could be different with the value of getTypeConstraint() according to the document of TypeConstraintInitialized:
/// Whether this template type parameter has a type-constraint construct.
bool HasTypeConstraint : 1;
/// Whether the type constraint has been initialized. This can be false if the
/// constraint was not initialized yet or if there was an error forming the
/// type constraint.
bool TypeConstraintInitialized : 1;
@Endilll unfortunately I wasn't able to reduce it to a nice reproduction scenario. I should be able to easily rebuild latest clang with any given patches and try reproducing the problem again though.
I've been dealing with this crash for the past couple of weeks (19.1.0_rcX to git master today). Based on @zyn0217's hint, I tried a patch that initially worked, but with my limited understanding after reading the code for mere minutes, its correctness is doubtful. Especially, given that days later it crashed again in ASTReader::ReadStmtFromStream
with ASTDeclReader::VisitTemplateTypeParmDecl
making a suspicious appearance in the stack trace.
Thanks to #109354 I was reminded of C-Reduce et.al. and used C-Vise to create this unhelpful-looking reproducer:
test.hpp
#include <h>
#include <variant>
I tried a preprocessed version but that is evidently not the same as far as clangd is concerned.
compile_commands.json
[
{
"directory": "/",
"command": "/usr/bin/g++-14 -std=c++20",
"file": "test.hpp"
}
]
Command line
/usr/lib/llvm/20/bin/clangd --compile-commands-dir=. --check=test.hpp
Output
I[17:36:59.185] clangd version 20.0.0git816134b3
I[17:36:59.185] Features: linux+debug
I[17:36:59.185] PID: 224952
I[17:36:59.185] Working directory: /volatile
I[17:36:59.185] argv[0]: /usr/lib/llvm/20/bin/clangd
I[17:36:59.185] argv[1]: --compile-commands-dir=.
I[17:36:59.185] argv[2]: --check=test.hpp
I[17:36:59.185] Entering check mode (no LSP server)
I[17:36:59.185] Testing on source file /volatile/test.hpp
I[17:36:59.185] Loading compilation database...
I[17:36:59.185] Loaded compilation database from /volatile/./compile_commands.json
I[17:36:59.186] Compile command inferred from test.hpp is: [/] /usr/x86_64-pc-linux-gnu/gcc-bin/14/g++-14 --driver-mode=g++ -std=c++20 -resource-dir=/usr/lib/llvm/20/bin/../../../../lib/clang/20 -- /volatile/test.hpp
I[17:36:59.186] Parsing command...
I[17:36:59.187] internal (cc1) args are: -cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -disable-free -clear-ast-before-backend -main-file-name test.hpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/ -fcoverage-compilation-dir=/ -resource-dir /usr/lib/llvm/20/bin/../../../../lib/clang/20 -include /usr/include/gentoo/fortify.h -include /usr/include/gentoo/maybe-stddefs.h -internal-isystem /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14 -internal-isystem /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/x86_64-pc-linux-gnu -internal-isystem /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/backward -internal-isystem /usr/lib/llvm/20/bin/../../../../lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-pc-linux-gnu/14/../../../../x86_64-pc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c++20 -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -no-round-trip-args -D__GCC_HAVE_DWARF2_CFI_ASM=1 -x c++-header /volatile/test.hpp
I[17:36:59.187] Building preamble...
clangd: /var/tmp/portage/sys-devel/clang-20.0.0.9999/work/clang/lib/Serialization/ASTWriterDecl.cpp:1890: void clang::ASTDeclWriter::VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl*): Assertion `(bool)TC == D->hasTypeConstraint()' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: /usr/lib/llvm/20/bin/clangd --compile-commands-dir=. --check=test.hpp
1. <eof> parser at end of file
2. /usr/lib/gcc/x86_64-pc-linux-gnu/14/include/g++-v14/bits/iterator_concepts.h:798:32: serializing '_Iter'
#0 0x00007fd6a5243fe0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/llvm/20/bin/../lib64/libLLVM.so.20.0git816134b3+0xa43fe0)
#1 0x00007fd6a5241294 llvm::sys::RunSignalHandlers() (/usr/lib/llvm/20/bin/../lib64/libLLVM.so.20.0git816134b3+0xa41294)
#2 0x00007fd6a5241426 (/usr/lib/llvm/20/bin/../lib64/libLLVM.so.20.0git816134b3+0xa41426)
#3 0x00007fd6a4250a50 (/usr/lib64/libc.so.6+0x3ca50)
#4 0x00007fd6a42a621c (/usr/lib64/libc.so.6+0x9221c)
#5 0x00007fd6a42509a6 raise (/usr/lib64/libc.so.6+0x3c9a6)
#6 0x00007fd6a42388fa abort (/usr/lib64/libc.so.6+0x248fa)
#7 0x00007fd6a423881e (/usr/lib64/libc.so.6+0x2481e)
#8 0x00007fd6a4248f36 (/usr/lib64/libc.so.6+0x34f36)
#9 0x00007fd6ad91617c clang::ASTDeclWriter::VisitTemplateTypeParmDecl(clang::TemplateTypeParmDecl*) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x311617c)
#10 0x00007fd6ad91c863 clang::ASTDeclWriter::Visit(clang::Decl*) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x311c863)
#11 0x00007fd6ad91cc97 clang::ASTWriter::WriteDecl(clang::ASTContext&, clang::Decl*) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x311cc97)
#12 0x00007fd6ad9067d2 clang::ASTWriter::WriteDeclAndTypes(clang::ASTContext&) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x31067d2)
#13 0x00007fd6ad907c07 clang::ASTWriter::WriteASTCore(clang::Sema&, llvm::StringRef, clang::Module*) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x3107c07)
#14 0x00007fd6ad9090ae clang::ASTWriter::WriteAST(clang::Sema&, llvm::StringRef, clang::Module*, llvm::StringRef, bool) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x31090ae)
#15 0x00007fd6ad92fcce clang::PCHGenerator::HandleTranslationUnit(clang::ASTContext&) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x312fcce)
#16 0x00007fd6adad47c2 (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x32d47c2)
#17 0x00007fd6ab1c37dc clang::ParseAST(clang::Sema&, bool, bool) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x9c37dc)
#18 0x00007fd6ada8a0e9 clang::FrontendAction::Execute() (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x328a0e9)
#19 0x00007fd6adad30fb clang::PrecompiledPreamble::Build(clang::CompilerInvocation const&, llvm::MemoryBuffer const*, clang::PreambleBounds, clang::DiagnosticsEngine&, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::shared_ptr<clang::PCHContainerOperations>, bool, llvm::StringRef, clang::PreambleCallbacks&) (/usr/lib/llvm/20/bin/../lib64/libclang-cpp.so.20.0git816134b3+0x32d30fb)
#20 0x000055774c1254c8 (/usr/lib/llvm/20/bin/clangd+0x4b34c8)
#21 0x000055774bec2562 (/usr/lib/llvm/20/bin/clangd+0x250562)
#22 0x000055774bec4b5c (/usr/lib/llvm/20/bin/clangd+0x252b5c)
#23 0x000055774beb6c84 (/usr/lib/llvm/20/bin/clangd+0x244c84)
#24 0x00007fd6a423a42e (/usr/lib64/libc.so.6+0x2642e)
#25 0x00007fd6a423a4e9 __libc_start_main (/usr/lib64/libc.so.6+0x264e9)
#26 0x000055774be01a65 (/usr/lib/llvm/20/bin/clangd+0x18fa65)
Aborted
Let me know if there's anything else I can provide.
I figured out enough of the code to prevent the crash. If my solution is an actual fix, depends on whether the type constraint may be uninitialized in ASTDeclWriter::VisitTemplateTypeParmDecl
– rendering the assertion invalid – or not. If the assertion is correct, I'd look in Sema::BuildTypeConstraint
and Sema::AttachTypeConstraint
next, but I'm not even going to attempt to diagnose that until I get a more authoritative opinion.
Meanwhile, here's the patch for anyone interested. I did not test if clang still produces correct output, as I'm only using clangd built with this patch.
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 7cead2728ca9..90783963934b 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2674,7 +2674,7 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
D->setDeclaredWithTypename(Record.readInt());
- if (D->hasTypeConstraint()) {
+ if (Record.readBool() && D->hasTypeConstraint()) {
ConceptReference *CR = nullptr;
if (Record.readBool())
CR = Record.readConceptReference();
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index b71684569609..ddd813bd1682 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1899,7 +1899,8 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
Record.push_back(D->wasDeclaredWithTypename());
const TypeConstraint *TC = D->getTypeConstraint();
- assert((bool)TC == D->hasTypeConstraint());
+ // assert((bool)TC == D->hasTypeConstraint());
+ Record.push_back(TC != nullptr);
if (TC) {
auto *CR = TC->getConceptReference();
Record.push_back(CR != nullptr);
@@ -1917,7 +1918,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
if (OwnsDefaultArg)
Record.AddTemplateArgumentLoc(D->getDefaultArgument());
- if (!TC && !OwnsDefaultArg &&
+ if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
D->getDeclContext() == D->getLexicalDeclContext() &&
!D->isInvalidDecl() && !D->hasAttrs() &&
!D->isTopLevelDeclInObjCContainer() && !D->isImplicit() &&
@@ -2580,6 +2581,7 @@ void ASTWriter::WriteDeclAbbrevs() {
// TemplateTypeParmDecl
Abv->Add(
BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // wasDeclaredWithTypename
+ Abv->Add(BitCodeAbbrevOp(0)); // TypeConstraintInitialized
Abv->Add(BitCodeAbbrevOp(0)); // OwnsDefaultArg
DeclTemplateTypeParmAbbrev = Stream.EmitAbbrev(std::move(Abv));
@falbrechtskirchinger Thanks for your diagnosis on this issue! Do you want to put up a PR with a reduced test case so that we can see if it makes sense? It would be great if we can fix the problem upstream in clang :)
@zyn0217 Sure. I've done some more work to create a better reproducer. I'll write a proper test and then submit a PR.
template<_Up>
concept __decayed_same_as;
template<__decayed_same_as>
partial_ordering operator0
If included in place of <variant>
it triggers the assertion. However, it doesn't trigger if parsed directly.
This and #109354 can now be closed. Fixes have landed in main
(#111179) and release/19.x
(#113182).
I'm getting the following crash when feeding clangd a
compile_commands.json
file generated for a esp32 cross-compilation build (not sure if it's relevant, the expected behaviour is still not to crash, regardless of the build parameters):