Hi Sebastian, please review. -Argiris
On Aug 3, 2010, at 6:30 PM, Argyrios Kyrtzidis wrote: > Author: akirtzidis > Date: Tue Aug 3 12:30:10 2010 > New Revision: 110125 > > URL: http://llvm.org/viewvc/llvm-project?rev=110125&view=rev > Log: > Apart from storing/retrieving the previous redeclaration from PCH, also > store/retrieve the most recent > redeclaration. That way we are sure that the full redeclarations chain is > loaded. > > When using chained PCHs, first declarations point to the most recent > redeclarations in the same PCH. > To address this use a REDECLS_UPDATE_LATEST record block to keep track of > which first declarations need > to point to a most recent redeclaration in another PCH. > > Modified: > cfe/trunk/include/clang/AST/Redeclarable.h > cfe/trunk/include/clang/Frontend/PCHBitCodes.h > cfe/trunk/include/clang/Frontend/PCHReader.h > cfe/trunk/include/clang/Frontend/PCHWriter.h > cfe/trunk/lib/Frontend/PCHReader.cpp > cfe/trunk/lib/Frontend/PCHReaderDecl.cpp > cfe/trunk/lib/Frontend/PCHWriter.cpp > cfe/trunk/lib/Frontend/PCHWriterDecl.cpp > cfe/trunk/test/PCH/cxx-templates.cpp > cfe/trunk/test/PCH/cxx-templates.h > > Modified: cfe/trunk/include/clang/AST/Redeclarable.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Redeclarable.h?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/include/clang/AST/Redeclarable.h (original) > +++ cfe/trunk/include/clang/AST/Redeclarable.h Tue Aug 3 12:30:10 2010 > @@ -177,6 +177,9 @@ > static_cast<const > decl_type*>(this))); > } > redecl_iterator redecls_end() const { return redecl_iterator(); } > + > + friend class PCHDeclReader; > + friend class PCHDeclWriter; > }; > > } > > Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original) > +++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Tue Aug 3 12:30:10 2010 > @@ -245,8 +245,12 @@ > /// declarations. > TU_UPDATE_LEXICAL = 28, > > + /// \brief Record code for an update to first decls pointing to the > + /// latest redeclarations. > + REDECLS_UPDATE_LATEST = 29, > + > /// \brief Record code for declarations that Sema keeps references of. > - SEMA_DECL_REFS = 29 > + SEMA_DECL_REFS = 30 > }; > > /// \brief Record types used within a source manager block. > > Modified: cfe/trunk/include/clang/Frontend/PCHReader.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Frontend/PCHReader.h (original) > +++ cfe/trunk/include/clang/Frontend/PCHReader.h Tue Aug 3 12:30:10 2010 > @@ -319,6 +319,11 @@ > /// DeclContext. > DeclContextOffsetsMap DeclContextOffsets; > > + typedef llvm::DenseMap<pch::DeclID, pch::DeclID> FirstLatestDeclIDMap; > + /// \brief Map of first declarations from a chained PCH that point to the > + /// most recent declarations in another PCH. > + FirstLatestDeclIDMap FirstLatestDeclIDs; > + > /// \brief Read the records that describe the contents of declcontexts. > bool ReadDeclContextStorage(llvm::BitstreamCursor &Cursor, > const std::pair<uint64_t, uint64_t> &Offsets, > @@ -561,7 +566,7 @@ > QualType ReadTypeRecord(unsigned Index); > RecordLocation TypeCursorForIndex(unsigned Index); > void LoadedDecl(unsigned Index, Decl *D); > - Decl *ReadDeclRecord(unsigned Index); > + Decl *ReadDeclRecord(unsigned Index, pch::DeclID ID); > RecordLocation DeclCursorForIndex(unsigned Index); > > void PassInterestingDeclsToConsumer(); > > Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/include/clang/Frontend/PCHWriter.h (original) > +++ cfe/trunk/include/clang/Frontend/PCHWriter.h Tue Aug 3 12:30:10 2010 > @@ -79,6 +79,7 @@ > public: > typedef llvm::SmallVector<uint64_t, 64> RecordData; > > + friend class PCHDeclWriter; > private: > /// \brief The bitstream writer used to emit this precompiled header. > llvm::BitstreamWriter &Stream; > @@ -195,6 +196,11 @@ > /// \brief Mapping from the macro definition indices in \c MacroDefinitions > /// to the corresponding offsets within the preprocessor block. > std::vector<uint32_t> MacroDefinitionOffsets; > + > + typedef llvm::DenseMap<Decl *, Decl *> FirstLatestDeclMap; > + /// \brief Map of first declarations from a chained PCH that point to the > + /// most recent declarations in another PCH. > + FirstLatestDeclMap FirstLatestDecls; > > /// \brief Declarations encountered that might be external > /// definitions. > > Modified: cfe/trunk/lib/Frontend/PCHReader.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/PCHReader.cpp (original) > +++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Aug 3 12:30:10 2010 > @@ -1557,6 +1557,18 @@ > break; > } > > + case pch::REDECLS_UPDATE_LATEST: { > + assert(Record.size() % 2 == 0 && "Expected pairs of DeclIDs"); > + for (unsigned i = 0, e = Record.size(); i < e; i += 2) { > + pch::DeclID First = Record[i], Latest = Record[i+1]; > + assert((FirstLatestDeclIDs.find(First) == FirstLatestDeclIDs.end() || > + Latest > FirstLatestDeclIDs[First]) && > + "The new latest is supposed to come after the previous > latest"); > + FirstLatestDeclIDs[First] = Latest; > + } > + break; > + } > + > case pch::LANGUAGE_OPTIONS: > if (ParseLanguageOptions(Record) && !DisableValidation) > return IgnorePCH; > @@ -2868,7 +2880,7 @@ > > TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() { > if (!DeclsLoaded[0]) { > - ReadDeclRecord(0); > + ReadDeclRecord(0, 0); > if (DeserializationListener) > DeserializationListener->DeclRead(1, DeclsLoaded[0]); > } > @@ -2887,7 +2899,7 @@ > > unsigned Index = ID - 1; > if (!DeclsLoaded[Index]) { > - ReadDeclRecord(Index); > + ReadDeclRecord(Index, ID); > if (DeserializationListener) > DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); > } > > Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original) > +++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Tue Aug 3 12:30:10 2010 > @@ -31,6 +31,7 @@ > class PCHDeclReader : public DeclVisitor<PCHDeclReader, void> { > PCHReader &Reader; > llvm::BitstreamCursor &Cursor; > + const pch::DeclID ThisDeclID; > const PCHReader::RecordData &Record; > unsigned &Idx; > pch::TypeID TypeIDForTypeDecl; > @@ -39,9 +40,10 @@ > > public: > PCHDeclReader(PCHReader &Reader, llvm::BitstreamCursor &Cursor, > - const PCHReader::RecordData &Record, unsigned &Idx) > - : Reader(Reader), Cursor(Cursor), Record(Record), Idx(Idx), > - TypeIDForTypeDecl(0) { } > + pch::DeclID thisDeclID, const PCHReader::RecordData > &Record, > + unsigned &Idx) > + : Reader(Reader), Cursor(Cursor), ThisDeclID(thisDeclID), > Record(Record), > + Idx(Idx), TypeIDForTypeDecl(0) { } > > void Visit(Decl *D); > > @@ -93,6 +95,7 @@ > void VisitBlockDecl(BlockDecl *BD); > > std::pair<uint64_t, uint64_t> VisitDeclContext(DeclContext *DC); > + template <typename T> void VisitRedeclarable(Redeclarable<T> *D); > > // FIXME: Reorder according to DeclNodes.td? > void VisitObjCMethodDecl(ObjCMethodDecl *D); > @@ -178,8 +181,7 @@ > void PCHDeclReader::VisitTagDecl(TagDecl *TD) { > VisitTypeDecl(TD); > TD->IdentifierNamespace = Record[Idx++]; > - TD->setPreviousDeclaration( > - > cast_or_null<TagDecl>(Reader.GetDecl(Record[Idx++]))); > + VisitRedeclarable(TD); > TD->setTagKind((TagDecl::TagKind)Record[Idx++]); > TD->setDefinition(Record[Idx++]); > TD->setEmbeddedInDeclarator(Record[Idx++]); > @@ -305,10 +307,7 @@ > // FunctionDecl's body is handled last at PCHReaderDecl::Visit, > // after everything else is read. > > - // Avoid side effects and invariant checking of FunctionDecl's > - // setPreviousDeclaration. > - FD->redeclarable_base::setPreviousDeclaration( > - > cast_or_null<FunctionDecl>(Reader.GetDecl(Record[Idx++]))); > + VisitRedeclarable(FD); > FD->setStorageClass((FunctionDecl::StorageClass)Record[Idx++]); > FD->setStorageClassAsWritten((FunctionDecl::StorageClass)Record[Idx++]); > FD->setInlineSpecified(Record[Idx++]); > @@ -550,8 +549,7 @@ > VD->setDeclaredInCondition(Record[Idx++]); > VD->setExceptionVariable(Record[Idx++]); > VD->setNRVOVariable(Record[Idx++]); > - VD->setPreviousDeclaration( > - > cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++]))); > + VisitRedeclarable(VD); > if (Record[Idx++]) > VD->setInit(Reader.ReadExpr(Cursor)); > > @@ -918,6 +916,25 @@ > > RedeclarableTemplateDecl *LatestDecl = > cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++])); > + > + // This decl is a first one and the latest declaration that it points to > is > + // in the same PCH. However, if this actually needs to point to a > + // redeclaration in another chained PCH, we need to update it by checking > + // the FirstLatestDeclIDs map which tracks this kind of decls. > + assert(Reader.GetDecl(ThisDeclID) == D && "Invalid ThisDeclID ?"); > + PCHReader::FirstLatestDeclIDMap::iterator I > + = Reader.FirstLatestDeclIDs.find(ThisDeclID); > + if (I != Reader.FirstLatestDeclIDs.end()) { > + Decl *NewLatest = Reader.GetDecl(I->second); > + assert((LatestDecl->getLocation().isInvalid() || > + NewLatest->getLocation().isInvalid() || > + Reader.SourceMgr.isBeforeInTranslationUnit( > + LatestDecl->getLocation(), > + > NewLatest->getLocation())) && > + "The new latest is supposed to come after the previous latest"); > + LatestDecl = cast<RedeclarableTemplateDecl>(NewLatest); > + } > + > assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch"); > D->getCommonPtr()->Latest = LatestDecl; > } > @@ -1072,6 +1089,54 @@ > return std::make_pair(LexicalOffset, VisibleOffset); > } > > +template <typename T> > +void PCHDeclReader::VisitRedeclarable(Redeclarable<T> *D) { > + enum RedeclKind { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; > + RedeclKind Kind = (RedeclKind)Record[Idx++]; > + switch (Kind) { > + default: > + assert(0 && "Out of sync with PCHDeclWriter::VisitRedeclarable or messed > up" > + " reading"); > + case NoRedeclaration: > + break; > + case PointsToPrevious: > + D->RedeclLink = typename Redeclarable<T>::PreviousDeclLink( > + > cast_or_null<T>(Reader.GetDecl(Record[Idx++]))); > + break; > + case PointsToLatest: > + D->RedeclLink = typename Redeclarable<T>::LatestDeclLink( > + > cast_or_null<T>(Reader.GetDecl(Record[Idx++]))); > + break; > + } > + > + assert(!(Kind == PointsToPrevious && > + Reader.FirstLatestDeclIDs.find(ThisDeclID) != > + Reader.FirstLatestDeclIDs.end()) && > + "This decl is not first, it should not be in the map"); > + if (Kind == PointsToPrevious) > + return; > + > + // This decl is a first one and the latest declaration that it points to > is in > + // the same PCH. However, if this actually needs to point to a > redeclaration > + // in another chained PCH, we need to update it by checking the > + // FirstLatestDeclIDs map which tracks this kind of decls. > + assert(Reader.GetDecl(ThisDeclID) == static_cast<T*>(D) && > + "Invalid ThisDeclID ?"); > + PCHReader::FirstLatestDeclIDMap::iterator I > + = Reader.FirstLatestDeclIDs.find(ThisDeclID); > + if (I != Reader.FirstLatestDeclIDs.end()) { > + Decl *NewLatest = Reader.GetDecl(I->second); > + assert((D->getMostRecentDeclaration()->getLocation().isInvalid() || > + NewLatest->getLocation().isInvalid() || > + Reader.SourceMgr.isBeforeInTranslationUnit( > + > D->getMostRecentDeclaration()->getLocation(), > + NewLatest->getLocation())) && > + "The new latest is supposed to come after the previous latest"); > + D->RedeclLink > + = typename > Redeclarable<T>::LatestDeclLink(cast_or_null<T>(NewLatest)); > + } > +} > + > //===----------------------------------------------------------------------===// > // Attribute Reading > //===----------------------------------------------------------------------===// > @@ -1304,7 +1369,7 @@ > } > > /// \brief Read the declaration at the given offset from the PCH file. > -Decl *PCHReader::ReadDeclRecord(unsigned Index) { > +Decl *PCHReader::ReadDeclRecord(unsigned Index, pch::DeclID ID) { > RecordLocation Loc = DeclCursorForIndex(Index); > llvm::BitstreamCursor &DeclsCursor = *Loc.first; > // Keep track of where we are in the stream, then jump back there > @@ -1320,7 +1385,7 @@ > RecordData Record; > unsigned Code = DeclsCursor.ReadCode(); > unsigned Idx = 0; > - PCHDeclReader Reader(*this, DeclsCursor, Record, Idx); > + PCHDeclReader Reader(*this, DeclsCursor, ID, Record, Idx); > > Decl *D = 0; > switch ((pch::DeclCode)DeclsCursor.ReadRecord(Code, Record)) { > > Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/PCHWriter.cpp (original) > +++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Aug 3 12:30:10 2010 > @@ -2410,6 +2410,19 @@ > WriteIdentifierTable(PP); > WriteTypeDeclOffsets(); > > + /// Build a record containing first declarations from a chained PCH and the > + /// most recent declarations in this PCH that they point to. > + RecordData FirstLatestDeclIDs; > + for (FirstLatestDeclMap::iterator > + I = FirstLatestDecls.begin(), E = FirstLatestDecls.end(); I != E; > ++I) { > + assert(I->first->getPCHLevel() > I->second->getPCHLevel() && > + "Expected first & second to be in different PCHs"); > + AddDeclRef(I->first, FirstLatestDeclIDs); > + AddDeclRef(I->second, FirstLatestDeclIDs); > + } > + if (!FirstLatestDeclIDs.empty()) > + Stream.EmitRecord(pch::REDECLS_UPDATE_LATEST, FirstLatestDeclIDs); > + > // Write the record containing external, unnamed definitions. > if (!ExternalDefinitions.empty()) > Stream.EmitRecord(pch::EXTERNAL_DEFINITIONS, ExternalDefinitions); > > Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original) > +++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Tue Aug 3 12:30:10 2010 > @@ -92,6 +92,7 @@ > > void VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, > uint64_t VisibleOffset); > + template <typename T> void VisitRedeclarable(Redeclarable<T> *D); > > > // FIXME: Put in the same order is DeclNodes.td? > @@ -163,7 +164,7 @@ > void PCHDeclWriter::VisitTagDecl(TagDecl *D) { > VisitTypeDecl(D); > Record.push_back(D->getIdentifierNamespace()); > - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); > + VisitRedeclarable(D); > Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding > Record.push_back(D->isDefinition()); > Record.push_back(D->isEmbeddedInDeclarator()); > @@ -279,7 +280,7 @@ > // FunctionDecl's body is handled last at PCHWriterDecl::Visit, > // after everything else is written. > > - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); > + VisitRedeclarable(D); > Record.push_back(D->getStorageClass()); // FIXME: stable encoding > Record.push_back(D->getStorageClassAsWritten()); > Record.push_back(D->isInlineSpecified()); > @@ -500,7 +501,7 @@ > Record.push_back(D->isDeclaredInCondition()); > Record.push_back(D->isExceptionVariable()); > Record.push_back(D->isNRVOVariable()); > - Writer.AddDeclRef(D->getPreviousDeclaration(), Record); > + VisitRedeclarable(D); > Record.push_back(D->getInit() ? 1 : 0); > if (D->getInit()) > Writer.AddStmt(D->getInit()); > @@ -854,6 +855,18 @@ > Record.push_back(D->isMemberSpecialization()); > > Writer.AddDeclRef(D->getCommonPtr()->Latest, Record); > + } else { > + RedeclarableTemplateDecl *First = D->getFirstDeclaration(); > + assert(First != D); > + // If this is a most recent redeclaration that is pointed to by a first > decl > + // in a chained PCH, keep track of the association with the map so we can > + // update the first decl during PCH reading. > + if (First->getMostRecentDeclaration() == D && > + First->getPCHLevel() > D->getPCHLevel()) { > + > assert(Writer.FirstLatestDecls.find(First)==Writer.FirstLatestDecls.end() > + && "The latest is already set"); > + Writer.FirstLatestDecls[First] = D; > + } > } > } > > @@ -1016,6 +1029,29 @@ > Record.push_back(VisibleOffset); > } > > +template <typename T> > +void PCHDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { > + enum { NoRedeclaration = 0, PointsToPrevious, PointsToLatest }; > + if (D->RedeclLink.getNext() == D) { > + Record.push_back(NoRedeclaration); > + } else { > + Record.push_back(D->RedeclLink.NextIsPrevious() ? PointsToPrevious > + : PointsToLatest); > + Writer.AddDeclRef(D->RedeclLink.getPointer(), Record); > + } > + > + T *First = D->getFirstDeclaration(); > + T *ThisDecl = static_cast<T*>(D); > + // If this is a most recent redeclaration that is pointed to by a first > decl > + // in a chained PCH, keep track of the association with the map so we can > + // update the first decl during PCH reading. > + if (ThisDecl != First && First->getMostRecentDeclaration() == ThisDecl && > + First->getPCHLevel() > ThisDecl->getPCHLevel()) { > + assert(Writer.FirstLatestDecls.find(First) == > Writer.FirstLatestDecls.end() > + && "The latest is already set"); > + Writer.FirstLatestDecls[First] = ThisDecl; > + } > +} > > //===----------------------------------------------------------------------===// > // PCHWriter Implementation > > Modified: cfe/trunk/test/PCH/cxx-templates.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.cpp?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/test/PCH/cxx-templates.cpp (original) > +++ cfe/trunk/test/PCH/cxx-templates.cpp Tue Aug 3 12:30:10 2010 > @@ -1,9 +1,13 @@ > // Test this without pch. > -// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump > +// RUN: %clang_cc1 -include %S/cxx-templates.h -verify %s -ast-dump > 1>/dev/null > +// RUN: %clang_cc1 -include %S/cxx-templates.h %s -emit-llvm -o - | > FileCheck %s > > // Test with pch. > // RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-templates.h > -// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump > +// RUN: %clang_cc1 -include-pch %t -verify %s -ast-dump 1>/dev/null > +// RUN: %clang_cc1 -include-pch %t %s -emit-llvm -o - | FileCheck %s > + > +// CHECK: define linkonce_odr void @_ZN2S3IiE1mEv > > struct A { > typedef int type; > @@ -22,4 +26,7 @@ > Dep<A>::Ty ty; > Dep<A> a; > a.f(); > + > + S3<int> s3; > + s3.m(); > } > > Modified: cfe/trunk/test/PCH/cxx-templates.h > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-templates.h?rev=110125&r1=110124&r2=110125&view=diff > ============================================================================== > --- cfe/trunk/test/PCH/cxx-templates.h (original) > +++ cfe/trunk/test/PCH/cxx-templates.h Tue Aug 3 12:30:10 2010 > @@ -116,3 +116,11 @@ > }; > > extern template class S2<true>; > + > +template <typename T> > +struct S3 { > + void m(); > +}; > + > +template <typename T> > +inline void S3<T>::m() { } > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
