Skip to content

Commit ab51ecc

Browse files
falbrechtskirchingertru
authored andcommitted
[Serialization] Handle uninitialized type constraints
The ASTWriter currently assumes template type constraints to be initialized ((bool)getTypeConstraint() == hasTypeConstraint()). Issues #99036 and #109354 identified a scenario where this assertion is violated. This patch removes the assumption and adds another boolean to the serialization, to explicitly encode whether the type constraint has been initialized. The same issue was incidentally fixed on the main branch by #111179. This solution avoids backporting #111179 and its dependencies.
1 parent e541aa5 commit ab51ecc

File tree

3 files changed

+16
-7
lines changed

3 files changed

+16
-7
lines changed

clang/lib/Serialization/ASTReaderDecl.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -2665,7 +2665,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
26652665

26662666
D->setDeclaredWithTypename(Record.readInt());
26672667

2668-
if (D->hasTypeConstraint()) {
2668+
const bool TypeConstraintInitialized = Record.readBool();
2669+
if (TypeConstraintInitialized && D->hasTypeConstraint()) {
26692670
ConceptReference *CR = nullptr;
26702671
if (Record.readBool())
26712672
CR = Record.readConceptReference();

clang/lib/Serialization/ASTWriterDecl.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1880,7 +1880,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
18801880
Record.push_back(D->wasDeclaredWithTypename());
18811881

18821882
const TypeConstraint *TC = D->getTypeConstraint();
1883-
assert((bool)TC == D->hasTypeConstraint());
1883+
Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr);
18841884
if (TC) {
18851885
auto *CR = TC->getConceptReference();
18861886
Record.push_back(CR != nullptr);
@@ -1898,7 +1898,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
18981898
if (OwnsDefaultArg)
18991899
Record.AddTemplateArgumentLoc(D->getDefaultArgument());
19001900

1901-
if (!TC && !OwnsDefaultArg &&
1901+
if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
19021902
D->getDeclContext() == D->getLexicalDeclContext() &&
19031903
!D->isInvalidDecl() && !D->hasAttrs() &&
19041904
!D->isTopLevelDeclInObjCContainer() && !D->isImplicit() &&
@@ -2561,6 +2561,7 @@ void ASTWriter::WriteDeclAbbrevs() {
25612561
// TemplateTypeParmDecl
25622562
Abv->Add(
25632563
BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // wasDeclaredWithTypename
2564+
Abv->Add(BitCodeAbbrevOp(0)); // TypeConstraintInitialized
25642565
Abv->Add(BitCodeAbbrevOp(0)); // OwnsDefaultArg
25652566
DeclTemplateTypeParmAbbrev = Stream.EmitAbbrev(std::move(Abv));
25662567

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

+11-4
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 -o %t %s -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+
34+
template <C U> void f(); // expected-error {{unknown type name 'C'}}
35+
36+
} // namespace GH99036

0 commit comments

Comments
 (0)