Skip to content

Commit 8913503

Browse files
[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.
1 parent 5df7d88 commit 8913503

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

clang-tools-extra/clangd/unittests/ASTTests.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,26 @@ TEST(ClangdAST, PreferredIncludeDirective) {
658658
Symbol::IncludeDirective::Import);
659659
}
660660

661+
TEST(ClangdAST, HandleUninitializedTypeConstraints) {
662+
auto TU = TestTU::withHeaderCode(R"cpp(
663+
template<typename T>
664+
concept C; // error-ok
665+
template<C U>
666+
void f();
667+
)cpp");
668+
TU.ExtraArgs.push_back("-std=c++20");
669+
670+
auto AST = TU.build();
671+
672+
const auto &F = llvm::cast<FunctionTemplateDecl>(findDecl(AST, "f"));
673+
const auto *Params = F.getTemplateParameters();
674+
const auto *U = llvm::cast<TemplateTypeParmDecl>(Params->getParam(0));
675+
const auto *TC = U->getTypeConstraint();
676+
677+
EXPECT_TRUE(U->hasTypeConstraint());
678+
EXPECT_FALSE(/*TypeConstraintInitialized=*/TC != nullptr);
679+
}
680+
661681
} // namespace
662682
} // namespace clangd
663683
} // namespace clang

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2674,7 +2674,7 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
26742674

26752675
D->setDeclaredWithTypename(Record.readInt());
26762676

2677-
if (D->hasTypeConstraint()) {
2677+
if (Record.readBool() && D->hasTypeConstraint()) {
26782678
ConceptReference *CR = nullptr;
26792679
if (Record.readBool())
26802680
CR = Record.readConceptReference();

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,7 +1899,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
18991899
Record.push_back(D->wasDeclaredWithTypename());
19001900

19011901
const TypeConstraint *TC = D->getTypeConstraint();
1902-
assert((bool)TC == D->hasTypeConstraint());
1902+
Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr);
19031903
if (TC) {
19041904
auto *CR = TC->getConceptReference();
19051905
Record.push_back(CR != nullptr);
@@ -1917,7 +1917,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
19171917
if (OwnsDefaultArg)
19181918
Record.AddTemplateArgumentLoc(D->getDefaultArgument());
19191919

1920-
if (!TC && !OwnsDefaultArg &&
1920+
if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
19211921
D->getDeclContext() == D->getLexicalDeclContext() &&
19221922
!D->isInvalidDecl() && !D->hasAttrs() &&
19231923
!D->isTopLevelDeclInObjCContainer() && !D->isImplicit() &&
@@ -2580,6 +2580,7 @@ void ASTWriter::WriteDeclAbbrevs() {
25802580
// TemplateTypeParmDecl
25812581
Abv->Add(
25822582
BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // wasDeclaredWithTypename
2583+
Abv->Add(BitCodeAbbrevOp(0)); // TypeConstraintInitialized
25832584
Abv->Add(BitCodeAbbrevOp(0)); // OwnsDefaultArg
25842585
DeclTemplateTypeParmAbbrev = Stream.EmitAbbrev(std::move(Abv));
25852586

0 commit comments

Comments
 (0)