From da211d6433cfaab45091527e1205dac1ff6410a1 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 27 Feb 2015 23:05:10 +0000 Subject: [PATCH] [modules] When writing out a list of specializations for a template, if we have undeserialized specializations (because we merged an imported declaration of the same template since we last added one), don't bother reading in the specializations themselves just so we can write out their IDs again. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@230805 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTReaderDecl.cpp | 6 -- lib/Serialization/ASTWriterDecl.cpp | 109 +++++++++++++++------------- 2 files changed, 58 insertions(+), 57 deletions(-) diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 97e43b700b..ab0f00b7b9 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1748,9 +1748,6 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. SmallVector SpecIDs; - // Specializations. - ReadDeclIDList(SpecIDs); - // Partial specializations. ReadDeclIDList(SpecIDs); if (!SpecIDs.empty()) { @@ -1779,9 +1776,6 @@ void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. SmallVector SpecIDs; - // Specializations. - ReadDeclIDList(SpecIDs); - // Partial specializations. ReadDeclIDList(SpecIDs); if (!SpecIDs.empty()) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 7f2e80583e..e4353cd41d 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -138,6 +138,58 @@ namespace clang { CD->NumCtorInitializers, Record); Writer.AddStmt(FD->getBody()); } + + /// Get the specialization decl from an entry in the specialization list. + template + typename RedeclarableTemplateDecl::SpecEntryTraits::DeclType * + getSpecializationDecl(EntryType &T) { + return RedeclarableTemplateDecl::SpecEntryTraits::getDecl(&T); + } + + /// Get the list of partial specializations from a template's common ptr. + template + decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) { + return Common->PartialSpecializations; + } + ArrayRef getPartialSpecializations(FunctionTemplateDecl::Common *) { + return None; + } + + template + void AddTemplateSpecializations(Decl *D) { + auto *Common = D->getCommonPtr(); + + // If we have any lazy specializations, and the external AST source is + // our chained AST reader, we can just write out the DeclIDs. Otherwise, + // we need to resolve them to actual declarations. + if (Writer.Chain != Writer.Context->getExternalSource() && + Common->LazySpecializations) { + D->LoadLazySpecializations(); + assert(!Common->LazySpecializations); + } + + auto &Specializations = Common->Specializations; + auto &&PartialSpecializations = getPartialSpecializations(Common); + ArrayRef LazySpecializations; + if (auto *LS = Common->LazySpecializations) + LazySpecializations = ArrayRef(LS + 1, LS + 1 + LS[0]); + + Record.push_back(Specializations.size() + + PartialSpecializations.size() + + LazySpecializations.size()); + for (auto &Entry : Specializations) { + auto *D = getSpecializationDecl(Entry); + assert(D->isCanonicalDecl() && "non-canonical decl in set"); + Writer.AddDeclRef(D, Record); + } + for (auto &Entry : PartialSpecializations) { + auto *D = getSpecializationDecl(Entry); + assert(D->isCanonicalDecl() && "non-canonical decl in set"); + Writer.AddDeclRef(D, Record); + } + for (DeclID ID : LazySpecializations) + Record.push_back(ID); + } }; } @@ -1172,24 +1224,8 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDecl()) { - typedef llvm::FoldingSetVector CTSDSetTy; - CTSDSetTy &CTSDSet = D->getSpecializations(); - Record.push_back(CTSDSet.size()); - for (CTSDSetTy::iterator I=CTSDSet.begin(), E = CTSDSet.end(); I!=E; ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - - typedef llvm::FoldingSetVector - CTPSDSetTy; - CTPSDSetTy &CTPSDSet = D->getPartialSpecializations(); - Record.push_back(CTPSDSet.size()); - for (CTPSDSetTy::iterator I=CTPSDSet.begin(), E=CTPSDSet.end(); I!=E; ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - } + if (D->isFirstDecl()) + AddTemplateSpecializations(D); Code = serialization::DECL_CLASS_TEMPLATE; } @@ -1247,26 +1283,8 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDecl()) { - typedef llvm::FoldingSetVector VTSDSetTy; - VTSDSetTy &VTSDSet = D->getSpecializations(); - Record.push_back(VTSDSet.size()); - for (VTSDSetTy::iterator I = VTSDSet.begin(), E = VTSDSet.end(); I != E; - ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - - typedef llvm::FoldingSetVector - VTPSDSetTy; - VTPSDSetTy &VTPSDSet = D->getPartialSpecializations(); - Record.push_back(VTPSDSet.size()); - for (VTPSDSetTy::iterator I = VTPSDSet.begin(), E = VTPSDSet.end(); I != E; - ++I) { - assert(I->isCanonicalDecl() && "Expected only canonical decls in set"); - Writer.AddDeclRef(&*I, Record); - } - } + if (D->isFirstDecl()) + AddTemplateSpecializations(D); Code = serialization::DECL_VAR_TEMPLATE; } @@ -1331,19 +1349,8 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl( void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { VisitRedeclarableTemplateDecl(D); - if (D->isFirstDecl()) { - // This FunctionTemplateDecl owns the CommonPtr; write it. - - // Write the function specialization declarations. - Record.push_back(D->getSpecializations().size()); - for (llvm::FoldingSetVector::iterator - I = D->getSpecializations().begin(), - E = D->getSpecializations().end() ; I != E; ++I) { - assert(I->Function->isCanonicalDecl() && - "Expected only canonical decls in set"); - Writer.AddDeclRef(I->Function, Record); - } - } + if (D->isFirstDecl()) + AddTemplateSpecializations(D); Code = serialization::DECL_FUNCTION_TEMPLATE; } -- 2.40.0