зеркало из https://github.com/microsoft/clang-1.git
In FileManager: use full paths to unique files and directories on Windows,
since inodes are bogus abstraction on that platform. Patch by Argiris Kirtzidis! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47535 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
10c5fa3b17
Коммит
6bb816a3b8
|
@ -22,6 +22,7 @@
|
|||
#include "llvm/Bitcode/Serialize.h"
|
||||
#include "llvm/Bitcode/Deserialize.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include "llvm/Config/config.h"
|
||||
using namespace clang;
|
||||
|
||||
// FIXME: Enhance libsystem to support inode and other fields.
|
||||
|
@ -35,6 +36,107 @@ using namespace clang;
|
|||
/// represent a dir name that doesn't exist on the disk.
|
||||
#define NON_EXISTENT_DIR reinterpret_cast<DirectoryEntry*>((intptr_t)-1)
|
||||
|
||||
#ifdef LLVM_ON_WIN32
|
||||
|
||||
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/' || (x) == '\\')
|
||||
|
||||
namespace {
|
||||
static std::string GetFullPath(const char *relPath)
|
||||
{
|
||||
char *absPathStrPtr = _fullpath(NULL, relPath, 0);
|
||||
assert(absPathStrPtr && "_fullpath() returned NULL!");
|
||||
|
||||
std::string absPath(absPathStrPtr);
|
||||
|
||||
free(absPathStrPtr);
|
||||
return absPath;
|
||||
}
|
||||
}
|
||||
|
||||
class FileManager::UniqueDirContainer {
|
||||
/// UniqueDirs - Cache from full path to existing directories/files.
|
||||
///
|
||||
llvm::StringMap<DirectoryEntry> UniqueDirs;
|
||||
|
||||
public:
|
||||
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
|
||||
std::string FullPath(GetFullPath(Name));
|
||||
return UniqueDirs.GetOrCreateValue(
|
||||
FullPath.c_str(),
|
||||
FullPath.c_str() + FullPath.size()
|
||||
).getValue();
|
||||
}
|
||||
|
||||
size_t size() { return UniqueDirs.size(); }
|
||||
};
|
||||
|
||||
class FileManager::UniqueFileContainer {
|
||||
/// UniqueFiles - Cache from full path to existing directories/files.
|
||||
///
|
||||
llvm::StringMap<FileEntry> UniqueFiles;
|
||||
|
||||
public:
|
||||
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
|
||||
std::string FullPath(GetFullPath(Name));
|
||||
return UniqueFiles.GetOrCreateValue(
|
||||
FullPath.c_str(),
|
||||
FullPath.c_str() + FullPath.size()
|
||||
).getValue();
|
||||
}
|
||||
|
||||
size_t size() { return UniqueFiles.size(); }
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define IS_DIR_SEPARATOR_CHAR(x) ((x) == '/')
|
||||
|
||||
class FileManager::UniqueDirContainer {
|
||||
/// UniqueDirs - Cache from ID's to existing directories/files.
|
||||
///
|
||||
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
|
||||
|
||||
public:
|
||||
DirectoryEntry &getDirectory(const char *Name, struct stat &StatBuf) {
|
||||
return UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
|
||||
}
|
||||
|
||||
size_t size() { return UniqueDirs.size(); }
|
||||
};
|
||||
|
||||
class FileManager::UniqueFileContainer {
|
||||
/// UniqueFiles - Cache from ID's to existing directories/files.
|
||||
///
|
||||
std::set<FileEntry> UniqueFiles;
|
||||
|
||||
public:
|
||||
FileEntry &getFile(const char *Name, struct stat &StatBuf) {
|
||||
return
|
||||
const_cast<FileEntry&>(
|
||||
*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
|
||||
StatBuf.st_ino)).first);
|
||||
}
|
||||
|
||||
size_t size() { return UniqueFiles.size(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
FileManager::FileManager() : UniqueDirs(*new UniqueDirContainer),
|
||||
UniqueFiles(*new UniqueFileContainer),
|
||||
DirEntries(64), FileEntries(64), NextFileUID(0)
|
||||
{
|
||||
NumDirLookups = NumFileLookups = 0;
|
||||
NumDirCacheMisses = NumFileCacheMisses = 0;
|
||||
}
|
||||
|
||||
FileManager::~FileManager() {
|
||||
delete &UniqueDirs;
|
||||
delete &UniqueFiles;
|
||||
}
|
||||
|
||||
|
||||
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
||||
/// returns null if the directory doesn't exist.
|
||||
///
|
||||
|
@ -63,11 +165,10 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
|
|||
if (stat(InterndDirName, &StatBuf) || // Error stat'ing.
|
||||
!S_ISDIR(StatBuf.st_mode)) // Not a directory?
|
||||
return 0;
|
||||
|
||||
|
||||
// It exists. See if we have already opened a directory with the same inode.
|
||||
// This occurs when one dir is symlinked to another, for example.
|
||||
DirectoryEntry &UDE =
|
||||
UniqueDirs[std::make_pair(StatBuf.st_dev, StatBuf.st_ino)];
|
||||
DirectoryEntry &UDE = UniqueDirs.getDirectory(InterndDirName, StatBuf);
|
||||
|
||||
NamedDirEnt.setValue(&UDE);
|
||||
if (UDE.getName()) // Already have an entry with this inode, return it.
|
||||
|
@ -108,7 +209,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
|
|||
// strip off everything after it.
|
||||
// FIXME: this logic should be in sys::Path.
|
||||
const char *SlashPos = NameEnd-1;
|
||||
while (SlashPos >= NameStart && SlashPos[0] != '/')
|
||||
while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
|
||||
--SlashPos;
|
||||
|
||||
const DirectoryEntry *DirInfo;
|
||||
|
@ -144,10 +245,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
|
|||
|
||||
// It exists. See if we have already opened a file with the same inode.
|
||||
// This occurs when one dir is symlinked to another, for example.
|
||||
FileEntry &UFE =
|
||||
const_cast<FileEntry&>(*UniqueFiles.insert(FileEntry(StatBuf.st_dev,
|
||||
StatBuf.st_ino)).first);
|
||||
|
||||
FileEntry &UFE = UniqueFiles.getFile(InterndFileName, StatBuf);
|
||||
|
||||
NamedFileEnt.setValue(&UFE);
|
||||
if (UFE.getName()) // Already have an entry with this inode, return it.
|
||||
|
|
|
@ -48,6 +48,8 @@ class FileEntry {
|
|||
friend class FileManager;
|
||||
public:
|
||||
FileEntry(dev_t device, ino_t inode) : Name(0), Device(device), Inode(inode){}
|
||||
// Add a default constructor for use with llvm::StringMap
|
||||
FileEntry() : Name(0), Device(0), Inode(0) {}
|
||||
|
||||
const char *getName() const { return Name; }
|
||||
off_t getSize() const { return Size; }
|
||||
|
@ -72,11 +74,15 @@ public:
|
|||
/// names (e.g. symlinked) will be treated as a single file.
|
||||
///
|
||||
class FileManager {
|
||||
/// UniqueDirs/UniqueFiles - Cache from ID's to existing directories/files.
|
||||
|
||||
class UniqueDirContainer;
|
||||
class UniqueFileContainer;
|
||||
|
||||
/// UniqueDirs/UniqueFiles - Cache for existing directories/files.
|
||||
///
|
||||
std::map<std::pair<dev_t, ino_t>, DirectoryEntry> UniqueDirs;
|
||||
std::set<FileEntry> UniqueFiles;
|
||||
|
||||
UniqueDirContainer &UniqueDirs;
|
||||
UniqueFileContainer &UniqueFiles;
|
||||
|
||||
/// DirEntries/FileEntries - This is a cache of directory/file entries we have
|
||||
/// looked up. The actual Entry is owned by UniqueFiles/UniqueDirs above.
|
||||
///
|
||||
|
@ -91,10 +97,8 @@ class FileManager {
|
|||
unsigned NumDirLookups, NumFileLookups;
|
||||
unsigned NumDirCacheMisses, NumFileCacheMisses;
|
||||
public:
|
||||
FileManager() : DirEntries(64), FileEntries(64), NextFileUID(0) {
|
||||
NumDirLookups = NumFileLookups = 0;
|
||||
NumDirCacheMisses = NumFileCacheMisses = 0;
|
||||
}
|
||||
FileManager();
|
||||
~FileManager();
|
||||
|
||||
/// getDirectory - Lookup, cache, and verify the specified directory. This
|
||||
/// returns null if the directory doesn't exist.
|
||||
|
|
Загрузка…
Ссылка в новой задаче