summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/FileManager.h9
-rw-r--r--clang/lib/Basic/FileManager.cpp95
-rw-r--r--clang/lib/Frontend/InitPreprocessor.cpp9
-rw-r--r--clang/test/Misc/Inputs/remapped-file-23
-rw-r--r--clang/test/Misc/Inputs/remapped-file-32
-rw-r--r--clang/test/Misc/remap-file.c9
6 files changed, 98 insertions, 29 deletions
diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h
index 5e7ac4f3c85..d0e0118d99d 100644
--- a/clang/include/clang/Basic/FileManager.h
+++ b/clang/include/clang/Basic/FileManager.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_FILEMANAGER_H
#define LLVM_CLANG_FILEMANAGER_H
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/OwningPtr.h"
@@ -151,6 +152,9 @@ class FileManager {
///
unsigned NextFileUID;
+ /// \brief The virtual files that we have allocated.
+ llvm::SmallVector<FileEntry *, 4> VirtualFileEntries;
+
// Statistics.
unsigned NumDirLookups, NumFileLookups;
unsigned NumDirCacheMisses, NumFileCacheMisses;
@@ -199,6 +203,11 @@ public:
const FileEntry *getFile(const char *FilenameStart,
const char *FilenameEnd);
+ /// \brief Retrieve a file entry for a "virtual" file that acts as
+ /// if there were a file with the given name on disk. The file
+ /// itself is not accessed.
+ const FileEntry *getVirtualFile(const llvm::StringRef &Filename,
+ off_t Size, time_t ModificationTime);
void PrintStats() const;
};
diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp
index ee4309de937..9c5f1d59c19 100644
--- a/clang/lib/Basic/FileManager.cpp
+++ b/clang/lib/Basic/FileManager.cpp
@@ -147,6 +147,12 @@ FileManager::FileManager()
FileManager::~FileManager() {
delete &UniqueDirs;
delete &UniqueFiles;
+ for (llvm::SmallVectorImpl<FileEntry *>::iterator
+ V = VirtualFileEntries.begin(),
+ VEnd = VirtualFileEntries.end();
+ V != VEnd;
+ ++V)
+ delete *V;
}
void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) {
@@ -184,6 +190,30 @@ void FileManager::removeStatCache(StatSysCallCache *statCache) {
assert(false && "Stat cache not found for removal");
}
+/// \brief Retrieve the directory that the given file name resides in.
+static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
+ const char *NameStart,
+ const char *NameEnd) {
+ // Figure out what directory it is in. If the string contains a / in it,
+ // strip off everything after it.
+ // FIXME: this logic should be in sys::Path.
+ const char *SlashPos = NameEnd-1;
+ while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
+ --SlashPos;
+ // Ignore duplicate //'s.
+ while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1]))
+ --SlashPos;
+
+ if (SlashPos < NameStart) {
+ // Use the current directory if file has no path component.
+ const char *Name = ".";
+ return FileMgr.getDirectory(Name, Name+1);
+ } else if (SlashPos == NameEnd-1)
+ return 0; // If filename ends with a /, it's a directory.
+ else
+ return FileMgr.getDirectory(NameStart, SlashPos);
+}
+
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
///
@@ -252,33 +282,16 @@ const FileEntry *FileManager::getFile(const char *NameStart,
// By default, initialize it to invalid.
NamedFileEnt.setValue(NON_EXISTENT_FILE);
- // Figure out what directory it is in. If the string contains a / in it,
- // strip off everything after it.
- // FIXME: this logic should be in sys::Path.
- const char *SlashPos = NameEnd-1;
- while (SlashPos >= NameStart && !IS_DIR_SEPARATOR_CHAR(SlashPos[0]))
- --SlashPos;
- // Ignore duplicate //'s.
- while (SlashPos > NameStart && IS_DIR_SEPARATOR_CHAR(SlashPos[-1]))
- --SlashPos;
-
- const DirectoryEntry *DirInfo;
- if (SlashPos < NameStart) {
- // Use the current directory if file has no path component.
- const char *Name = ".";
- DirInfo = getDirectory(Name, Name+1);
- } else if (SlashPos == NameEnd-1)
- return 0; // If filename ends with a /, it's a directory.
- else
- DirInfo = getDirectory(NameStart, SlashPos);
-
- if (DirInfo == 0) // Directory doesn't exist, file can't exist.
- return 0;
// Get the null-terminated file name as stored as the key of the
// FileEntries map.
const char *InterndFileName = NamedFileEnt.getKeyData();
+ const DirectoryEntry *DirInfo
+ = getDirectoryFromFile(*this, NameStart, NameEnd);
+ if (DirInfo == 0) // Directory doesn't exist, file can't exist.
+ return 0;
+
// FIXME: Use the directory info to prune this, before doing the stat syscall.
// FIXME: This will reduce the # syscalls.
@@ -312,6 +325,44 @@ const FileEntry *FileManager::getFile(const char *NameStart,
return &UFE;
}
+const FileEntry *
+FileManager::getVirtualFile(const llvm::StringRef &Filename,
+ off_t Size, time_t ModificationTime) {
+ const char *NameStart = Filename.begin(), *NameEnd = Filename.end();
+
+ ++NumFileLookups;
+
+ // See if there is already an entry in the map.
+ llvm::StringMapEntry<FileEntry *> &NamedFileEnt =
+ FileEntries.GetOrCreateValue(NameStart, NameEnd);
+
+ // See if there is already an entry in the map.
+ if (NamedFileEnt.getValue())
+ return NamedFileEnt.getValue() == NON_EXISTENT_FILE
+ ? 0 : NamedFileEnt.getValue();
+
+ ++NumFileCacheMisses;
+
+ // By default, initialize it to invalid.
+ NamedFileEnt.setValue(NON_EXISTENT_FILE);
+
+ const DirectoryEntry *DirInfo
+ = getDirectoryFromFile(*this, NameStart, NameEnd);
+ if (DirInfo == 0) // Directory doesn't exist, file can't exist.
+ return 0;
+
+ FileEntry *UFE = new FileEntry();
+ VirtualFileEntries.push_back(UFE);
+ NamedFileEnt.setValue(UFE);
+
+ UFE->Name = NamedFileEnt.getKeyData();
+ UFE->Size = Size;
+ UFE->ModTime = ModificationTime;
+ UFE->Dir = DirInfo;
+ UFE->UID = NextFileUID++;
+ return UFE;
+}
+
void FileManager::PrintStats() const {
llvm::errs() << "\n*** File Manager Stats:\n";
llvm::errs() << UniqueFiles.size() << " files found, "
diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 9c42993cf05..aa05b34ef5c 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -19,6 +19,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Path.h"
@@ -502,11 +503,11 @@ static void InitializeFileRemapping(Diagnostic &Diags,
continue;
}
- // Find the file that we're mapping from.
- const FileEntry *FromFile = FileMgr.getFile(Remap->first);
+ // Create the file entry for the file that we're mapping from.
+ const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
+ ToFile->getSize(),
+ 0);
if (!FromFile) {
- // FIXME: We could actually recover from this, by faking a
- // FileEntry based on the "ToFile".
Diags.Report(diag::err_fe_remap_missing_from_file)
<< Remap->first;
continue;
diff --git a/clang/test/Misc/Inputs/remapped-file-2 b/clang/test/Misc/Inputs/remapped-file-2
new file mode 100644
index 00000000000..9ac034a3b97
--- /dev/null
+++ b/clang/test/Misc/Inputs/remapped-file-2
@@ -0,0 +1,3 @@
+#include "nonexistent.h"
+
+int *f() { return fp; }
diff --git a/clang/test/Misc/Inputs/remapped-file-3 b/clang/test/Misc/Inputs/remapped-file-3
new file mode 100644
index 00000000000..b7ab613367d
--- /dev/null
+++ b/clang/test/Misc/Inputs/remapped-file-3
@@ -0,0 +1,2 @@
+extern float *fp;
+
diff --git a/clang/test/Misc/remap-file.c b/clang/test/Misc/remap-file.c
index e8aa3e44cc9..da10590ccd6 100644
--- a/clang/test/Misc/remap-file.c
+++ b/clang/test/Misc/remap-file.c
@@ -1,5 +1,8 @@
-// RUN: clang-cc -remap-file="%s;%S/Inputs/remapped-file" -fsyntax-only %s 2>&1 | FileCheck %s
-
-// CHECK: remap-file.c:1:28: warning: incompatible pointer types
+// RUN: clang-cc -remap-file="%s;%S/Inputs/remapped-file" -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-EXIST %s
+// RUN: clang-cc -remap-file="%S/nonexistent.c;%S/Inputs/remapped-file" -fsyntax-only %S/nonexistent.c 2>&1 | FileCheck -check-prefix=CHECK-NONEXIST %s
+// RUN: clang-cc -remap-file="%S/nonexistent.c;%S/Inputs/remapped-file-2" -remap-file="%S/nonexistent.h;%S/Inputs/remapped-file-3" -fsyntax-only %S/nonexistent.c 2>&1 | FileCheck -check-prefix=CHECK-HEADER %s
+// CHECK-EXIST: remap-file.c:1:28: warning: incompatible pointer types
+// CHECK-NONEXIST: nonexistent.c:1:28: warning: incompatible pointer types
+// CHECK-HEADER: nonexistent.c:3:19: warning: incompatible pointer types
int
OpenPOWER on IntegriCloud