Index: include/clang/Frontend/ASTUnit.h =================================================================== --- include/clang/Frontend/ASTUnit.h +++ include/clang/Frontend/ASTUnit.h @@ -518,6 +518,8 @@ const FileManager &getFileManager() const { return *FileMgr; } FileManager &getFileManager() { return *FileMgr; } + void recreateFileManager(); + const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } IntrusiveRefCntPtr getASTReader() const; Index: lib/Frontend/ASTUnit.cpp =================================================================== --- lib/Frontend/ASTUnit.cpp +++ lib/Frontend/ASTUnit.cpp @@ -241,6 +241,10 @@ this->PP = std::move(PP); } +void ASTUnit::recreateFileManager() { + FileMgr = new FileManager(FileMgr->getFileSystemOpts()); +} + /// \brief Determine the set of code-completion contexts in which this /// declaration should be shown. static unsigned getDeclShowContexts(const NamedDecl *ND, @@ -1311,6 +1315,10 @@ /// this routine will determine if it is still valid and, if so, avoid /// rebuilding the precompiled preamble. /// +/// The caller is required to recreate the FileMgr before calling this routine +/// to ensure a clean stat cache and on the other hand that the stats done here +/// can be reused for e.g. Reparse(). +/// /// \param AllowRebuild When true (the default), this routine is /// allowed to rebuild the precompiled preamble if it is found to be /// out-of-date. @@ -1368,30 +1376,30 @@ if (AnyFileChanged) break; - vfs::Status Status; - if (FileMgr->getNoncachedStatValue(R.second, Status)) { + const FileEntry *fileEntry = FileMgr->getFile(R.second); + if (!fileEntry) { // If we can't stat the file we're remapping to, assume that something // horrible happened. AnyFileChanged = true; break; } - OverriddenFiles[Status.getUniqueID()] = PreambleFileHash::createForFile( - Status.getSize(), - llvm::sys::toTimeT(Status.getLastModificationTime())); + OverriddenFiles[fileEntry->getUniqueID()] = PreambleFileHash::createForFile( + fileEntry->getSize(), + fileEntry->getModificationTime()); } for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) { if (AnyFileChanged) break; - vfs::Status Status; - if (FileMgr->getNoncachedStatValue(RB.first, Status)) { + const FileEntry *fileEntry = FileMgr->getFile(RB.first); + if (!fileEntry) { AnyFileChanged = true; break; } - OverriddenFiles[Status.getUniqueID()] = + OverriddenFiles[fileEntry->getUniqueID()] = PreambleFileHash::createForMemoryBuffer(RB.second); } @@ -1400,15 +1408,15 @@ F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end(); !AnyFileChanged && F != FEnd; ++F) { - vfs::Status Status; - if (FileMgr->getNoncachedStatValue(F->first(), Status)) { + const FileEntry *fileEntry = FileMgr->getFile(F->first()); + if (!fileEntry) { // If we can't stat the file, assume that something horrible happened. AnyFileChanged = true; break; } std::map::iterator Overridden - = OverriddenFiles.find(Status.getUniqueID()); + = OverriddenFiles.find(fileEntry->getUniqueID()); if (Overridden != OverriddenFiles.end()) { // This file was remapped; check whether the newly-mapped file // matches up with the previous mapping. @@ -1416,11 +1424,10 @@ AnyFileChanged = true; continue; } - + // The file was not remapped; check whether it has changed on disk. - if (Status.getSize() != uint64_t(F->second.Size) || - llvm::sys::toTimeT(Status.getLastModificationTime()) != - F->second.ModTime) + if (fileEntry->getSize() != F->second.Size || + fileEntry->getModificationTime() != F->second.ModTime) AnyFileChanged = true; } @@ -1873,6 +1880,8 @@ getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); + recreateFileManager(); + std::unique_ptr OverrideMainBuffer; if (PrecompilePreambleAfterNParses > 0) { PreambleRebuildCounter = PrecompilePreambleAfterNParses; @@ -2040,6 +2049,8 @@ RemappedFile.second); } + recreateFileManager(); + // If we have a preamble file lying around, or if we might try to // build a precompiled preamble, do so now. std::unique_ptr OverrideMainBuffer; @@ -2048,7 +2059,6 @@ getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); // Clear out the diagnostics state. - FileMgr.reset(); getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); if (OverrideMainBuffer) Index: tools/libclang/CIndexCodeCompletion.cpp =================================================================== --- tools/libclang/CIndexCodeCompletion.cpp +++ tools/libclang/CIndexCodeCompletion.cpp @@ -680,6 +680,7 @@ } // Parse the resulting source file to find code-completion results. + AST->recreateFileManager(); AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults( &AST->getFileManager()); Results->Results = nullptr;