diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-02-05 19:42:43 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-02-05 19:42:43 +0000 |
commit | 606c4ac32536be0534e077ee730e6f9085eff3ab (patch) | |
tree | eb1ea38b964d12a13dbf894daf32c3f1c0f73b58 /clang/lib/Basic/FileManager.cpp | |
parent | 0890502f44a1f65f1216c7b0658656dcbf8d3054 (diff) | |
download | bcm5719-llvm-606c4ac32536be0534e077ee730e6f9085eff3ab.tar.gz bcm5719-llvm-606c4ac32536be0534e077ee730e6f9085eff3ab.zip |
Improve our uniquing of file entries when files are re-saved or are
overridden via remapping. Thus, when we create a "virtual" file in the
file manager, we still stat() the real file that lives behind it so
that we can provide proper uniquing based on inodes. This helps keep
the file manager much more consistent.
To take advantage of this when reparsing files in libclang, we disable
the use of the stat() cache when reparsing or performing code
completion, since the stat() cache is very likely to be out of date in
this use case.
llvm-svn: 124971
Diffstat (limited to 'clang/lib/Basic/FileManager.cpp')
-rw-r--r-- | clang/lib/Basic/FileManager.cpp | 57 |
1 files changed, 36 insertions, 21 deletions
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index cbe90bfdc16..138b54cc086 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -359,12 +359,43 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, NamedFileEnt.setValue(NON_EXISTENT_FILE); // We allow the directory to not exist. If it does exist we store it. - // + FileEntry *UFE = 0; const DirectoryEntry *DirInfo = getDirectoryFromFile(*this, Filename); + if (DirInfo) { + // Check to see if the file exists. If so, drop the virtual file + int FileDescriptor = -1; + struct stat StatBuf; + const char *InterndFileName = NamedFileEnt.getKeyData(); + if (getStatValue(InterndFileName, StatBuf, &FileDescriptor) == 0) { + // If the stat process opened the file, close it to avoid a FD leak. + if (FileDescriptor != -1) + close(FileDescriptor); + + StatBuf.st_size = Size; + StatBuf.st_mtime = ModificationTime; + UFE = &UniqueFiles.getFile(InterndFileName, StatBuf); + + NamedFileEnt.setValue(UFE); + + // If we had already opened this file, close it now so we don't + // leak the descriptor. We're not going to use the file + // descriptor anyway, since this is a virtual file. + if (UFE->FD != -1) { + close(UFE->FD); + UFE->FD = -1; + } + + // If we already have an entry with this inode, return it. + if (UFE->getName()) + return UFE; + } + } - FileEntry *UFE = new FileEntry(); - VirtualFileEntries.push_back(UFE); - NamedFileEnt.setValue(UFE); + if (!UFE) { + UFE = new FileEntry(); + VirtualFileEntries.push_back(UFE); + NamedFileEnt.setValue(UFE); + } // Get the null-terminated file name as stored as the key of the // FileEntries map. @@ -375,23 +406,7 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size, UFE->ModTime = ModificationTime; UFE->Dir = DirInfo; UFE->UID = NextFileUID++; - - // If this virtual file resolves to a file, also map that file to the - // newly-created file entry. - int FileDescriptor = -1; - struct stat StatBuf; - if (getStatValue(InterndFileName, StatBuf, &FileDescriptor)) { - // If the stat process opened the file, close it to avoid a FD leak. - if (FileDescriptor != -1) - close(FileDescriptor); - - return UFE; - } - - UFE->FD = FileDescriptor; - llvm::SmallString<128> FilePath(UFE->Name); - llvm::sys::fs::make_absolute(FilePath); - FileEntries[FilePath] = UFE; + UFE->FD = -1; return UFE; } |