diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index a1c4d5399ec9ad297c87354d8a0a56608842b852..1ad33990f2e5b2a563adacf4067c593544aa1cbd 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 e71f51a0e7001bdc448d0f9ddbe03a5802f22cbe..44a7079edd24cf6de62df7f1db0fa648dbe58db5 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 0000000000000000000000000000000000000000..4f3c2ae03df01227e3a0f06be8636daff442aa6e --- /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 2098698400c79fd8e311bdd5afd97d468394d530..4f5c17344d1d687052ca8d49dffbebfe6b340548 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 8a967d033a399835e861fb0d123defa442f39265..dee123ddd49686bd851a1460ef0b627f90d4ccba 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 da762becb64401f2ae34e51a6f88a9dd689d64b2..907639f58b5d83c1cf4be67637f99ed48a298adf 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 45f771763d534f5ce421838cba7ea8b2d76f911f..980cd54cb314933f3fd39082fe6d695a48f24929 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 e5121e1bf9d1295ac6c4a980590ad9b09f7d4f8d..3db6077029110ab312db6dc2bf0d9e1326ca20ed 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 aef02448f0997437dd933315ee115331e3b18103..641c5f6650ebfe9d365597fdbabfefd915e13aeb 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 fe722db381d0106b1379f3872fb45f7a7f90dc1f..ff075445b49fee9d9c7626eb7be886b6b9a79eaf 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 9837e296535f1345df14c40aa64b8ab4ba3b7685..4f17ae3ec3bd1dfda8c4da876231c7ee986363ed 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 80b38dee06afa40b190dcc85086d232b33b3d681..7d467a56800bf376fcb4a7d3e3bea740d979e7a2 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 5e8a4f144c96d0310aaccc06769e42bfa81efdbc..a3787e3ffef12c71f22ccae6357de417360f484b 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 7b138884e0bb5758fb7a56c32f0df7f91fa9ef12..b45f47bf117e1a3dd2aa3b4a9bf76f188a823fba 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 9ac7c3185290c0f95f95e5833ee157c1161fb355..420197c260693d70c9875e716335b5089059de66 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 a8cb1c5bed5962aced00c0ee112d2155a3b8950f..7747e617e3a50bbfe72f4f1a442efe7215843d0e 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 565f8a61dee67310c3645987cff060b883757fe1..247ba1b752b32561c0c86438e7ab3cd783d2e857 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 7127e80018655b005f3771bbe661f910f5652037..97af0d6fe36fdfbe92e19890a0f8294379990762 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 135520606592b651f63ebe05d30dbf9317850ca4..c7a74348374db2d3b30eb52cbd4675c84e4149cc 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 7ba1dc8be7eda96fe7fc678048c0f05a720c5046..744b0ae661f81a0ae192d178a75760b8e12cf701 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 b46212fedaf47c91cb65936e46db2b8971e4fd69..f2708463430533dbdc610a241535d190426afa7d 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 b07ed12f757db679842e46ab729bfc0aa7970e5b..bbee11ba7c98a3104c2a62bf4b49ded8fc201355 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 95d417f63347dda8d0195cf0e3ba6842ae08afe4..c5e5d7f90a0131f8ecd78d3c230f8ebebfbec389 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 561555ad1f67d13194b24ee1631c40af14e965a1..b20520bbeead6cd2a240174f510d232b8dace962 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 48f115fd3e3a214f6de62eb17b4726568752b05c..cfa0b6dbd3f232534029474b81c9b9618dbbd252 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 5bc6506e1fd9499e9e5f8219b365f40d586425a3..9ef1ca64d740c3e3ca966e563ecb9ea841cfe316 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 97157b3615d0bfc11a64360a5480264572e25e1a..e47381e39d3714b032cfa03b8b2029e66352d39e 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 181f671025691b032aadb0c029c04510eda92160..7275733bbb06f015fe6d87e872e35d2c8395b935 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 4010d613ac24267051df1905b12aaee0667a940b..5d9b218a7d8abc18b54a69a67ffb0c2c7c596324 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 4554ababf76d4aedd3d4af1bc43234e538abd29c..5a11652fc1d654e77d96fecc7d249e8bda041c97 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 63b4823cf19eac8c09fea2aa1e0c2055497248b0..3d52159fa3beb1e784d6d45bb95c75220fcdd2ff 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 1be22df6b1cbc329f9657f0e736dc41a409f45de..ff18c3f32456f4195faec4d67cdfb1d7705d8c38 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 5c947bc6395b5e4b31307f6604a4fdd4dc05f5f3..b90203b477b0dae2d12704fd6b03548a4cd0717c 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 0000000000000000000000000000000000000000..061df629d6ade67b86ddf363be3b9421bb816fcf --- /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 0000000000000000000000000000000000000000..5c71d9f3f323bb6d86b929e0a5b391ac521a7ca4 --- /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 ac57a6941c34a8534a9e6af432a294158d71b0b1..3afe3007ea0e31302e6357794977350065a4ea15 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 d42e9eacd0ad12c1be0bc82bac10b11e9ee3247b..c92e2afaf3c219fc64619f60cb15fc38276a9988 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 89b098728dc0893ed798bf4736509b8a114e34a0..1fcb964c6efeb5ad80e2639d31b1e8ff69db98a4 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 {