diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 3341679965cc..d879fdf40202 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -316,7 +316,11 @@ namespace clang { /// \brief Record code for an update to a decl context's lookup table. /// /// In practice, this should only be used for the TU and namespaces. - UPDATE_VISIBLE = 34 + UPDATE_VISIBLE = 34, + + /// \brief Record code for template specializations introduced after + /// serializations of the original template decl. + ADDITIONAL_TEMPLATE_SPECIALIZATIONS = 35 }; /// \brief Record types used within a source manager block. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 889605e34d38..12fb3163f88b 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -372,6 +372,16 @@ private: /// most recent declarations in another AST file. FirstLatestDeclIDMap FirstLatestDeclIDs; + typedef llvm::SmallVector + AdditionalTemplateSpecializations; + typedef llvm::DenseMap + AdditionalTemplateSpecializationsMap; + + /// \brief Additional specializations (including partial) of templates that + /// were introduced after the template was serialized. + AdditionalTemplateSpecializationsMap AdditionalTemplateSpecializationsPending; + /// \brief Read the records that describe the contents of declcontexts. bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, const std::pair &Offsets, diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 46448fff0c9d..9acc759fc945 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1972,6 +1972,13 @@ ASTReader::ReadASTBlock(PerFileData &F) { std::make_pair(&F, Record[I+1]); break; } + + case ADDITIONAL_TEMPLATE_SPECIALIZATIONS: { + AdditionalTemplateSpecializations &ATS = + AdditionalTemplateSpecializationsPending[Record[0]]; + ATS.insert(ATS.end(), Record.begin()+1, Record.end()); + break; + } } First = false; } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d2fb408e56c9..d5649ad7be01 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1424,6 +1424,20 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { } } } + + // If this is a template, read additional specializations that may be in a + // different part of the chain. + if (isa(D)) { + AdditionalTemplateSpecializationsMap::iterator F = + AdditionalTemplateSpecializationsPending.find(ID); + if (F != AdditionalTemplateSpecializationsPending.end()) { + for (AdditionalTemplateSpecializations::iterator I = F->second.begin(), + E = F->second.end(); + I != E; ++I) + GetDecl(*I); + AdditionalTemplateSpecializationsPending.erase(F); + } + } assert(Idx == Record.size()); // If we have deserialized a declaration that has a definition the