diff options
Diffstat (limited to 'lib/Serialization/GlobalModuleIndex.cpp')
| -rw-r--r-- | lib/Serialization/GlobalModuleIndex.cpp | 76 | 
1 files changed, 66 insertions, 10 deletions
diff --git a/lib/Serialization/GlobalModuleIndex.cpp b/lib/Serialization/GlobalModuleIndex.cpp index ae5796ede126..6978e7e09774 100644 --- a/lib/Serialization/GlobalModuleIndex.cpp +++ b/lib/Serialization/GlobalModuleIndex.cpp @@ -376,6 +376,15 @@ namespace {      /// \brief The set of modules on which this module depends. Each entry is      /// a module ID.      SmallVector<unsigned, 4> Dependencies; +    ASTFileSignature Signature; +  }; + +  struct ImportedModuleFileInfo { +    off_t StoredSize; +    time_t StoredModTime; +    ASTFileSignature StoredSignature; +    ImportedModuleFileInfo(off_t Size, time_t ModTime, ASTFileSignature Sig) +        : StoredSize(Size), StoredModTime(ModTime), StoredSignature(Sig) {}    };    /// \brief Builder that generates the global module index file. @@ -383,12 +392,20 @@ namespace {      FileManager &FileMgr;      const PCHContainerReader &PCHContainerRdr; -    /// \brief Mapping from files to module file information. +    /// Mapping from files to module file information.      typedef llvm::MapVector<const FileEntry *, ModuleFileInfo> ModuleFilesMap; -    /// \brief Information about each of the known module files. +    /// Information about each of the known module files.      ModuleFilesMap ModuleFiles; +    /// \brief Mapping from the imported module file to the imported +    /// information. +    typedef std::multimap<const FileEntry *, ImportedModuleFileInfo> +        ImportedModuleFilesMap; + +    /// \brief Information about each importing of a module file. +    ImportedModuleFilesMap ImportedModuleFiles; +      /// \brief Mapping from identifiers to the list of module file IDs that      /// consider this identifier to be interesting.      typedef llvm::StringMap<SmallVector<unsigned, 2> > InterestingIdentifierMap; @@ -424,7 +441,8 @@ namespace {      bool loadModuleFile(const FileEntry *File);      /// \brief Write the index to the given bitstream. -    void writeIndex(llvm::BitstreamWriter &Stream); +    /// \returns true if an error occurred, false otherwise. +    bool writeIndex(llvm::BitstreamWriter &Stream);    };  } @@ -515,7 +533,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {    unsigned ID = getModuleFileInfo(File).ID;    // Search for the blocks and records we care about. -  enum { Other, ControlBlock, ASTBlock } State = Other; +  enum { Other, ControlBlock, ASTBlock, DiagnosticOptionsBlock } State = Other;    bool Done = false;    while (!Done) {      llvm::BitstreamEntry Entry = InStream.advance(); @@ -553,6 +571,15 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {          continue;        } +      if (Entry.ID == UNHASHED_CONTROL_BLOCK_ID) { +        if (InStream.EnterSubBlock(UNHASHED_CONTROL_BLOCK_ID)) +          return true; + +        // Found the Diagnostic Options block. +        State = DiagnosticOptionsBlock; +        continue; +      } +        if (InStream.SkipBlock())          return true; @@ -587,7 +614,10 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {          // Skip the stored signature.          // FIXME: we could read the signature out of the import and validate it. -        Idx++; +        ASTFileSignature StoredSignature = { +            {{(uint32_t)Record[Idx++], (uint32_t)Record[Idx++], +              (uint32_t)Record[Idx++], (uint32_t)Record[Idx++], +              (uint32_t)Record[Idx++]}}};          // Retrieve the imported file name.          unsigned Length = Record[Idx++]; @@ -599,11 +629,16 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {          const FileEntry *DependsOnFile            = FileMgr.getFile(ImportedFile, /*openFile=*/false,                              /*cacheFailure=*/false); -        if (!DependsOnFile || -            (StoredSize != DependsOnFile->getSize()) || -            (StoredModTime != DependsOnFile->getModificationTime())) + +        if (!DependsOnFile)            return true; +        // Save the information in ImportedModuleFileInfo so we can verify after +        // loading all pcms. +        ImportedModuleFiles.insert(std::make_pair( +            DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime, +                                                  StoredSignature))); +          // Record the dependency.          unsigned DependsOnID = getModuleFileInfo(DependsOnFile).ID;          getModuleFileInfo(File).Dependencies.push_back(DependsOnID); @@ -632,6 +667,12 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) {        }      } +    // Get Signature. +    if (State == DiagnosticOptionsBlock && Code == SIGNATURE) +      getModuleFileInfo(File).Signature = { +          {{(uint32_t)Record[0], (uint32_t)Record[1], (uint32_t)Record[2], +            (uint32_t)Record[3], (uint32_t)Record[4]}}}; +      // We don't care about this record.    } @@ -680,7 +721,20 @@ public:  } -void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { +bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { +  for (auto MapEntry : ImportedModuleFiles) { +    auto *File = MapEntry.first; +    ImportedModuleFileInfo &Info = MapEntry.second; +    if (getModuleFileInfo(File).Signature) { +      if (getModuleFileInfo(File).Signature != Info.StoredSignature) +        // Verify Signature. +        return true; +    } else if (Info.StoredSize != File->getSize() || +               Info.StoredModTime != File->getModificationTime()) +      // Verify Size and ModTime. +      return true; +  } +    using namespace llvm;    // Emit the file header. @@ -756,6 +810,7 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) {    }    Stream.ExitBlock(); +  return false;  }  GlobalModuleIndex::ErrorCode @@ -816,7 +871,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr,    SmallVector<char, 16> OutputBuffer;    {      llvm::BitstreamWriter OutputStream(OutputBuffer); -    Builder.writeIndex(OutputStream); +    if (Builder.writeIndex(OutputStream)) +      return EC_IOError;    }    // Write the global index file to a temporary file.  | 
