aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTImporter.h7
-rw-r--r--include/clang/Basic/FileManager.h63
-rw-r--r--include/clang/Basic/FileSystemOptions.h29
-rw-r--r--include/clang/Basic/SourceManager.h15
-rw-r--r--include/clang/Driver/CC1Options.td5
-rw-r--r--include/clang/Driver/Options.td5
-rw-r--r--include/clang/Frontend/ASTUnit.h15
-rw-r--r--include/clang/Frontend/CompilerInstance.h9
-rw-r--r--include/clang/Frontend/CompilerInvocation.h9
-rw-r--r--include/clang/Frontend/Utils.h2
-rw-r--r--include/clang/Lex/HeaderMap.h7
-rw-r--r--include/clang/Lex/HeaderSearch.h5
-rw-r--r--include/clang/Lex/PTHManager.h4
-rw-r--r--include/clang/Lex/Preprocessor.h3
-rw-r--r--include/clang/Serialization/ASTReader.h7
-rw-r--r--lib/AST/ASTImporter.cpp8
-rw-r--r--lib/Basic/FileManager.cpp60
-rw-r--r--lib/Basic/SourceManager.cpp7
-rw-r--r--lib/Driver/Driver.cpp17
-rw-r--r--lib/Driver/Tools.cpp2
-rw-r--r--lib/Frontend/ASTMerge.cpp7
-rw-r--r--lib/Frontend/ASTUnit.cpp33
-rw-r--r--lib/Frontend/CompilerInstance.cpp32
-rw-r--r--lib/Frontend/CompilerInvocation.cpp28
-rw-r--r--lib/Frontend/FrontendAction.cpp5
-rw-r--r--lib/Frontend/FrontendActions.cpp5
-rw-r--r--lib/Frontend/InitHeaderSearch.cpp5
-rw-r--r--lib/Frontend/InitPreprocessor.cpp12
-rw-r--r--lib/Lex/HeaderMap.cpp10
-rw-r--r--lib/Lex/HeaderSearch.cpp30
-rw-r--r--lib/Lex/PTHLexer.cpp6
-rw-r--r--lib/Lex/Preprocessor.cpp3
-rw-r--r--lib/Serialization/ASTReader.cpp17
-rw-r--r--test/Misc/Inputs/working-directory.h1
-rw-r--r--test/Misc/working-directory.c5
-rw-r--r--tools/libclang/CIndex.cpp7
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp11
-rw-r--r--tools/libclang/CIndexer.h6
38 files changed, 398 insertions, 104 deletions
diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h
index a1c4d5399e..1ad33990f2 100644
--- a/include/clang/AST/ASTImporter.h
+++ b/include/clang/AST/ASTImporter.h
@@ -28,6 +28,7 @@ namespace clang {
class Diagnostic;
class Expr;
class FileManager;
+ class FileSystemOptions;
class IdentifierInfo;
class NestedNameSpecifier;
class Stmt;
@@ -45,6 +46,8 @@ namespace clang {
/// \brief The file managers we're importing to and from.
FileManager &ToFileManager, &FromFileManager;
+
+ const FileSystemOptions &ToFileSystemOpts, &FromFileSystemOpts;
/// \brief The diagnostics object that we should use to emit diagnostics.
Diagnostic &Diags;
@@ -76,7 +79,9 @@ namespace clang {
public:
ASTImporter(Diagnostic &Diags,
ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager);
+ const FileSystemOptions &ToFileSystemOpts,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ const FileSystemOptions &FromFileSystemOpts);
virtual ~ASTImporter();
diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h
index e71f51a0e7..44a7079edd 100644
--- a/include/clang/Basic/FileManager.h
+++ b/include/clang/Basic/FileManager.h
@@ -24,8 +24,16 @@
#include <sys/types.h>
#include <sys/stat.h>
+namespace llvm {
+class MemoryBuffer;
+namespace sys {
+class Path;
+}
+}
+
namespace clang {
class FileManager;
+class FileSystemOptions;
/// DirectoryEntry - Cached information about one directory on the disk.
///
@@ -162,9 +170,8 @@ class FileManager {
// Caching.
llvm::OwningPtr<StatSysCallCache> StatCache;
- int stat_cached(const char* path, struct stat* buf) {
- return StatCache.get() ? StatCache->stat(path, buf) : stat(path, buf);
- }
+ int stat_cached(const char* path, struct stat* buf,
+ const FileSystemOptions &FileSystemOpts);
public:
FileManager();
@@ -189,25 +196,61 @@ public:
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
///
- const DirectoryEntry *getDirectory(llvm::StringRef Filename) {
- return getDirectory(Filename.begin(), Filename.end());
+ const DirectoryEntry *getDirectory(llvm::StringRef Filename,
+ const FileSystemOptions &FileSystemOpts) {
+ return getDirectory(Filename.begin(), Filename.end(), FileSystemOpts);
}
- const DirectoryEntry *getDirectory(const char *FileStart,const char *FileEnd);
+ const DirectoryEntry *getDirectory(const char *FileStart,const char *FileEnd,
+ const FileSystemOptions &FileSystemOpts);
/// getFile - Lookup, cache, and verify the specified file. This returns null
/// if the file doesn't exist.
///
- const FileEntry *getFile(llvm::StringRef Filename) {
- return getFile(Filename.begin(), Filename.end());
+ const FileEntry *getFile(llvm::StringRef Filename,
+ const FileSystemOptions &FileSystemOpts) {
+ return getFile(Filename.begin(), Filename.end(), FileSystemOpts);
}
const FileEntry *getFile(const char *FilenameStart,
- const char *FilenameEnd);
+ const char *FilenameEnd,
+ const FileSystemOptions &FileSystemOpts);
/// \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(llvm::StringRef Filename, off_t Size,
- time_t ModificationTime);
+ time_t ModificationTime,
+ const FileSystemOptions &FileSystemOpts);
+
+ /// \brief Open the specified file as a MemoryBuffer, returning a new
+ /// MemoryBuffer if successful, otherwise returning null.
+ llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry,
+ const FileSystemOptions &FileSystemOpts,
+ std::string *ErrorStr = 0,
+ struct stat *FileInfo = 0) {
+ return getBufferForFile(Entry->getName(), FileSystemOpts,
+ ErrorStr, Entry->getSize(), FileInfo);
+ }
+ llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
+ const FileSystemOptions &FileSystemOpts,
+ std::string *ErrorStr = 0,
+ int64_t FileSize = -1,
+ struct stat *FileInfo = 0) {
+ return getBufferForFile(Filename.begin(), Filename.end(), FileSystemOpts,
+ ErrorStr, FileSize, FileInfo);
+ }
+ llvm::MemoryBuffer *getBufferForFile(const char *FilenameStart,
+ const char *FilenameEnd,
+ const FileSystemOptions &FileSystemOpts,
+ std::string *ErrorStr = 0,
+ int64_t FileSize = -1,
+ struct stat *FileInfo = 0);
+
+ /// \brief If path is not absolute and FileSystemOptions set the working
+ /// directory, the path is modified to be relative to the given
+ /// working directory.
+ static void FixupRelativePath(llvm::sys::Path &path,
+ const FileSystemOptions &FSOpts);
+
void PrintStats() const;
};
diff --git a/include/clang/Basic/FileSystemOptions.h b/include/clang/Basic/FileSystemOptions.h
new file mode 100644
index 0000000000..4f3c2ae03d
--- /dev/null
+++ b/include/clang/Basic/FileSystemOptions.h
@@ -0,0 +1,29 @@
+//===--- FileSystemOptions.h - File System Options --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the FileSystemOptions interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
+#define LLVM_CLANG_BASIC_FILESYSTEMOPTIONS_H
+
+namespace clang {
+
+/// \brief Keeps track of options that affect how file operations are performed.
+class FileSystemOptions {
+public:
+ /// \brief If set, paths are resolved as if the working directory was
+ /// set to the value of WorkingDir.
+ std::string WorkingDir;
+};
+
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 2098698400..4f5c17344d 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -33,6 +33,7 @@ namespace clang {
class Diagnostic;
class SourceManager;
class FileManager;
+class FileSystemOptions;
class FileEntry;
class LineTableInfo;
@@ -369,7 +370,10 @@ public:
class SourceManager {
/// \brief Diagnostic object.
Diagnostic &Diag;
-
+
+ FileManager &FileMgr;
+ const FileSystemOptions &FileSystemOpts;
+
mutable llvm::BumpPtrAllocator ContentCacheAlloc;
/// FileInfos - Memoized information about all of the files tracked by this
@@ -427,8 +431,10 @@ class SourceManager {
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
- SourceManager(Diagnostic &Diag)
- : Diag(Diag), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
+ SourceManager(Diagnostic &Diag, FileManager &FileMgr,
+ const FileSystemOptions &FSOpts)
+ : Diag(Diag), FileMgr(FileMgr), FileSystemOpts(FSOpts),
+ ExternalSLocEntries(0), LineTable(0), NumLinearScans(0),
NumBinaryProbes(0) {
clearIDTables();
}
@@ -438,6 +444,9 @@ public:
Diagnostic &getDiagnostics() const { return Diag; }
+ FileManager &getFileManager() const { return FileMgr; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
//===--------------------------------------------------------------------===//
// MainFileID creation and querying methods.
//===--------------------------------------------------------------------===//
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 8a967d033a..dee123ddd4 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -366,6 +366,11 @@ def create_module : Flag<"-create-module">,
def import_module : Separate<"-import-module">,
HelpText<"Import a module definition file">;
+def working_directory : JoinedOrSeparate<"-working-directory">,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<"-working-directory=">,
+ Alias<working_directory>;
+
def relocatable_pch : Flag<"-relocatable-pch">,
HelpText<"Whether to build a relocatable precompiled header">;
def chained_pch : Flag<"-chained-pch">,
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index da762becb6..907639f58b 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -624,6 +624,11 @@ def x : JoinedOrSeparate<"-x">, Flags<[DriverOption]>,
MetaVarName<"<language>">;
def y : Joined<"-y">;
+def working_directory : Separate<"-working-directory">,
+ HelpText<"Resolve file paths relative to the specified directory">;
+def working_directory_EQ : Joined<"-working-directory=">,
+ Alias<working_directory>;
+
// Double dash options, which are usually an alias for one of the previous
// options.
diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h
index 45f771763d..980cd54cb3 100644
--- a/include/clang/Frontend/ASTUnit.h
+++ b/include/clang/Frontend/ASTUnit.h
@@ -21,6 +21,7 @@
#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang-c/Index.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/OwningPtr.h"
@@ -68,7 +69,9 @@ private:
llvm::OwningPtr<TargetInfo> Target;
llvm::OwningPtr<Preprocessor> PP;
llvm::OwningPtr<ASTContext> Ctx;
-
+
+ FileSystemOptions FileSystemOpts;
+
/// \brief The AST consumer that received information about the translation
/// unit as it was parsed or loaded.
llvm::OwningPtr<ASTConsumer> Consumer;
@@ -359,6 +362,8 @@ public:
const FileManager &getFileManager() const { return *FileMgr; }
FileManager &getFileManager() { return *FileMgr; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
+
const std::string &getOriginalSourceFileName();
const std::string &getASTFileName();
@@ -452,7 +457,12 @@ public:
unsigned cached_completion_size() const {
return CachedCompletionResults.size();
}
-
+
+ llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr = 0,
+ int64_t FileSize = -1,
+ struct stat *FileInfo = 0);
+
/// \brief Whether this AST represents a complete translation unit.
///
/// If false, this AST is only a partial translation unit, e.g., one
@@ -473,6 +483,7 @@ public:
/// \returns - The initialized ASTUnit or null if the AST failed to load.
static ASTUnit *LoadFromASTFile(const std::string &Filename,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ const FileSystemOptions &FileSystemOpts,
bool OnlyLocalDecls = false,
RemappedFile *RemappedFiles = 0,
unsigned NumRemappedFiles = 0,
diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h
index e5121e1bf9..3db6077029 100644
--- a/include/clang/Frontend/CompilerInstance.h
+++ b/include/clang/Frontend/CompilerInstance.h
@@ -220,6 +220,10 @@ public:
return Invocation->getDiagnosticOpts();
}
+ const FileSystemOptions &getFileSystemOpts() const {
+ return Invocation->getFileSystemOpts();
+ }
+
FrontendOptions &getFrontendOpts() {
return Invocation->getFrontendOpts();
}
@@ -499,7 +503,8 @@ public:
void createFileManager();
/// Create the source manager and replace any existing one with it.
- void createSourceManager();
+ void createSourceManager(FileManager &FileMgr,
+ const FileSystemOptions &FSOpts);
/// Create the preprocessor, using the invocation, file, and source managers,
/// and replace any existing one with it.
@@ -517,6 +522,7 @@ public:
const DependencyOutputOptions &,
const TargetInfo &,
const FrontendOptions &,
+ const FileSystemOptions &,
SourceManager &, FileManager &);
/// Create the AST context.
@@ -617,6 +623,7 @@ public:
static bool InitializeSourceManager(llvm::StringRef InputFile,
Diagnostic &Diags,
FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
SourceManager &SourceMgr,
const FrontendOptions &Opts);
diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h
index aef02448f0..641c5f6650 100644
--- a/include/clang/Frontend/CompilerInvocation.h
+++ b/include/clang/Frontend/CompilerInvocation.h
@@ -12,6 +12,7 @@
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "clang/Frontend/AnalyzerOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/DependencyOutputOptions.h"
@@ -52,6 +53,9 @@ class CompilerInvocation {
/// Options controlling the diagnostic engine.
DiagnosticOptions DiagnosticOpts;
+ /// Options controlling file system operations.
+ FileSystemOptions FileSystemOpts;
+
/// Options controlling the frontend itself.
FrontendOptions FrontendOpts;
@@ -126,6 +130,11 @@ public:
DiagnosticOptions &getDiagnosticOpts() { return DiagnosticOpts; }
const DiagnosticOptions &getDiagnosticOpts() const { return DiagnosticOpts; }
+ FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; }
+ const FileSystemOptions &getFileSystemOpts() const {
+ return FileSystemOpts;
+ }
+
HeaderSearchOptions &getHeaderSearchOpts() { return HeaderSearchOpts; }
const HeaderSearchOptions &getHeaderSearchOpts() const {
return HeaderSearchOpts;
diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h
index fe722db381..ff075445b4 100644
--- a/include/clang/Frontend/Utils.h
+++ b/include/clang/Frontend/Utils.h
@@ -39,6 +39,7 @@ class SourceManager;
class Stmt;
class TargetInfo;
class FrontendOptions;
+class FileSystemOptions;
/// Normalize \arg File for use in a user defined #include directive (in the
/// predefines buffer).
@@ -53,6 +54,7 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS,
/// InitializePreprocessor - Initialize the preprocessor getting it and the
/// environment ready to process a single file.
void InitializePreprocessor(Preprocessor &PP,
+ const FileSystemOptions &FSOpts,
const PreprocessorOptions &PPOpts,
const HeaderSearchOptions &HSOpts,
const FrontendOptions &FEOpts);
diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h
index 9837e29653..4f17ae3ec3 100644
--- a/include/clang/Lex/HeaderMap.h
+++ b/include/clang/Lex/HeaderMap.h
@@ -21,6 +21,7 @@ namespace llvm {
namespace clang {
class FileEntry;
class FileManager;
+ class FileSystemOptions;
struct HMapBucket;
struct HMapHeader;
@@ -43,11 +44,13 @@ public:
/// HeaderMap::Create - This attempts to load the specified file as a header
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
- static const HeaderMap *Create(const FileEntry *FE);
+ static const HeaderMap *Create(const FileEntry *FE, FileManager &FM,
+ const FileSystemOptions &FSOpts);
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
- const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const;
+ const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM,
+ const FileSystemOptions &FileSystemOpts) const;
/// getFileName - Return the filename of the headermap.
const char *getFileName() const;
diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h
index 80b38dee06..7d467a5680 100644
--- a/include/clang/Lex/HeaderSearch.h
+++ b/include/clang/Lex/HeaderSearch.h
@@ -23,6 +23,7 @@ namespace clang {
class ExternalIdentifierLookup;
class FileEntry;
class FileManager;
+class FileSystemOptions;
class IdentifierInfo;
/// HeaderFileInfo - The preprocessor keeps track of this information for each
@@ -71,6 +72,7 @@ struct HeaderFileInfo {
/// file referenced by a #include or #include_next, (sub-)framework lookup, etc.
class HeaderSearch {
FileManager &FileMgr;
+ const FileSystemOptions &FileSystemOpts;
/// #include search path information. Requests for #include "x" search the
/// directory of the #including file first, then each directory in SearchDirs
@@ -118,10 +120,11 @@ class HeaderSearch {
explicit HeaderSearch(const HeaderSearch&);
void operator=(const HeaderSearch&);
public:
- HeaderSearch(FileManager &FM);
+ HeaderSearch(FileManager &FM, const FileSystemOptions &FSOpts);
~HeaderSearch();
FileManager &getFileMgr() const { return FileMgr; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
/// SetSearchPaths - Interface for setting the file search paths.
///
diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h
index 5e8a4f144c..a3787e3ffe 100644
--- a/include/clang/Lex/PTHManager.h
+++ b/include/clang/Lex/PTHManager.h
@@ -119,7 +119,9 @@ public:
/// Create - This method creates PTHManager objects. The 'file' argument
/// is the name of the PTH file. This method returns NULL upon failure.
- static PTHManager *Create(const std::string& file, Diagnostic &Diags);
+ static PTHManager *Create(const std::string& file, FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
+ Diagnostic &Diags);
void setPreprocessor(Preprocessor *pp) { PP = pp; }
diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h
index 7b138884e0..b45f47bf11 100644
--- a/include/clang/Lex/Preprocessor.h
+++ b/include/clang/Lex/Preprocessor.h
@@ -35,6 +35,7 @@ namespace clang {
class SourceManager;
class ExternalPreprocessorSource;
class FileManager;
+class FileSystemOptions;
class FileEntry;
class HeaderSearch;
class PragmaNamespace;
@@ -57,6 +58,7 @@ class Preprocessor {
LangOptions Features;
const TargetInfo &Target;
FileManager &FileMgr;
+ const FileSystemOptions &FileSystemOpts;
SourceManager &SourceMgr;
ScratchBuffer *ScratchBuf;
HeaderSearch &HeaderInfo;
@@ -279,6 +281,7 @@ public:
const LangOptions &getLangOptions() const { return Features; }
const TargetInfo &getTargetInfo() const { return Target; }
FileManager &getFileManager() const { return FileMgr; }
+ const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; }
SourceManager &getSourceManager() const { return SourceMgr; }
HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; }
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 9ac7c31852..420197c260 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -67,6 +67,7 @@ class ASTDeclReader;
class ASTStmtReader;
class ASTIdentifierLookupTrait;
class TypeLocReader;
+class FileSystemOptions;
struct HeaderFileInfo;
struct PCHPredefinesBlock {
@@ -193,6 +194,7 @@ private:
SourceManager &SourceMgr;
FileManager &FileMgr;
+ const FileSystemOptions &FileSystemOpts;
Diagnostic &Diags;
/// \brief The semantic analysis object that will be processing the
@@ -802,7 +804,8 @@ public:
/// \param DisableValidation If true, the AST reader will suppress most
/// of its regular consistency checking, allowing the use of precompiled
/// headers that cannot be determined to be compatible.
- ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ const FileSystemOptions &FileSystemOpts,
Diagnostic &Diags, const char *isysroot = 0,
bool DisableValidation = false);
~ASTReader();
@@ -834,6 +837,8 @@ public:
/// \brief Retrieve the name of the original source file name directly from
/// the AST file, without actually loading the AST file.
static std::string getOriginalSourceFile(const std::string &ASTFileName,
+ FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
Diagnostic &Diags);
/// \brief Returns the suggested contents of the predefines buffer,
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index a8cb1c5bed..7747e617e3 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -2980,9 +2980,12 @@ Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) {
ASTImporter::ASTImporter(Diagnostic &Diags,
ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager)
+ const FileSystemOptions &ToFileSystemOpts,
+ ASTContext &FromContext, FileManager &FromFileManager,
+ const FileSystemOptions &FromFileSystemOpts)
: ToContext(ToContext), FromContext(FromContext),
ToFileManager(ToFileManager), FromFileManager(FromFileManager),
+ ToFileSystemOpts(ToFileSystemOpts), FromFileSystemOpts(FromFileSystemOpts),
Diags(Diags) {
ImportedDecls[FromContext.getTranslationUnitDecl()]
= ToContext.getTranslationUnitDecl();
@@ -3153,7 +3156,8 @@ FileID ASTImporter::Import(FileID FromID) {
// disk again
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
// than mmap the files several times.
- const FileEntry *Entry = ToFileManager.getFile(Cache->Entry->getName());
+ const FileEntry *Entry = ToFileManager.getFile(Cache->Entry->getName(),
+ ToFileSystemOpts);
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
FromSLoc.getFile().getFileCharacteristic());
} else {
diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp
index 565f8a61de..247ba1b752 100644
--- a/lib/Basic/FileManager.cpp
+++ b/lib/Basic/FileManager.cpp
@@ -18,8 +18,10 @@
//===----------------------------------------------------------------------===//
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include "llvm/Config/config.h"
@@ -197,7 +199,8 @@ void FileManager::removeStatCache(StatSysCallCache *statCache) {
/// \brief Retrieve the directory that the given file name resides in.
static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
const char *NameStart,
- const char *NameEnd) {
+ const char *NameEnd,
+ const FileSystemOptions &FileSystemOpts) {
// 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.
@@ -211,18 +214,19 @@ static const DirectoryEntry *getDirectoryFromFile(FileManager &FileMgr,
if (SlashPos < NameStart) {
// Use the current directory if file has no path component.
const char *Name = ".";
- return FileMgr.getDirectory(Name, Name+1);
+ return FileMgr.getDirectory(Name, Name+1, FileSystemOpts);
} else if (SlashPos == NameEnd-1)
return 0; // If filename ends with a /, it's a directory.
else
- return FileMgr.getDirectory(NameStart, SlashPos);
+ return FileMgr.getDirectory(NameStart, SlashPos, FileSystemOpts);
}
/// getDirectory - Lookup, cache, and verify the specified directory. This
/// returns null if the directory doesn't exist.
///
const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
- const char *NameEnd) {
+ const char *NameEnd,
+ const FileSystemOptions &FileSystemOpts) {
// stat doesn't like trailing separators (at least on Windows).
if (((NameEnd - NameStart) > 1) &&
((*(NameEnd - 1) == '/') || (*(NameEnd - 1) == '\\')))
@@ -248,7 +252,7 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
// Check to see if the directory exists.
struct stat StatBuf;
- if (stat_cached(InterndDirName, &StatBuf) || // Error stat'ing.
+ if (stat_cached(InterndDirName, &StatBuf, FileSystemOpts) || // Error stat'ing.
!S_ISDIR(StatBuf.st_mode)) // Not a directory?
return 0;
@@ -274,7 +278,8 @@ const DirectoryEntry *FileManager::getDirectory(const char *NameStart,
/// if the file doesn't exist.
///
const FileEntry *FileManager::getFile(const char *NameStart,
- const char *NameEnd) {
+ const char *NameEnd,
+ const FileSystemOptions &FileSystemOpts) {
++NumFileLookups;
// See if there is already an entry in the map.
@@ -297,7 +302,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
const char *InterndFileName = NamedFileEnt.getKeyData();
const DirectoryEntry *DirInfo
- = getDirectoryFromFile(*this, NameStart, NameEnd);
+ = getDirectoryFromFile(*this, NameStart, NameEnd, FileSystemOpts);
if (DirInfo == 0) // Directory doesn't exist, file can't exist.
return 0;
@@ -307,7 +312,7 @@ const FileEntry *FileManager::getFile(const char *NameStart,
// Nope, there isn't. Check to see if the file exists.
struct stat StatBuf;
//llvm::errs() << "STATING: " << Filename;
- if (stat_cached(InterndFileName, &StatBuf) || // Error stat'ing.
+ if (stat_cached(InterndFileName, &StatBuf, FileSystemOpts) || // Error stat'ing.
S_ISDIR(StatBuf.st_mode)) { // A directory?
// If this file doesn't exist, we leave a null in FileEntries for this path.
//llvm::errs() << ": Not existing\n";
@@ -336,7 +341,8 @@ const FileEntry *FileManager::getFile(const char *NameStart,
const FileEntry *
FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
- time_t ModificationTime) {
+ time_t ModificationTime,
+ const FileSystemOptions &FileSystemOpts) {
const char *NameStart = Filename.begin(), *NameEnd = Filename.end();
++NumFileLookups;
@@ -356,7 +362,7 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
NamedFileEnt.setValue(NON_EXISTENT_FILE);
const DirectoryEntry *DirInfo
- = getDirectoryFromFile(*this, NameStart, NameEnd);
+ = getDirectoryFromFile(*this, NameStart, NameEnd, FileSystemOpts);
if (DirInfo == 0) // Directory doesn't exist, file can't exist.
return 0;
@@ -374,7 +380,7 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
// newly-created file entry.
const char *InterndFileName = NamedFileEnt.getKeyData();
struct stat StatBuf;
- if (!stat_cached(InterndFileName, &StatBuf) &&
+ if (!stat_cached(InterndFileName, &StatBuf, FileSystemOpts) &&
!S_ISDIR(StatBuf.st_mode)) {
llvm::sys::Path FilePath(InterndFileName);
FilePath.makeAbsolute();
@@ -384,6 +390,38 @@ FileManager::getVirtualFile(llvm::StringRef Filename, off_t Size,
return UFE;
}
+llvm::MemoryBuffer *FileManager::getBufferForFile(const char *FilenameStart,
+ const char *FilenameEnd,
+ const FileSystemOptions &FileSystemOpts,
+ std::string *ErrorStr,
+ int64_t FileSize,
+ struct stat *FileInfo) {
+ llvm::sys::Path FilePath(llvm::StringRef(FilenameStart,
+ FilenameEnd-FilenameStart));
+ FixupRelativePath(FilePath, FileSystemOpts);
+
+ return llvm::MemoryBuffer::getFile(FilePath.c_str(), ErrorStr,
+ FileSize, FileInfo);
+}
+
+int FileManager::stat_cached(const char* path, struct stat* buf,
+ const FileSystemOptions &FileSystemOpts) {
+ llvm::sys::Path FilePath(path);
+ FixupRelativePath(FilePath, FileSystemOpts);
+
+ return StatCache.get() ? StatCache->stat(FilePath.c_str(), buf)
+ : stat(FilePath.c_str(), buf);
+}
+
+void FileManager::FixupRelativePath(llvm::sys::Path &path,
+ const FileSystemOptions &FSOpts) {
+ if (!FSOpts.WorkingDir.empty() && !path.isAbsolute()) {
+ llvm::sys::Path NewPath(FSOpts.WorkingDir);
+ NewPath.appendComponent(path.str());
+ path = NewPath;
+ }
+}
+
void FileManager::PrintStats() const {
llvm::errs() << "\n*** File Manager Stats:\n";
llvm::errs() << UniqueFiles.size() << " files found, "
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 7127e80018..97af0d6fe3 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -73,9 +73,10 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
if (!Buffer.getPointer() && Entry) {
std::string ErrorStr;
struct stat FileInfo;
- Buffer.setPointer(MemoryBuffer::getFile(Entry->getName(), &ErrorStr,
- Entry->getSize(), &FileInfo));
-
+ Buffer.setPointer(SM.getFileManager().getBufferForFile(Entry,
+ SM.getFileSystemOpts(),
+ &ErrorStr, &FileInfo));
+
// If we were unable to open the file, then we are in an inconsistent
// situation where the content cache referenced a file which no longer
// exists. Most likely, we were using a stat cache with an invalid entry but
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 1355206065..c7a7434837 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -753,10 +753,19 @@ void Driver::BuildActions(const ToolChain &TC, const ArgList &Args,
}
// Check that the file exists, if enabled.
- if (CheckInputsExist && memcmp(Value, "-", 2) != 0 &&
- !llvm::sys::Path(Value).exists())
- Diag(clang::diag::err_drv_no_such_file) << A->getValue(Args);
- else
+ if (CheckInputsExist && memcmp(Value, "-", 2) != 0) {
+ llvm::sys::Path Path(Value);
+ if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory))
+ if (!Path.isAbsolute()) {
+ Path = WorkDir->getValue(Args);
+ Path.appendComponent(Value);
+ }
+
+ if (!Path.exists())
+ Diag(clang::diag::err_drv_no_such_file) << Path.str();
+ else
+ Inputs.push_back(std::make_pair(Ty, A));
+ } else
Inputs.push_back(std::make_pair(Ty, A));
} else if (A->getOption().isLinkerInput()) {
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 7ba1dc8be7..744b0ae661 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -1073,6 +1073,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-resource-dir");
CmdArgs.push_back(D.ResourceDir.c_str());
+ Args.AddLastArg(CmdArgs, options::OPT_working_directory);
+
// Add preprocessing options like -I, -D, etc. if we are using the
// preprocessor.
//
diff --git a/lib/Frontend/ASTMerge.cpp b/lib/Frontend/ASTMerge.cpp
index b46212feda..f270846343 100644
--- a/lib/Frontend/ASTMerge.cpp
+++ b/lib/Frontend/ASTMerge.cpp
@@ -40,7 +40,8 @@ void ASTMergeAction::ExecuteAction() {
&CI.getASTContext());
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
for (unsigned I = 0, N = ASTFiles.size(); I != N; ++I) {
- ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags, false);
+ ASTUnit *Unit = ASTUnit::LoadFromASTFile(ASTFiles[I], Diags,
+ CI.getFileSystemOpts(), false);
if (!Unit)
continue;
@@ -53,8 +54,10 @@ void ASTMergeAction::ExecuteAction() {
ASTImporter Importer(CI.getDiagnostics(),
CI.getASTContext(),
CI.getFileManager(),
+ CI.getFileSystemOpts(),
Unit->getASTContext(),
- Unit->getFileManager());
+ Unit->getFileManager(),
+ Unit->getFileSystemOpts());
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
for (DeclContext::decl_iterator D = TU->decls_begin(),
diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp
index b07ed12f75..bbee11ba7c 100644
--- a/lib/Frontend/ASTUnit.cpp
+++ b/lib/Frontend/ASTUnit.cpp
@@ -449,8 +449,17 @@ const std::string &ASTUnit::getASTFileName() {
return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName();
}
+llvm::MemoryBuffer *ASTUnit::getBufferForFile(llvm::StringRef Filename,
+ std::string *ErrorStr,
+ int64_t FileSize,
+ struct stat *FileInfo) {
+ return FileMgr->getBufferForFile(Filename, FileSystemOpts,
+ ErrorStr, FileSize, FileInfo);
+}
+
ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
+ const FileSystemOptions &FileSystemOpts,
bool OnlyLocalDecls,
RemappedFile *RemappedFiles,
unsigned NumRemappedFiles,
@@ -467,9 +476,13 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
AST->CaptureDiagnostics = CaptureDiagnostics;
AST->OnlyLocalDecls = OnlyLocalDecls;
AST->Diagnostics = Diags;
+ AST->FileSystemOpts = FileSystemOpts;
AST->FileMgr.reset(new FileManager);
- AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
- AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
+ AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics(),
+ AST->getFileManager(),
+ AST->getFileSystemOpts()));
+ AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager(),
+ AST->getFileSystemOpts()));
// If requested, capture diagnostics in the ASTUnit.
CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
@@ -480,7 +493,8 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
const FileEntry *FromFile
= AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
RemappedFiles[I].second->getBufferSize(),
- 0);
+ 0,
+ AST->getFileSystemOpts());
if (!FromFile) {
AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
<< RemappedFiles[I].first;
@@ -505,7 +519,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
llvm::OwningPtr<ASTReader> Reader;
Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(),
- AST->getDiagnostics()));
+ AST->getFileSystemOpts(), AST->getDiagnostics()));
Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple,
Predefines, Counter));
@@ -732,7 +746,8 @@ bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
// Configure the various subsystems.
// FIXME: Should we retain the previous file manager?
FileMgr.reset(new FileManager);
- SourceMgr.reset(new SourceManager(getDiagnostics()));
+ FileSystemOpts = Clang.getFileSystemOpts();
+ SourceMgr.reset(new SourceManager(getDiagnostics(), *FileMgr, FileSystemOpts));
TheSema.reset();
Ctx.reset();
PP.reset();
@@ -908,7 +923,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
CreatedBuffer = false;
}
- Buffer = llvm::MemoryBuffer::getFile(M->second);
+ Buffer = getBufferForFile(M->second);
if (!Buffer)
return std::make_pair((llvm::MemoryBuffer*)0,
std::make_pair(0, true));
@@ -941,7 +956,7 @@ ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
// If the main source file was not remapped, load it now.
if (!Buffer) {
- Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
+ Buffer = getBufferForFile(FrontendOpts.Inputs[0].second);
if (!Buffer)
return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
@@ -1240,7 +1255,9 @@ llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Clang.setFileManager(new FileManager);
// Create the source manager.
- Clang.setSourceManager(new SourceManager(getDiagnostics()));
+ Clang.setSourceManager(new SourceManager(getDiagnostics(),
+ Clang.getFileManager(),
+ Clang.getFileSystemOpts()));
llvm::OwningPtr<PrecompilePreambleAction> Act;
Act.reset(new PrecompilePreambleAction(*this));
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index 95d417f633..c5e5d7f90a 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -148,8 +148,9 @@ void CompilerInstance::createFileManager() {
// Source Manager
-void CompilerInstance::createSourceManager() {
- SourceMgr.reset(new SourceManager(getDiagnostics()));
+void CompilerInstance::createSourceManager(FileManager &FileMgr,
+ const FileSystemOptions &FSOpts) {
+ SourceMgr.reset(new SourceManager(getDiagnostics(), FileMgr, FSOpts));
}
// Preprocessor
@@ -158,8 +159,8 @@ void CompilerInstance::createPreprocessor() {
PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
getPreprocessorOpts(), getHeaderSearchOpts(),
getDependencyOutputOpts(), getTarget(),
- getFrontendOpts(), getSourceManager(),
- getFileManager()));
+ getFrontendOpts(), getFileSystemOpts(),
+ getSourceManager(), getFileManager()));
}
Preprocessor *
@@ -170,15 +171,16 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
const DependencyOutputOptions &DepOpts,
const TargetInfo &Target,
const FrontendOptions &FEOpts,
+ const FileSystemOptions &FSOpts,
SourceManager &SourceMgr,
FileManager &FileMgr) {
// Create a PTH manager if we are using some form of a token cache.
PTHManager *PTHMgr = 0;
if (!PPOpts.TokenCache.empty())
- PTHMgr = PTHManager::Create(PPOpts.TokenCache, Diags);
+ PTHMgr = PTHManager::Create(PPOpts.TokenCache, FileMgr, FSOpts, Diags);
// Create the Preprocessor.
- HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
+ HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr, FSOpts);
Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
SourceMgr, *HeaderInfo, PTHMgr,
/*OwnsHeaderSearch=*/true);
@@ -194,7 +196,7 @@ CompilerInstance::createPreprocessor(Diagnostic &Diags,
if (PPOpts.DetailedRecord)
PP->createPreprocessingRecord();
- InitializePreprocessor(*PP, PPOpts, HSOpts, FEOpts);
+ InitializePreprocessor(*PP, FSOpts, PPOpts, HSOpts, FEOpts);
// Handle generating dependencies, if requested.
if (!DepOpts.OutputFile.empty())
@@ -271,7 +273,8 @@ static bool EnableCodeCompletion(Preprocessor &PP,
unsigned Column) {
// Tell the source manager to chop off the given file at a specific
// line and column.
- const FileEntry *Entry = PP.getFileManager().getFile(Filename);
+ const FileEntry *Entry = PP.getFileManager().getFile(Filename,
+ PP.getFileSystemOpts());
if (!Entry) {
PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
<< Filename;
@@ -352,7 +355,11 @@ void CompilerInstance::clearOutputFiles(bool EraseFiles) {
TempPath.eraseFromDisk();
else {
std::string Error;
- if (TempPath.renamePathOnDisk(llvm::sys::Path(it->Filename), &Error)) {
+ llvm::sys::Path NewOutFile(it->Filename);
+ // If '-working-directory' was passed, the output filename should be
+ // relative to that.
+ FileManager::FixupRelativePath(NewOutFile, getFileSystemOpts());
+ if (TempPath.renamePathOnDisk(NewOutFile, &Error)) {
getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
<< it->TempFilename << it->Filename << Error;
TempPath.eraseFromDisk();
@@ -457,17 +464,19 @@ CompilerInstance::createOutputFile(llvm::StringRef OutputPath,
bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile) {
return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
+ getFileSystemOpts(),
getSourceManager(), getFrontendOpts());
}
bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
Diagnostic &Diags,
FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
SourceManager &SourceMgr,
const FrontendOptions &Opts) {
// Figure out where to get and map in the main file.
if (InputFile != "-") {
- const FileEntry *File = FileMgr.getFile(InputFile);
+ const FileEntry *File = FileMgr.getFile(InputFile, FSOpts);
if (!File) {
Diags.Report(diag::err_fe_error_reading) << InputFile;
return false;
@@ -480,7 +489,8 @@ bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
return false;
}
const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
- SB->getBufferSize(), 0);
+ SB->getBufferSize(), 0,
+ FSOpts);
SourceMgr.createMainFileID(File);
SourceMgr.overrideFileContents(File, SB);
}
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 561555ad1f..b20520bbee 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -10,6 +10,7 @@
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/Version.h"
+#include "clang/Basic/FileManager.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/CC1Options.h"
@@ -351,6 +352,14 @@ static const char *getActionName(frontend::ActionKind Kind) {
return 0;
}
+static void FileSystemOptsToArgs(const FileSystemOptions &Opts,
+ std::vector<std::string> &Res) {
+ if (!Opts.WorkingDir.empty()) {
+ Res.push_back("-working-directory");
+ Res.push_back(Opts.WorkingDir);
+ }
+}
+
static void FrontendOptsToArgs(const FrontendOptions &Opts,
std::vector<std::string> &Res) {
if (Opts.DisableFree)
@@ -743,6 +752,7 @@ void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
CodeGenOptsToArgs(getCodeGenOpts(), Res);
DependencyOutputOptsToArgs(getDependencyOutputOpts(), Res);
DiagnosticOptsToArgs(getDiagnosticOpts(), Res);
+ FileSystemOptsToArgs(getFileSystemOpts(), Res);
FrontendOptsToArgs(getFrontendOpts(), Res);
HeaderSearchOptsToArgs(getHeaderSearchOpts(), Res);
LangOptsToArgs(getLangOpts(), Res);
@@ -979,6 +989,10 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
Opts.Warnings = Args.getAllArgValues(OPT_W);
}
+static void ParseFileSystemArgs(FileSystemOptions &Opts, ArgList &Args) {
+ Opts.WorkingDir = Args.getLastArgValue(OPT_working_directory);
+}
+
static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
Diagnostic &Diags) {
using namespace cc1options;
@@ -1402,6 +1416,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
+ FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
Diagnostic &Diags) {
using namespace cc1options;
Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
@@ -1456,7 +1472,8 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
// PCH is handled specially, we need to extra the original include path.
if (A->getOption().matches(OPT_include_pch)) {
std::string OriginalFile =
- ASTReader::getOriginalSourceFile(A->getValue(Args), Diags);
+ ASTReader::getOriginalSourceFile(A->getValue(Args), FileMgr, FSOpts,
+ Diags);
if (OriginalFile.empty())
continue;
@@ -1535,11 +1552,18 @@ void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, Diags);
ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
+ ParseFileSystemArgs(Res.getFileSystemOpts(), *Args);
InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
if (DashX != IK_AST && DashX != IK_LLVM_IR)
ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
- ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, Diags);
+ // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of
+ // PCH file and find the original header name. Remove the need to do that in
+ // ParsePreprocessorArgs and remove the FileManager & FileSystemOptions
+ // parameters from the function and the "FileManager.h" #include.
+ FileManager FileMgr;
+ ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args,
+ FileMgr, Res.getFileSystemOpts(), Diags);
ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
ParseTargetArgs(Res.getTargetOpts(), *Args);
}
diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp
index 48f115fd3e..cfa0b6dbd3 100644
--- a/lib/Frontend/FrontendAction.cpp
+++ b/lib/Frontend/FrontendAction.cpp
@@ -103,7 +103,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
llvm::IntrusiveRefCntPtr<Diagnostic> Diags(&CI.getDiagnostics());
std::string Error;
- ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags);
+ ASTUnit *AST = ASTUnit::LoadFromASTFile(Filename, Diags,
+ CI.getFileSystemOpts());
if (!AST)
goto failure;
@@ -132,7 +133,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
if (!CI.hasFileManager())
CI.createFileManager();
if (!CI.hasSourceManager())
- CI.createSourceManager();
+ CI.createSourceManager(CI.getFileManager(), CI.getFileSystemOpts());
// IR files bypass the rest of initialization.
if (InputKind == IK_LLVM_IR) {
diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp
index 5bc6506e1f..9ef1ca64d7 100644
--- a/lib/Frontend/FrontendActions.cpp
+++ b/lib/Frontend/FrontendActions.cpp
@@ -207,7 +207,10 @@ void PrintPreambleAction::ExecuteAction() {
return;
}
- llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile());
+ CompilerInstance &CI = getCompilerInstance();
+ llvm::MemoryBuffer *Buffer
+ = CI.getFileManager().getBufferForFile(getCurrentFile(),
+ CI.getFileSystemOpts());
if (Buffer) {
unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
llvm::outs().write(Buffer->getBufferStart(), Preamble);
diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp
index 97157b3615..e47381e39d 100644
--- a/lib/Frontend/InitHeaderSearch.cpp
+++ b/lib/Frontend/InitHeaderSearch.cpp
@@ -99,6 +99,7 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
bool IgnoreSysRoot) {
assert(!Path.isTriviallyEmpty() && "can't handle empty path here");
FileManager &FM = Headers.getFileMgr();
+ const FileSystemOptions &FSOpts = Headers.getFileSystemOpts();
// Compute the actual path, taking into consideration -isysroot.
llvm::SmallString<256> MappedPathStr;
@@ -125,7 +126,7 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
// If the directory exists, add it.
- if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str())) {
+ if (const DirectoryEntry *DE = FM.getDirectory(MappedPath.str(), FSOpts)) {
IncludeGroup[Group].push_back(DirectoryLookup(DE, Type, isUserSupplied,
isFramework));
return;
@@ -134,7 +135,7 @@ void InitHeaderSearch::AddPath(const llvm::Twine &Path,
// Check to see if this is an apple-style headermap (which are not allowed to
// be frameworks).
if (!isFramework) {
- if (const FileEntry *FE = FM.getFile(MappedPath.str())) {
+ if (const FileEntry *FE = FM.getFile(MappedPath.str(), FSOpts)) {
if (const HeaderMap *HM = Headers.CreateHeaderMap(FE)) {
// It is a headermap, add it to the search path.
IncludeGroup[Group].push_back(DirectoryLookup(HM, Type,isUserSupplied));
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 181f671025..7275733bbb 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -478,6 +478,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
static void InitializeFileRemapping(Diagnostic &Diags,
SourceManager &SourceMgr,
FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
const PreprocessorOptions &InitOpts) {
// Remap files in the source manager (with buffers).
for (PreprocessorOptions::const_remapped_file_buffer_iterator
@@ -488,7 +489,7 @@ static void InitializeFileRemapping(Diagnostic &Diags,
// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
Remap->second->getBufferSize(),
- 0);
+ 0, FSOpts);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
<< Remap->first;
@@ -510,7 +511,7 @@ static void InitializeFileRemapping(Diagnostic &Diags,
Remap != RemapEnd;
++Remap) {
// Find the file that we're mapping to.
- const FileEntry *ToFile = FileMgr.getFile(Remap->second);
+ const FileEntry *ToFile = FileMgr.getFile(Remap->second, FSOpts);
if (!ToFile) {
Diags.Report(diag::err_fe_remap_missing_to_file)
<< Remap->first << Remap->second;
@@ -520,7 +521,7 @@ static void InitializeFileRemapping(Diagnostic &Diags,
// Create the file entry for the file that we're mapping from.
const FileEntry *FromFile = FileMgr.getVirtualFile(Remap->first,
ToFile->getSize(),
- 0);
+ 0, FSOpts);
if (!FromFile) {
Diags.Report(diag::err_fe_remap_missing_from_file)
<< Remap->first;
@@ -530,7 +531,7 @@ static void InitializeFileRemapping(Diagnostic &Diags,
// Load the contents of the file we're mapping to.
std::string ErrorStr;
const llvm::MemoryBuffer *Buffer
- = llvm::MemoryBuffer::getFile(ToFile->getName(), &ErrorStr);
+ = FileMgr.getBufferForFile(ToFile->getName(), FSOpts, &ErrorStr);
if (!Buffer) {
Diags.Report(diag::err_fe_error_opening)
<< Remap->second << ErrorStr;
@@ -547,6 +548,7 @@ static void InitializeFileRemapping(Diagnostic &Diags,
/// environment ready to process a single file. This returns true on error.
///
void clang::InitializePreprocessor(Preprocessor &PP,
+ const FileSystemOptions &FSOpts,
const PreprocessorOptions &InitOpts,
const HeaderSearchOptions &HSOpts,
const FrontendOptions &FEOpts) {
@@ -556,7 +558,7 @@ void clang::InitializePreprocessor(Preprocessor &PP,
MacroBuilder Builder(Predefines);
InitializeFileRemapping(PP.getDiagnostics(), PP.getSourceManager(),
- PP.getFileManager(), InitOpts);
+ PP.getFileManager(), FSOpts, InitOpts);
// Emit line markers for various builtin sections of the file. We don't do
// this in asm preprocessor mode, because "# 4" is not a line marker directive
diff --git a/lib/Lex/HeaderMap.cpp b/lib/Lex/HeaderMap.cpp
index 4010d613ac..5d9b218a7d 100644
--- a/lib/Lex/HeaderMap.cpp
+++ b/lib/Lex/HeaderMap.cpp
@@ -75,13 +75,14 @@ static inline unsigned HashHMapKey(llvm::StringRef Str) {
/// map. If it doesn't look like a HeaderMap, it gives up and returns null.
/// If it looks like a HeaderMap but is obviously corrupted, it puts a reason
/// into the string error argument and returns null.
-const HeaderMap *HeaderMap::Create(const FileEntry *FE) {
+const HeaderMap *HeaderMap::Create(const FileEntry *FE, FileManager &FM,
+ const FileSystemOptions &FSOpts) {
// If the file is too small to be a header map, ignore it.
unsigned FileSize = FE->getSize();
if (FileSize <= sizeof(HMapHeader)) return 0;
llvm::OwningPtr<const llvm::MemoryBuffer> FileBuffer(
- llvm::MemoryBuffer::getFile(FE->getName(), 0, FE->getSize()));
+ FM.getBufferForFile(FE, FSOpts));
if (FileBuffer == 0) return 0; // Unreadable file?
const char *FileStart = FileBuffer->getBufferStart();
@@ -200,7 +201,8 @@ void HeaderMap::dump() const {
/// LookupFile - Check to see if the specified relative filename is located in
/// this HeaderMap. If so, open it and return its FileEntry.
const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename,
- FileManager &FM) const {
+ FileManager &FM,
+ const FileSystemOptions &FileSystemOpts) const {
const HMapHeader &Hdr = getHeader();
unsigned NumBuckets = getEndianAdjustedWord(Hdr.NumBuckets);
@@ -223,6 +225,6 @@ const FileEntry *HeaderMap::LookupFile(llvm::StringRef Filename,
llvm::SmallString<1024> DestPath;
DestPath += getString(B.Prefix);
DestPath += getString(B.Suffix);
- return FM.getFile(DestPath.begin(), DestPath.end());
+ return FM.getFile(DestPath.begin(), DestPath.end(), FileSystemOpts);
}
}
diff --git a/lib/Lex/HeaderSearch.cpp b/lib/Lex/HeaderSearch.cpp
index 4554ababf7..5a11652fc1 100644
--- a/lib/Lex/HeaderSearch.cpp
+++ b/lib/Lex/HeaderSearch.cpp
@@ -32,7 +32,8 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) {
return ControllingMacro;
}
-HeaderSearch::HeaderSearch(FileManager &FM) : FileMgr(FM), FrameworkMap(64) {
+HeaderSearch::HeaderSearch(FileManager &FM, const FileSystemOptions &FSOpts)
+ : FileMgr(FM), FileSystemOpts(FSOpts), FrameworkMap(64) {
SystemDirIdx = 0;
NoCurDirSearch = false;
@@ -83,7 +84,7 @@ const HeaderMap *HeaderSearch::CreateHeaderMap(const FileEntry *FE) {
return HeaderMaps[i].second;
}
- if (const HeaderMap *HM = HeaderMap::Create(FE)) {
+ if (const HeaderMap *HM = HeaderMap::Create(FE, FileMgr, FileSystemOpts)) {
HeaderMaps.push_back(std::make_pair(FE, HM));
return HM;
}
@@ -118,14 +119,16 @@ const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename,
TmpDir += getDir()->getName();
TmpDir.push_back('/');
TmpDir.append(Filename.begin(), Filename.end());
- return HS.getFileMgr().getFile(TmpDir.begin(), TmpDir.end());
+ return HS.getFileMgr().getFile(TmpDir.begin(), TmpDir.end(),
+ HS.getFileSystemOpts());
}
if (isFramework())
return DoFrameworkLookup(Filename, HS);
assert(isHeaderMap() && "Unknown directory lookup");
- return getHeaderMap()->LookupFile(Filename, HS.getFileMgr());
+ return getHeaderMap()->LookupFile(Filename, HS.getFileMgr(),
+ HS.getFileSystemOpts());
}
@@ -134,6 +137,7 @@ const FileEntry *DirectoryLookup::LookupFile(llvm::StringRef Filename,
const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename,
HeaderSearch &HS) const {
FileManager &FileMgr = HS.getFileMgr();
+ const FileSystemOptions &FileSystemOpts = HS.getFileSystemOpts();
// Framework names must have a '/' in the filename.
size_t SlashPos = Filename.find('/');
@@ -184,7 +188,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename,
FrameworkName += "Headers/";
FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end());
if (const FileEntry *FE = FileMgr.getFile(FrameworkName.begin(),
- FrameworkName.end())) {
+ FrameworkName.end(),
+ FileSystemOpts)) {
return FE;
}
@@ -192,7 +197,8 @@ const FileEntry *DirectoryLookup::DoFrameworkLookup(llvm::StringRef Filename,
const char *Private = "Private";
FrameworkName.insert(FrameworkName.begin()+OrigSize, Private,
Private+strlen(Private));
- return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end());
+ return FileMgr.getFile(FrameworkName.begin(), FrameworkName.end(),
+ FileSystemOpts);
}
@@ -219,7 +225,7 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename,
if (FromDir) return 0;
// Otherwise, just return the file.
- return FileMgr.getFile(Filename);
+ return FileMgr.getFile(Filename, FileSystemOpts);
}
// Step #0, unless disabled, check to see if the file is in the #includer's
@@ -234,7 +240,7 @@ const FileEntry *HeaderSearch::LookupFile(llvm::StringRef Filename,
TmpDir += CurFileEnt->getDir()->getName();
TmpDir.push_back('/');
TmpDir.append(Filename.begin(), Filename.end());
- if (const FileEntry *FE = FileMgr.getFile(TmpDir.str())) {
+ if (const FileEntry *FE = FileMgr.getFile(TmpDir.str(), FileSystemOpts)) {
// Leave CurDir unset.
// This file is a system header or C++ unfriendly if the old file is.
//
@@ -344,7 +350,8 @@ LookupSubframeworkHeader(llvm::StringRef Filename,
// If the framework dir doesn't exist, we fail.
const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName.begin(),
- FrameworkName.end());
+ FrameworkName.end(),
+ FileSystemOpts);
if (Dir == 0) return 0;
// Otherwise, if it does, remember that this is the right direntry for this
@@ -359,13 +366,14 @@ LookupSubframeworkHeader(llvm::StringRef Filename,
HeadersFilename += "Headers/";
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
if (!(FE = FileMgr.getFile(HeadersFilename.begin(),
- HeadersFilename.end()))) {
+ HeadersFilename.end(), FileSystemOpts))) {
// Check ".../Frameworks/HIToolbox.framework/PrivateHeaders/HIToolbox.h"
HeadersFilename = FrameworkName;
HeadersFilename += "PrivateHeaders/";
HeadersFilename.append(Filename.begin()+SlashPos+1, Filename.end());
- if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end())))
+ if (!(FE = FileMgr.getFile(HeadersFilename.begin(), HeadersFilename.end(),
+ FileSystemOpts)))
return 0;
}
diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp
index 63b4823cf1..3d52159fa3 100644
--- a/lib/Lex/PTHLexer.cpp
+++ b/lib/Lex/PTHLexer.cpp
@@ -434,10 +434,12 @@ static void InvalidPTH(Diagnostic &Diags, const char *Msg) {
Diags.Report(Diags.getCustomDiagID(Diagnostic::Error, Msg));
}
-PTHManager* PTHManager::Create(const std::string& file, Diagnostic &Diags) {
+PTHManager* PTHManager::Create(const std::string& file, FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
+ Diagnostic &Diags) {
// Memory map the PTH file.
llvm::OwningPtr<llvm::MemoryBuffer>
- File(llvm::MemoryBuffer::getFile(file.c_str()));
+ File(FileMgr.getBufferForFile(file, FSOpts));
if (!File) {
Diags.Report(diag::err_invalid_pth_file) << file;
diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp
index 1be22df6b1..ff18c3f324 100644
--- a/lib/Lex/Preprocessor.cpp
+++ b/lib/Lex/Preprocessor.cpp
@@ -53,7 +53,8 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
IdentifierInfoLookup* IILookup,
bool OwnsHeaders)
: Diags(&diags), Features(opts), Target(target),FileMgr(Headers.getFileMgr()),
- SourceMgr(SM), HeaderInfo(Headers), ExternalSource(0),
+ FileSystemOpts(Headers.getFileSystemOpts()), SourceMgr(SM),
+ HeaderInfo(Headers), ExternalSource(0),
Identifiers(opts, IILookup), BuiltinInfo(Target), CodeComplete(0),
CodeCompletionFile(0), SkipMainFilePreamble(0, true), CurPPLexer(0),
CurDirLookup(0), Callbacks(0), MacroArgCache(0), Record(0), MIChainHead(0),
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 5c947bc639..b90203b477 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1234,7 +1234,7 @@ ASTReader::ASTReadResult ASTReader::ReadSLocEntryRecord(unsigned ID) {
case SM_SLOC_FILE_ENTRY: {
std::string Filename(BlobStart, BlobStart + BlobLen);
MaybeAddSystemRootToFilename(Filename);
- const FileEntry *File = FileMgr.getFile(Filename);
+ const FileEntry *File = FileMgr.getFile(Filename, FileSystemOpts);
if (File == 0) {
std::string ErrorStr = "could not find file '";
ErrorStr += Filename;
@@ -1549,7 +1549,8 @@ void ASTReader::ReadMacroRecord(PerFileData &F, uint64_t Offset) {
const char *FullFileNameStart = BlobStart + Record[3];
const FileEntry *File
= PP->getFileManager().getFile(FullFileNameStart,
- FullFileNameStart + (BlobLen - Record[3]));
+ FullFileNameStart + (BlobLen - Record[3]),
+ FileSystemOpts);
// FIXME: Stable encoding
InclusionDirective::InclusionKind Kind
@@ -2257,7 +2258,10 @@ ASTReader::ASTReadResult ASTReader::ReadASTCore(llvm::StringRef FileName,
//
// FIXME: This shouldn't be here, we should just take a raw_ostream.
std::string ErrStr;
- F.Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
+ if (FileName == "-")
+ F.Buffer.reset(llvm::MemoryBuffer::getSTDIN(&ErrStr));
+ else
+ F.Buffer.reset(FileMgr.getBufferForFile(FileName, FileSystemOpts, &ErrStr));
if (!F.Buffer) {
Error(ErrStr.c_str());
return IgnorePCH;
@@ -2459,11 +2463,13 @@ void ASTReader::InitializeContext(ASTContext &Ctx) {
/// directly from the AST file, without actually loading the AST
/// file.
std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName,
+ FileManager &FileMgr,
+ const FileSystemOptions &FSOpts,
Diagnostic &Diags) {
// Open the AST file.
std::string ErrStr;
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
- Buffer.reset(llvm::MemoryBuffer::getFile(ASTFileName.c_str(), &ErrStr));
+ Buffer.reset(FileMgr.getBufferForFile(ASTFileName, FSOpts, &ErrStr));
if (!Buffer) {
Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr;
return std::string();
@@ -4477,6 +4483,7 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
const char *isysroot, bool DisableValidation)
: Listener(new PCHValidator(PP, *this)), DeserializationListener(0),
SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()),
+ FileSystemOpts(PP.getFileSystemOpts()),
Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context),
Consumer(0), isysroot(isysroot), DisableValidation(DisableValidation),
NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0),
@@ -4490,9 +4497,11 @@ ASTReader::ASTReader(Preprocessor &PP, ASTContext *Context,
}
ASTReader::ASTReader(SourceManager &SourceMgr, FileManager &FileMgr,
+ const FileSystemOptions &FileSystemOpts,
Diagnostic &Diags, const char *isysroot,
bool DisableValidation)
: DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr),
+ FileSystemOpts(FileSystemOpts),
Diags(Diags), SemaObj(0), PP(0), Context(0), Consumer(0),
isysroot(isysroot), DisableValidation(DisableValidation), NumStatHits(0),
NumStatMisses(0), NumSLocEntriesRead(0), TotalNumSLocEntries(0),
diff --git a/test/Misc/Inputs/working-directory.h b/test/Misc/Inputs/working-directory.h
new file mode 100644
index 0000000000..061df629d6
--- /dev/null
+++ b/test/Misc/Inputs/working-directory.h
@@ -0,0 +1 @@
+typedef int Foo;
diff --git a/test/Misc/working-directory.c b/test/Misc/working-directory.c
new file mode 100644
index 0000000000..5c71d9f3f3
--- /dev/null
+++ b/test/Misc/working-directory.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -working-directory %S working-directory.c -IInputs -fsyntax-only
+
+#include "working-directory.h"
+
+Foo bar;
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index ac57a6941c..3afe3007ea 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -1977,9 +1977,11 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
return 0;
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ FileSystemOptions FileSystemOpts;
+ FileSystemOpts.WorkingDir = CXXIdx->getWorkingDirectory();
llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
- return ASTUnit::LoadFromASTFile(ast_filename, Diags,
+ return ASTUnit::LoadFromASTFile(ast_filename, Diags, FileSystemOpts,
CXXIdx->getOnlyLocalDecls(),
0, 0, true);
}
@@ -2405,7 +2407,8 @@ CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
FileManager &FMgr = CXXUnit->getFileManager();
- const FileEntry *File = FMgr.getFile(file_name, file_name+strlen(file_name));
+ const FileEntry *File = FMgr.getFile(file_name, file_name+strlen(file_name),
+ CXXUnit->getFileSystemOpts());
return const_cast<FileEntry *>(File);
}
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index d42e9eacd0..c92e2afaf3 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -232,12 +232,14 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
/// \brief Language options used to adjust source locations.
LangOptions LangOpts;
-
- /// \brief Source manager, used for diagnostics.
- SourceManager SourceMgr;
/// \brief File manager, used for diagnostics.
FileManager FileMgr;
+
+ FileSystemOptions FileSystemOpts;
+
+ /// \brief Source manager, used for diagnostics.
+ SourceManager SourceMgr;
/// \brief Temporary files that should be removed once we have finished
/// with the code-completion results.
@@ -248,7 +250,8 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
};
AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
- : CXCodeCompleteResults(), Diag(new Diagnostic), SourceMgr(*Diag) { }
+ : CXCodeCompleteResults(), Diag(new Diagnostic),
+ SourceMgr(*Diag, FileMgr, FileSystemOpts) { }
AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
for (unsigned I = 0, N = NumResults; I != N; ++I)
diff --git a/tools/libclang/CIndexer.h b/tools/libclang/CIndexer.h
index 89b098728d..1fcb964c6e 100644
--- a/tools/libclang/CIndexer.h
+++ b/tools/libclang/CIndexer.h
@@ -32,7 +32,8 @@ class CIndexer {
bool DisplayDiagnostics;
llvm::sys::Path ResourcesPath;
-
+ std::string WorkingDir;
+
public:
CIndexer() : OnlyLocalDecls(false), DisplayDiagnostics(false) { }
@@ -49,6 +50,9 @@ public:
/// \brief Get the path of the clang resource files.
std::string getClangResourcesPath();
+
+ const std::string &getWorkingDirectory() const { return WorkingDir; }
+ void setWorkingDirectory(const std::string &Dir) { WorkingDir = Dir; }
};
namespace clang {