From: Florian Albrechtskirchinger Date: Mon, 21 Oct 2024 10:24:58 +0000 (+0200) Subject: [Serialization] Handle uninitialized type constraints X-Git-Tag: upstream/19.1.4~23 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ab51eccf88f5321e7c60591c5546b254b6afab99;p=platform%2Fupstream%2Fllvm.git [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. --- diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index c118f3818467..154acdfbe032 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -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(); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 8a4ca54349e3..ff1334340874 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -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)); diff --git a/clang/test/PCH/cxx2a-constraints-crash.cpp b/clang/test/PCH/cxx2a-constraints-crash.cpp index 637c55f0c879..6126a0509fa4 100644 --- a/clang/test/PCH/cxx2a-constraints-crash.cpp +++ b/clang/test/PCH/cxx2a-constraints-crash.cpp @@ -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 +concept C; // expected-error {{expected '='}} + +template void f(); // expected-error {{unknown type name 'C'}} + +} // namespace GH99036