Skip to content

Commit c090601

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 c090601

File tree

3 files changed

+15
-7
lines changed

3 files changed

+15
-7
lines changed

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

clang/test/PCH/cxx2a-constraints-crash.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
2-
// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
3-
4-
// expected-no-diagnostics
1+
// RUN: %clang_cc1 -std=c++2a -fallow-pch-with-compiler-errors -emit-pch %s -o %t -verify
2+
// RUN: %clang_cc1 -std=c++2a -fallow-pch-with-compiler-errors -include-pch %t %s -verify
53

64
#ifndef HEADER
75
#define HEADER
@@ -27,3 +25,12 @@ int main() {
2725
}
2826

2927
#endif
28+
29+
namespace GH99036 {
30+
31+
template <typename T>
32+
concept C; // expected-error {{expected '='}}
33+
// expected-note@32 {{declared here}}
34+
template <C U> void f(); // expected-error {{a concept definition cannot refer to itself}}
35+
36+
} // namespace GH99036

0 commit comments

Comments
 (0)