[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.
This commit is contained in:
Florian Albrechtskirchinger 2024-10-21 12:24:58 +02:00 committed by Tobias Hieta
parent e541aa5ff9
commit ab51eccf88
No known key found for this signature in database
GPG Key ID: 44F2485E45D59042
3 changed files with 16 additions and 7 deletions

View File

@ -2665,7 +2665,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
D->setDeclaredWithTypename(Record.readInt());
if (D->hasTypeConstraint()) {
const bool TypeConstraintInitialized = Record.readBool();
if (TypeConstraintInitialized && D->hasTypeConstraint()) {
ConceptReference *CR = nullptr;
if (Record.readBool())
CR = Record.readConceptReference();

View File

@ -1880,7 +1880,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);
@ -1898,7 +1898,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() &&
@ -2561,6 +2561,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));

View File

@ -1,7 +1,5 @@
// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
// expected-no-diagnostics
// RUN: %clang_cc1 -std=c++2a -fallow-pch-with-compiler-errors -emit-pch -o %t %s -verify
// RUN: %clang_cc1 -std=c++2a -fallow-pch-with-compiler-errors -include-pch %t %s -verify
#ifndef HEADER
#define HEADER
@ -27,3 +25,12 @@ int main() {
}
#endif
namespace GH99036 {
template <typename T>
concept C; // expected-error {{expected '='}}
template <C U> void f(); // expected-error {{unknown type name 'C'}}
} // namespace GH99036