Index: clang-tidy/ClangTidy.h =================================================================== --- clang-tidy/ClangTidy.h +++ clang-tidy/ClangTidy.h @@ -227,6 +227,7 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context, const tooling::CompilationDatabase &Compilations, ArrayRef InputFiles, + llvm::IntrusiveRefCntPtr BaseFS, ProfileData *Profile = nullptr); // FIXME: This interface will need to be significantly extended to be useful. @@ -236,7 +237,8 @@ /// Errors containing fixes are automatically applied and reformatted. If no /// clang-format configuration file is found, the given \P FormatStyle is used. void handleErrors(ClangTidyContext &Context, bool Fix, - unsigned &WarningsAsErrorsCount); + unsigned &WarningsAsErrorsCount, + llvm::IntrusiveRefCntPtr BaseFS); /// \brief Serializes replacements into YAML and writes them to the specified /// output stream. Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -89,8 +89,10 @@ class ErrorReporter { public: - ErrorReporter(ClangTidyContext &Context, bool ApplyFixes) - : Files(FileSystemOptions()), DiagOpts(new DiagnosticOptions()), + ErrorReporter(ClangTidyContext &Context, bool ApplyFixes, + llvm::IntrusiveRefCntPtr BaseFS) + : Files(FileSystemOptions(), BaseFS), + DiagOpts(new DiagnosticOptions()), DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)), Diags(IntrusiveRefCntPtr(new DiagnosticIDs), &*DiagOpts, DiagPrinter), @@ -474,8 +476,11 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context, const CompilationDatabase &Compilations, - ArrayRef InputFiles, ProfileData *Profile) { - ClangTool Tool(Compilations, InputFiles); + ArrayRef InputFiles, + llvm::IntrusiveRefCntPtr BaseFS, + ProfileData *Profile) { + ClangTool Tool(Compilations, InputFiles, + std::make_shared(), BaseFS); // Add extra arguments passed by the clang-tidy command-line. ArgumentsAdjuster PerFileExtraArgumentsInserter = @@ -546,8 +551,9 @@ } void handleErrors(ClangTidyContext &Context, bool Fix, - unsigned &WarningsAsErrorsCount) { - ErrorReporter Reporter(Context, Fix); + unsigned &WarningsAsErrorsCount, + llvm::IntrusiveRefCntPtr BaseFS) { + ErrorReporter Reporter(Context, Fix, BaseFS); vfs::FileSystem &FileSystem = *Reporter.getSourceManager().getFileManager().getVirtualFileSystem(); auto InitialWorkingDir = FileSystem.getCurrentWorkingDirectory(); Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -209,6 +209,12 @@ cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt VfsOverlay("vfsoverlay", cl::desc(R"( +Overlay the virtual filesystem described by file over the real file system. +)"), + cl::value_desc("filename"), + cl::cat(ClangTidyCategory)); + namespace clang { namespace tidy { @@ -330,6 +336,29 @@ OverrideOptions); } +llvm::IntrusiveRefCntPtr +getVfsOverlayFromFile(const std::string &OverlayFile) { + llvm::IntrusiveRefCntPtr OverlayFS( + new vfs::OverlayFileSystem(vfs::getRealFileSystem())); + llvm::ErrorOr> Buffer = + OverlayFS->getBufferForFile(OverlayFile); + if (!Buffer) { + llvm::errs() << "Can't load virtual filesystem overlay file: '" + << OverlayFile << "' " << Buffer.getError().message() << ".\n"; + return nullptr; + } + + IntrusiveRefCntPtr FS = vfs::getVFSFromYAML( + std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile); + if (!FS) { + llvm::errs() << "Error: invalid virtual filesystem overlay file '" + << OverlayFile << "'.\n"; + return nullptr; + } + OverlayFS->pushOverlay(FS); + return OverlayFS; +} + static int clangTidyMain(int argc, const char **argv) { CommonOptionsParser OptionsParser(argc, argv, ClangTidyCategory, cl::ZeroOrMore); @@ -401,6 +430,11 @@ llvm::cl::PrintHelpMessage(/*Hidden=*/false, /*Categorized=*/true); return 0; } + llvm::IntrusiveRefCntPtr BaseFS( + VfsOverlay.empty() ? vfs::getRealFileSystem() + : getVfsOverlayFromFile(VfsOverlay)); + if (!BaseFS) + return 1; ProfileData Profile; @@ -410,7 +444,7 @@ ClangTidyContext Context(std::move(OwningOptionsProvider)); runClangTidy(Context, OptionsParser.getCompilations(), PathList, - EnableCheckProfile ? &Profile : nullptr); + BaseFS, EnableCheckProfile ? &Profile : nullptr); ArrayRef Errors = Context.getErrors(); bool FoundErrors = std::find_if(Errors.begin(), Errors.end(), [](const ClangTidyError &E) { @@ -422,7 +456,7 @@ unsigned WErrorCount = 0; // -fix-errors implies -fix. - handleErrors(Context, (FixErrors || Fix) && !DisableFixes, WErrorCount); + handleErrors(Context, (FixErrors || Fix) && !DisableFixes, WErrorCount, BaseFS); if (!ExportFixes.empty() && !Errors.empty()) { std::error_code EC;