From: Sebastian Redl Date: Fri, 23 Jul 2010 23:49:55 +0000 (+0000) Subject: Make declarations in the dependent PCH visible, for C at least. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f2f0f03d08c6143137a79a8edffc7d41823bc3c7;p=clang Make declarations in the dependent PCH visible, for C at least. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109292 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Frontend/PCHDeserializationListener.h b/include/clang/Frontend/PCHDeserializationListener.h index 84d7f8c1f5..fe9c755605 100644 --- a/include/clang/Frontend/PCHDeserializationListener.h +++ b/include/clang/Frontend/PCHDeserializationListener.h @@ -27,6 +27,8 @@ protected: virtual ~PCHDeserializationListener() {} public: + /// \brief An identifier was deserialized from the PCH. + virtual void IdentifierRead(pch::IdentID ID, IdentifierInfo *II) = 0; /// \brief A type was deserialized from the PCH. The ID here has the qualifier /// bits already removed, and T is guaranteed to be locally unqualified virtual void TypeRead(pch::TypeID ID, QualType T) = 0; diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 17a733ce30..8bf51e109e 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -655,11 +655,16 @@ public: /// \brief Read preprocessed entities into the virtual void ReadPreprocessedEntities(); - /// \brief Returns the number of source locations found in this file. + /// \brief Returns the number of source locations found in the chain. unsigned getTotalNumSLocs() const { return TotalNumSLocEntries; } + /// \brief Returns the number of identifiers found in the chain. + unsigned getTotalNumIdentifiers() const { + return static_cast(IdentifiersLoaded.size()); + } + /// \brief Returns the number of types found in this file. unsigned getTotalNumTypes() const { return static_cast(TypesLoaded.size()); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index ab6c6ef8c6..10b96e8a3c 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -113,6 +113,9 @@ private: /// \brief The first ID number we can use for our own declarations. pch::DeclID FirstDeclID; + /// \brief The decl ID that will be assigned to the next new decl. + pch::DeclID NextDeclID; + /// \brief Map that provides the ID numbers of each declaration within /// the output stream, as well as those deserialized from a chained PCH. /// @@ -128,6 +131,9 @@ private: /// \brief The first ID number we can use for our own types. pch::TypeID FirstTypeID; + /// \brief The type ID that will be assigned to the next new type. + pch::TypeID NextTypeID; + /// \brief Map that provides the ID numbers of each type within the /// output stream, plus those deserialized from a chained PCH. /// @@ -143,8 +149,11 @@ private: /// the type's ID. std::vector TypeOffsets; - /// \brief The type ID that will be assigned to the next new type. - pch::TypeID NextTypeID; + /// \brief The first ID number we can use for our own identifiers. + pch::IdentID FirstIdentID; + + /// \brief The identifier ID that will be assigned to the next new identifier. + pch::IdentID NextIdentID; /// \brief Map that provides the ID numbers of each identifier in /// the output stream. @@ -405,7 +414,10 @@ public: unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; } + bool hasChain() const { return Chain; } + // PCHDeserializationListener implementation + void IdentifierRead(pch::IdentID ID, IdentifierInfo *II); void TypeRead(pch::TypeID ID, QualType T); void DeclRead(pch::DeclID ID, const Decl *D); }; diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index b4564885a8..48d05ba826 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -3193,6 +3193,8 @@ void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) { assert(ID && "Non-zero identifier ID required"); assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range"); IdentifiersLoaded[ID - 1] = II; + if (DeserializationListener) + DeserializationListener->IdentifierRead(ID, II); } /// \brief Set the globally-visible declarations associated with the given @@ -3277,6 +3279,8 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) { | (((unsigned) StrLenPtr[1]) << 8)) - 1; IdentifiersLoaded[ID] = &PP->getIdentifierTable().get(Str, StrLen); + if (DeserializationListener) + DeserializationListener->IdentifierRead(ID + 1, IdentifiersLoaded[ID]); } return IdentifiersLoaded[ID]; diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 0b8c5b4258..4474eaef48 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1851,12 +1851,14 @@ public: // "stat"), but IdentifierResolver::AddDeclToIdentifierChain() // adds declarations to the end of the list (so we need to see the // struct "status" before the function "status"). + // Only emit declarations that aren't from a chained PCH, though. llvm::SmallVector Decls(IdentifierResolver::begin(II), IdentifierResolver::end()); for (llvm::SmallVector::reverse_iterator D = Decls.rbegin(), DEnd = Decls.rend(); D != DEnd; ++D) - clang::io::Emit32(Out, Writer.getDeclID(*D)); + if (!Writer.hasChain() || (*D)->getPCHLevel() == 0) + clang::io::Emit32(Out, Writer.getDeclID(*D)); } }; } // end anonymous namespace @@ -1884,13 +1886,17 @@ void PCHWriter::WriteIdentifierTable(Preprocessor &PP) { ID != IDEnd; ++ID) getIdentifierRef(ID->second); - // Create the on-disk hash table representation. - IdentifierOffsets.resize(IdentifierIDs.size()); + // Create the on-disk hash table representation. We only store offsets + // for identifiers that appear here for the first time. + IdentifierOffsets.resize(NextIdentID - FirstIdentID); for (llvm::DenseMap::iterator ID = IdentifierIDs.begin(), IDEnd = IdentifierIDs.end(); ID != IDEnd; ++ID) { assert(ID->first && "NULL identifier in identifier table"); - Generator.insert(ID->first, ID->second); + // FIXME: Right now, we only write identifiers that are new to this file. + // We need to write older identifiers that changed too, though. + if (ID->second >= FirstIdentID) + Generator.insert(ID->first, ID->second); } // Create the on-disk hash table in a buffer. @@ -2116,7 +2122,11 @@ void PCHWriter::AddString(const std::string &Str, RecordData &Record) { /// \brief Note that the identifier II occurs at the given offset /// within the identifier table. void PCHWriter::SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset) { - IdentifierOffsets[IdentifierIDs[II] - 1] = Offset; + pch::IdentID ID = IdentifierIDs[II]; + // Only store offsets new to this PCH file. Other identifier names are looked + // up earlier in the chain and thus don't need an offset. + if (ID >= FirstIdentID) + IdentifierOffsets[ID - FirstIdentID] = Offset; } /// \brief Note that the selector Sel occurs at the given offset @@ -2129,15 +2139,18 @@ void PCHWriter::SetSelectorOffset(Selector Sel, uint32_t Offset) { PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream, PCHReader *Chain) : Stream(Stream), Chain(Chain), FirstDeclID(1), - FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), + FirstTypeID(pch::NUM_PREDEF_TYPE_IDS), FirstIdentID(1), CollectedStmts(&StmtsToEmit), NumStatements(0), NumMacros(0), NumLexicalDeclContexts(0), NumVisibleDeclContexts(0) { if (Chain) { Chain->setDeserializationListener(this); FirstDeclID += Chain->getTotalNumDecls(); FirstTypeID += Chain->getTotalNumTypes(); + FirstIdentID += Chain->getTotalNumIdentifiers(); } + NextDeclID = FirstDeclID; NextTypeID = FirstTypeID; + NextIdentID = FirstIdentID; } void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, @@ -2165,6 +2178,7 @@ void PCHWriter::WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, // The translation unit is the first declaration we'll emit. DeclIDs[Context.getTranslationUnitDecl()] = 1; + ++NextDeclID; DeclTypesToEmit.push(Context.getTranslationUnitDecl()); // Make sure that we emit IdentifierInfos (and any attached @@ -2334,6 +2348,9 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, // We don't start with the translation unit, but with its decls that // don't come from the other PCH. const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + // The TU was loaded before we managed to register ourselves as a listener. + // Thus we need to add it manually. + DeclIDs[TU] = 1; // FIXME: We don't want to iterate over everything here, because it needlessly // deserializes the entire original PCH. Instead we only want to iterate over // the stuff that's already there. @@ -2359,7 +2376,7 @@ void PCHWriter::WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, // FIXME: Preprocessor // FIXME: Method pool - // FIXME: Identifier table + WriteIdentifierTable(PP); WriteTypeDeclOffsets(); // FIXME: External unnamed definitions // FIXME: Tentative definitions @@ -2407,7 +2424,7 @@ pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) { pch::IdentID &ID = IdentifierIDs[II]; if (ID == 0) - ID = IdentifierIDs.size(); + ID = NextIdentID++; return ID; } @@ -2576,7 +2593,7 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) { if (ID == 0) { // We haven't seen this declaration before. Give it a new ID and // enqueue it in the list of declarations to emit. - ID = DeclIDs.size(); + ID = NextDeclID++; DeclTypesToEmit.push(const_cast(D)); } @@ -2777,6 +2794,10 @@ void PCHWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, AddSourceRange(Base.getSourceRange(), Record); } +void PCHWriter::IdentifierRead(pch::IdentID ID, IdentifierInfo *II) { + IdentifierIDs[II] = ID; +} + void PCHWriter::TypeRead(pch::TypeID ID, QualType T) { TypeIDs[T] = ID; } diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 7c4a21adb6..09cafe2c33 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -1144,9 +1144,9 @@ void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) { // Determine the ID for this declaration pch::DeclID &ID = DeclIDs[D]; if (ID == 0) - ID = DeclIDs.size(); + ID = NextDeclID++; - unsigned Index = ID - 1; + unsigned Index = ID - FirstDeclID; // Record the offset for this declaration if (DeclOffsets.size() == Index) diff --git a/test/PCH/Inputs/chain-function1.h b/test/PCH/Inputs/chain-function1.h new file mode 100644 index 0000000000..789447c027 --- /dev/null +++ b/test/PCH/Inputs/chain-function1.h @@ -0,0 +1 @@ +void f(); diff --git a/test/PCH/Inputs/chain-function2.h b/test/PCH/Inputs/chain-function2.h new file mode 100644 index 0000000000..e8fc9651ed --- /dev/null +++ b/test/PCH/Inputs/chain-function2.h @@ -0,0 +1 @@ +void g(); diff --git a/test/PCH/chain-function.c b/test/PCH/chain-function.c new file mode 100644 index 0000000000..29bfdd4c3e --- /dev/null +++ b/test/PCH/chain-function.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -emit-pch -o %t1 %S/Inputs/chain-function1.h +// RUN: %clang_cc1 -emit-pch -o %t2 %S/Inputs/chain-function2.h -include-pch %t1 -chained-pch +// RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s + +void h() { + f(); + g(); +}