https://github.com/falbrechtskirchinger updated https://github.com/llvm/llvm-project/pull/110496
>From 8913503b3fd5518201663395d91b7444232e9856 Mon Sep 17 00:00:00 2001 From: Florian Albrechtskirchinger <falbrechtskirchin...@gmail.com> Date: Mon, 30 Sep 2024 12:58:15 +0200 Subject: [PATCH] [clangd][AST] Handle uninitialized type constraints The ASTWriter currently assumes template type constraints to be initialized ((bool)getTypeConstraint() == hasTypeConstraint()). The attached test case presents a scenario where that is not the case. This patch removes the assumption and adds another boolean to the serialization, to explicitly encode whether the type constraint has been initialized. Fixes #99036. Fixes #109354. --- .../clangd/unittests/ASTTests.cpp | 20 +++++++++++++++++++ clang/lib/Serialization/ASTReaderDecl.cpp | 2 +- clang/lib/Serialization/ASTWriterDecl.cpp | 5 +++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clangd/unittests/ASTTests.cpp b/clang-tools-extra/clangd/unittests/ASTTests.cpp index 32c8e8a63a215a..6bf0667b68f967 100644 --- a/clang-tools-extra/clangd/unittests/ASTTests.cpp +++ b/clang-tools-extra/clangd/unittests/ASTTests.cpp @@ -658,6 +658,26 @@ TEST(ClangdAST, PreferredIncludeDirective) { Symbol::IncludeDirective::Import); } +TEST(ClangdAST, HandleUninitializedTypeConstraints) { + auto TU = TestTU::withHeaderCode(R"cpp( + template<typename T> + concept C; // error-ok + template<C U> + void f(); + )cpp"); + TU.ExtraArgs.push_back("-std=c++20"); + + auto AST = TU.build(); + + const auto &F = llvm::cast<FunctionTemplateDecl>(findDecl(AST, "f")); + const auto *Params = F.getTemplateParameters(); + const auto *U = llvm::cast<TemplateTypeParmDecl>(Params->getParam(0)); + const auto *TC = U->getTypeConstraint(); + + EXPECT_TRUE(U->hasTypeConstraint()); + EXPECT_FALSE(/*TypeConstraintInitialized=*/TC != nullptr); +} + } // namespace } // namespace clangd } // namespace clang diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 7cead2728ca938..90783963934bb0 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 b71684569609ac..4da2108f553127 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1899,7 +1899,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { Record.push_back(D->wasDeclaredWithTypename()); const TypeConstraint *TC = D->getTypeConstraint(); - assert((bool)TC == D->hasTypeConstraint()); + Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr); if (TC) { auto *CR = TC->getConceptReference(); Record.push_back(CR != nullptr); @@ -1917,7 +1917,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 +2580,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)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits