Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 0fda0f7

Browse files
committed
Use llvm::sys::fs::UniqueID for windows and unix.
This unifies the unix and windows versions of FileManager::UniqueDirContainer and FileManager::UniqueFileContainer by using UniqueID. We cannot just replace "struct stat" with llvm::sys::fs::file_status, since we want to be able to construct fake ones, and file_status has different members on unix and windows. What the patch does is: * Record only the information that clang is actually using. * Use llvm::sys::fs::status instead of stat and fstat. * Use llvm::sys::fs::UniqueID * Delete the old windows versions of UniqueDirContainer and UniqueFileContainer since the "unix" one now works on windows too. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187619 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 1cf9ab8 commit 0fda0f7

File tree

10 files changed

+197
-249
lines changed

10 files changed

+197
-249
lines changed

Diff for: include/clang/Basic/FileManager.h

+16-15
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,22 @@ class FileEntry {
6363
time_t ModTime; // Modification time of file.
6464
const DirectoryEntry *Dir; // Directory file lives in.
6565
unsigned UID; // A unique (small) ID for the file.
66-
dev_t Device; // ID for the device containing the file.
67-
ino_t Inode; // Inode number for the file.
68-
mode_t FileMode; // The file mode as returned by 'stat'.
66+
llvm::sys::fs::UniqueID UniqueID;
67+
bool IsNamedPipe;
68+
bool InPCH;
6969

7070
/// FD - The file descriptor for the file entry if it is opened and owned
7171
/// by the FileEntry. If not, this is set to -1.
7272
mutable int FD;
7373
friend class FileManager;
7474

7575
public:
76-
FileEntry(dev_t device, ino_t inode, mode_t m)
77-
: Name(0), Device(device), Inode(inode), FileMode(m), FD(-1) {}
76+
FileEntry(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe, bool InPCH)
77+
: Name(0), UniqueID(UniqueID), IsNamedPipe(IsNamedPipe), InPCH(InPCH),
78+
FD(-1) {}
7879
// Add a default constructor for use with llvm::StringMap
79-
FileEntry() : Name(0), Device(0), Inode(0), FileMode(0), FD(-1) {}
80+
FileEntry()
81+
: Name(0), UniqueID(0, 0), IsNamedPipe(false), InPCH(false), FD(-1) {}
8082

8183
FileEntry(const FileEntry &FE) {
8284
memcpy(this, &FE, sizeof(FE));
@@ -93,23 +95,22 @@ class FileEntry {
9395
const char *getName() const { return Name; }
9496
off_t getSize() const { return Size; }
9597
unsigned getUID() const { return UID; }
96-
ino_t getInode() const { return Inode; }
97-
dev_t getDevice() const { return Device; }
98+
const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; }
99+
bool isInPCH() const { return InPCH; }
98100
time_t getModificationTime() const { return ModTime; }
99-
mode_t getFileMode() const { return FileMode; }
100101

101102
/// \brief Return the directory the file lives in.
102103
const DirectoryEntry *getDir() const { return Dir; }
103104

104-
bool operator<(const FileEntry &RHS) const {
105-
return Device < RHS.Device || (Device == RHS.Device && Inode < RHS.Inode);
106-
}
105+
bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; }
107106

108107
/// \brief Check whether the file is a named pipe (and thus can't be opened by
109108
/// the native FileManager methods).
110-
bool isNamedPipe() const;
109+
bool isNamedPipe() const { return IsNamedPipe; }
111110
};
112111

112+
struct FileData;
113+
113114
/// \brief Implements support for file system lookup, file system caching,
114115
/// and directory search management.
115116
///
@@ -170,8 +171,8 @@ class FileManager : public RefCountedBase<FileManager> {
170171
// Caching.
171172
OwningPtr<FileSystemStatCache> StatCache;
172173

173-
bool getStatValue(const char *Path, struct stat &StatBuf,
174-
bool isFile, int *FileDescriptor);
174+
bool getStatValue(const char *Path, FileData &Data, bool isFile,
175+
int *FileDescriptor);
175176

176177
/// Add all ancestors of the given path (pointing to either a file
177178
/// or a directory) as virtual directories.

Diff for: include/clang/Basic/FileSystemStatCache.h

+28-19
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,21 @@
1818
#include "clang/Basic/LLVM.h"
1919
#include "llvm/ADT/OwningPtr.h"
2020
#include "llvm/ADT/StringMap.h"
21+
#include "llvm/Support/FileSystem.h"
2122
#include <sys/stat.h>
2223
#include <sys/types.h>
2324

2425
namespace clang {
2526

27+
struct FileData {
28+
uint64_t Size;
29+
time_t ModTime;
30+
llvm::sys::fs::UniqueID UniqueID;
31+
bool IsDirectory;
32+
bool IsNamedPipe;
33+
bool InPCH;
34+
};
35+
2636
/// \brief Abstract interface for introducing a FileManager cache for 'stat'
2737
/// system calls, which is used by precompiled and pretokenized headers to
2838
/// improve performance.
@@ -49,10 +59,9 @@ class FileSystemStatCache {
4959
/// success for directories (not files). On a successful file lookup, the
5060
/// implementation can optionally fill in FileDescriptor with a valid
5161
/// descriptor and the client guarantees that it will close it.
52-
static bool get(const char *Path, struct stat &StatBuf,
53-
bool isFile, int *FileDescriptor, FileSystemStatCache *Cache);
54-
55-
62+
static bool get(const char *Path, FileData &Data, bool isFile,
63+
int *FileDescriptor, FileSystemStatCache *Cache);
64+
5665
/// \brief Sets the next stat call cache in the chain of stat caches.
5766
/// Takes ownership of the given stat cache.
5867
void setNextStatCache(FileSystemStatCache *Cache) {
@@ -68,18 +77,18 @@ class FileSystemStatCache {
6877
FileSystemStatCache *takeNextStatCache() { return NextStatCache.take(); }
6978

7079
protected:
71-
virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
72-
bool isFile, int *FileDescriptor) = 0;
80+
virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
81+
int *FileDescriptor) = 0;
7382

74-
LookupResult statChained(const char *Path, struct stat &StatBuf,
75-
bool isFile, int *FileDescriptor) {
83+
LookupResult statChained(const char *Path, FileData &Data, bool isFile,
84+
int *FileDescriptor) {
7685
if (FileSystemStatCache *Next = getNextStatCache())
77-
return Next->getStat(Path, StatBuf, isFile, FileDescriptor);
78-
86+
return Next->getStat(Path, Data, isFile, FileDescriptor);
87+
7988
// If we hit the end of the list of stat caches to try, just compute and
8089
// return it without a cache.
81-
return get(Path, StatBuf,
82-
isFile, FileDescriptor, 0) ? CacheMissing : CacheExists;
90+
return get(Path, Data, isFile, FileDescriptor, 0) ? CacheMissing
91+
: CacheExists;
8392
}
8493
};
8594

@@ -89,16 +98,16 @@ class FileSystemStatCache {
8998
class MemorizeStatCalls : public FileSystemStatCache {
9099
public:
91100
/// \brief The set of stat() calls that have been seen.
92-
llvm::StringMap<struct stat, llvm::BumpPtrAllocator> StatCalls;
93-
94-
typedef llvm::StringMap<struct stat, llvm::BumpPtrAllocator>::const_iterator
101+
llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls;
102+
103+
typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator
95104
iterator;
96-
105+
97106
iterator begin() const { return StatCalls.begin(); }
98107
iterator end() const { return StatCalls.end(); }
99-
100-
virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
101-
bool isFile, int *FileDescriptor);
108+
109+
virtual LookupResult getStat(const char *Path, FileData &Data, bool isFile,
110+
int *FileDescriptor);
102111
};
103112

104113
} // end namespace clang

Diff for: lib/Basic/FileManager.cpp

+27-104
Original file line numberDiff line numberDiff line change
@@ -63,91 +63,16 @@ FileEntry::~FileEntry() {
6363
if (FD != -1) ::close(FD);
6464
}
6565

66-
bool FileEntry::isNamedPipe() const {
67-
return S_ISFIFO(FileMode);
68-
}
69-
70-
//===----------------------------------------------------------------------===//
71-
// Windows.
72-
//===----------------------------------------------------------------------===//
73-
74-
#ifdef LLVM_ON_WIN32
75-
76-
namespace {
77-
static std::string GetFullPath(const char *relPath) {
78-
char *absPathStrPtr = _fullpath(NULL, relPath, 0);
79-
assert(absPathStrPtr && "_fullpath() returned NULL!");
80-
81-
std::string absPath(absPathStrPtr);
82-
83-
free(absPathStrPtr);
84-
return absPath;
85-
}
86-
}
87-
88-
class FileManager::UniqueDirContainer {
89-
/// UniqueDirs - Cache from full path to existing directories/files.
90-
///
91-
llvm::StringMap<DirectoryEntry> UniqueDirs;
92-
93-
public:
94-
/// getDirectory - Return an existing DirectoryEntry with the given
95-
/// name if there is already one; otherwise create and return a
96-
/// default-constructed DirectoryEntry.
97-
DirectoryEntry &getDirectory(const char *Name,
98-
const struct stat & /*StatBuf*/) {
99-
std::string FullPath(GetFullPath(Name));
100-
return UniqueDirs.GetOrCreateValue(FullPath).getValue();
101-
}
102-
103-
size_t size() const { return UniqueDirs.size(); }
104-
};
105-
106-
class FileManager::UniqueFileContainer {
107-
/// UniqueFiles - Cache from full path to existing directories/files.
108-
///
109-
llvm::StringMap<FileEntry, llvm::BumpPtrAllocator> UniqueFiles;
110-
111-
public:
112-
/// getFile - Return an existing FileEntry with the given name if
113-
/// there is already one; otherwise create and return a
114-
/// default-constructed FileEntry.
115-
FileEntry &getFile(const char *Name, const struct stat & /*StatBuf*/) {
116-
std::string FullPath(GetFullPath(Name));
117-
118-
// Lowercase string because Windows filesystem is case insensitive.
119-
FullPath = StringRef(FullPath).lower();
120-
return UniqueFiles.GetOrCreateValue(FullPath).getValue();
121-
}
122-
123-
size_t size() const { return UniqueFiles.size(); }
124-
125-
void erase(const FileEntry *Entry) {
126-
std::string FullPath(GetFullPath(Entry->getName()));
127-
128-
// Lowercase string because Windows filesystem is case insensitive.
129-
FullPath = StringRef(FullPath).lower();
130-
UniqueFiles.erase(FullPath);
131-
}
132-
};
133-
134-
//===----------------------------------------------------------------------===//
135-
// Unix-like Systems.
136-
//===----------------------------------------------------------------------===//
137-
138-
#else
139-
14066
class FileManager::UniqueDirContainer {
14167
/// UniqueDirs - Cache from ID's to existing directories/files.
142-
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
68+
std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueDirs;
14369

14470
public:
14571
/// getDirectory - Return an existing DirectoryEntry with the given
14672
/// ID's if there is already one; otherwise create and return a
14773
/// default-constructed DirectoryEntry.
148-
DirectoryEntry &getDirectory(const char * /*Name*/,
149-
const struct stat &StatBuf) {
150-
return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
74+
DirectoryEntry &getDirectory(const llvm::sys::fs::UniqueID &UniqueID) {
75+
return UniqueDirs[UniqueID];
15176
}
15277

15378
size_t size() const { return UniqueDirs.size(); }
@@ -161,21 +86,17 @@ class FileManager::UniqueFileContainer {
16186
/// getFile - Return an existing FileEntry with the given ID's if
16287
/// there is already one; otherwise create and return a
16388
/// default-constructed FileEntry.
164-
FileEntry &getFile(const char * /*Name*/, const struct stat &StatBuf) {
165-
return
166-
const_cast<FileEntry&>(
167-
*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
168-
StatBuf.st_ino,
169-
StatBuf.st_mode)).first);
89+
FileEntry &getFile(llvm::sys::fs::UniqueID UniqueID, bool IsNamedPipe,
90+
bool InPCH) {
91+
return const_cast<FileEntry &>(
92+
*UniqueFiles.insert(FileEntry(UniqueID, IsNamedPipe, InPCH)).first);
17093
}
17194

17295
size_t size() const { return UniqueFiles.size(); }
17396

17497
void erase(const FileEntry *Entry) { UniqueFiles.erase(*Entry); }
17598
};
17699

177-
#endif
178-
179100
//===----------------------------------------------------------------------===//
180101
// Common logic.
181102
//===----------------------------------------------------------------------===//
@@ -323,8 +244,8 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
323244
const char *InterndDirName = NamedDirEnt.getKeyData();
324245

325246
// Check to see if the directory exists.
326-
struct stat StatBuf;
327-
if (getStatValue(InterndDirName, StatBuf, false, 0/*directory lookup*/)) {
247+
FileData Data;
248+
if (getStatValue(InterndDirName, Data, false, 0 /*directory lookup*/)) {
328249
// There's no real directory at the given path.
329250
if (!CacheFailure)
330251
SeenDirEntries.erase(DirName);
@@ -335,7 +256,8 @@ const DirectoryEntry *FileManager::getDirectory(StringRef DirName,
335256
// same inode (this occurs on Unix-like systems when one dir is
336257
// symlinked to another, for example) or the same path (on
337258
// Windows).
338-
DirectoryEntry &UDE = UniqueRealDirs.getDirectory(InterndDirName, StatBuf);
259+
DirectoryEntry &UDE =
260+
UniqueRealDirs.getDirectory(Data.UniqueID);
339261

340262
NamedDirEnt.setValue(&UDE);
341263
if (!UDE.getName()) {
@@ -388,8 +310,8 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
388310

389311
// Nope, there isn't. Check to see if the file exists.
390312
int FileDescriptor = -1;
391-
struct stat StatBuf;
392-
if (getStatValue(InterndFileName, StatBuf, true,
313+
FileData Data;
314+
if (getStatValue(InterndFileName, Data, true,
393315
openFile ? &FileDescriptor : 0)) {
394316
// There's no real file at the given path.
395317
if (!CacheFailure)
@@ -405,7 +327,8 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
405327

406328
// It exists. See if we have already opened a file with the same inode.
407329
// This occurs when one dir is symlinked to another, for example.
408-
FileEntry &UFE = UniqueRealFiles.getFile(InterndFileName, StatBuf);
330+
FileEntry &UFE =
331+
UniqueRealFiles.getFile(Data.UniqueID, Data.IsNamedPipe, Data.InPCH);
409332

410333
NamedFileEnt.setValue(&UFE);
411334
if (UFE.getName()) { // Already have an entry with this inode, return it.
@@ -420,8 +343,8 @@ const FileEntry *FileManager::getFile(StringRef Filename, bool openFile,
420343
// FIXME: Change the name to be a char* that points back to the
421344
// 'SeenFileEntries' key.
422345
UFE.Name = InterndFileName;
423-
UFE.Size = StatBuf.st_size;
424-
UFE.ModTime = StatBuf.st_mtime;
346+
UFE.Size = Data.Size;
347+
UFE.ModTime = Data.ModTime;
425348
UFE.Dir = DirInfo;
426349
UFE.UID = NextFileUID++;
427350
UFE.FD = FileDescriptor;
@@ -458,12 +381,12 @@ FileManager::getVirtualFile(StringRef Filename, off_t Size,
458381
"The directory of a virtual file should already be in the cache.");
459382

460383
// Check to see if the file exists. If so, drop the virtual file
461-
struct stat StatBuf;
384+
FileData Data;
462385
const char *InterndFileName = NamedFileEnt.getKeyData();
463-
if (getStatValue(InterndFileName, StatBuf, true, 0) == 0) {
464-
StatBuf.st_size = Size;
465-
StatBuf.st_mtime = ModificationTime;
466-
UFE = &UniqueRealFiles.getFile(InterndFileName, StatBuf);
386+
if (getStatValue(InterndFileName, Data, true, 0) == 0) {
387+
Data.Size = Size;
388+
Data.ModTime = ModificationTime;
389+
UFE = &UniqueRealFiles.getFile(Data.UniqueID, Data.IsNamedPipe, Data.InPCH);
467390

468391
NamedFileEnt.setValue(UFE);
469392

@@ -572,19 +495,19 @@ getBufferForFile(StringRef Filename, std::string *ErrorStr) {
572495
/// if the path points to a virtual file or does not exist, or returns
573496
/// false if it's an existent real file. If FileDescriptor is NULL,
574497
/// do directory look-up instead of file look-up.
575-
bool FileManager::getStatValue(const char *Path, struct stat &StatBuf,
576-
bool isFile, int *FileDescriptor) {
498+
bool FileManager::getStatValue(const char *Path, FileData &Data, bool isFile,
499+
int *FileDescriptor) {
577500
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
578501
// absolute!
579502
if (FileSystemOpts.WorkingDir.empty())
580-
return FileSystemStatCache::get(Path, StatBuf, isFile, FileDescriptor,
503+
return FileSystemStatCache::get(Path, Data, isFile, FileDescriptor,
581504
StatCache.get());
582505

583506
SmallString<128> FilePath(Path);
584507
FixupRelativePath(FilePath);
585508

586-
return FileSystemStatCache::get(FilePath.c_str(), StatBuf,
587-
isFile, FileDescriptor, StatCache.get());
509+
return FileSystemStatCache::get(FilePath.c_str(), Data, isFile,
510+
FileDescriptor, StatCache.get());
588511
}
589512

590513
bool FileManager::getNoncachedStatValue(StringRef Path,

0 commit comments

Comments
 (0)