Index: clang-tidy/ClangTidy.cpp =================================================================== --- clang-tidy/ClangTidy.cpp +++ clang-tidy/ClangTidy.cpp @@ -87,10 +87,34 @@ ClangTidyContext &Context; }; +void pushVfsOverlayFromFile(StringRef OverlayFile, + DiagnosticsEngine &Diags, + vfs::OverlayFileSystem &OverlayFS) { + if (OverlayFile.empty()) + return; + + llvm::ErrorOr> Buffer = + OverlayFS.getBufferForFile(OverlayFile); + if (!Buffer) { + Diags.Report(diag::err_missing_vfs_overlay_file) << OverlayFile; + return; + } + + IntrusiveRefCntPtr FS = vfs::getVFSFromYAML( + std::move(Buffer.get()), /*DiagHandler*/ nullptr, OverlayFile); + if (!FS.get()) { + Diags.Report(diag::err_invalid_vfs_overlay) << OverlayFile; + return; + } + OverlayFS.pushOverlay(FS); +} + class ErrorReporter { public: ErrorReporter(ClangTidyContext &Context, bool ApplyFixes) - : Files(FileSystemOptions()), DiagOpts(new DiagnosticOptions()), + : OverlayFS(new vfs::OverlayFileSystem(vfs::getRealFileSystem())), + Files(FileSystemOptions(), OverlayFS), + DiagOpts(new DiagnosticOptions()), DiagPrinter(new TextDiagnosticPrinter(llvm::outs(), &*DiagOpts)), Diags(IntrusiveRefCntPtr(new DiagnosticIDs), &*DiagOpts, DiagPrinter), @@ -98,6 +122,11 @@ TotalFixes(0), AppliedFixes(0), WarningsAsErrors(0) { DiagOpts->ShowColors = llvm::sys::Process::StandardOutHasColors(); DiagPrinter->BeginSourceFile(LangOpts); + + if (Context.getOptions().VfsOverlay) { + pushVfsOverlayFromFile(*Context.getOptions().VfsOverlay, Diags, + *OverlayFS); + } } SourceManager &getSourceManager() { return SourceMgr; } @@ -249,6 +278,7 @@ << Message.Message; } + IntrusiveRefCntPtr OverlayFS; FileManager Files; LangOptions LangOpts; // FIXME: use langopts from each original file IntrusiveRefCntPtr DiagOpts; @@ -475,7 +505,10 @@ void runClangTidy(clang::tidy::ClangTidyContext &Context, const CompilationDatabase &Compilations, ArrayRef InputFiles, ProfileData *Profile) { - ClangTool Tool(Compilations, InputFiles); + llvm::IntrusiveRefCntPtr OverlayFS( + new vfs::OverlayFileSystem(vfs::getRealFileSystem())); + ClangTool Tool(Compilations, InputFiles, + std::make_shared(), OverlayFS); // Add extra arguments passed by the clang-tidy command-line. ArgumentsAdjuster PerFileExtraArgumentsInserter = @@ -520,6 +553,11 @@ Tool.setDiagnosticConsumer(&DiagConsumer); + if (Context.getOptions().VfsOverlay) { + pushVfsOverlayFromFile(*Context.getOptions().VfsOverlay, + Context.getDiagnosticsEngine(), *OverlayFS); + } + class ActionFactory : public FrontendActionFactory { public: ActionFactory(ClangTidyContext &Context) : ConsumerFactory(Context) {} Index: clang-tidy/ClangTidyDiagnosticConsumer.h =================================================================== --- clang-tidy/ClangTidyDiagnosticConsumer.h +++ clang-tidy/ClangTidyDiagnosticConsumer.h @@ -166,6 +166,9 @@ /// \brief Returns all collected errors. ArrayRef getErrors() const { return Errors; } + /// \brief Returns diagnostics engine + DiagnosticsEngine &getDiagnosticsEngine() const { return *DiagEngine; } + /// \brief Clears collected errors. void clearErrors() { Errors.clear(); } Index: clang-tidy/ClangTidyOptions.h =================================================================== --- clang-tidy/ClangTidyOptions.h +++ clang-tidy/ClangTidyOptions.h @@ -108,6 +108,10 @@ /// \brief Add extra compilation arguments to the start of the list. llvm::Optional ExtraArgsBefore; + + /// \brief Overlay the virtual filesystem described by file + /// over the real file system + llvm::Optional VfsOverlay; }; /// \brief Abstract interface for retrieving various ClangTidy options. Index: clang-tidy/ClangTidyOptions.cpp =================================================================== --- clang-tidy/ClangTidyOptions.cpp +++ clang-tidy/ClangTidyOptions.cpp @@ -92,6 +92,7 @@ IO.mapOptional("CheckOptions", NOpts->Options); IO.mapOptional("ExtraArgs", Options.ExtraArgs); IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore); + IO.mapOptional("VfsOverlay", Options.VfsOverlay); } }; @@ -152,6 +153,7 @@ overrideValue(Result.User, Other.User); mergeVectors(Result.ExtraArgs, Other.ExtraArgs); mergeVectors(Result.ExtraArgsBefore, Other.ExtraArgsBefore); + overrideValue(Result.VfsOverlay, Other.VfsOverlay); for (const auto &KeyValue : Other.CheckOptions) Result.CheckOptions[KeyValue.first] = KeyValue.second; 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 { @@ -295,6 +301,7 @@ DefaultOptions.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors; DefaultOptions.FormatStyle = FormatStyle; DefaultOptions.User = llvm::sys::Process::GetEnv("USER"); + DefaultOptions.VfsOverlay = VfsOverlay; // USERNAME is used on Windows. if (!DefaultOptions.User) DefaultOptions.User = llvm::sys::Process::GetEnv("USERNAME"); @@ -312,6 +319,8 @@ OverrideOptions.AnalyzeTemporaryDtors = AnalyzeTemporaryDtors; if (FormatStyle.getNumOccurrences() > 0) OverrideOptions.FormatStyle = FormatStyle; + if (VfsOverlay.getNumOccurrences() > 0) + OverrideOptions.VfsOverlay = VfsOverlay; if (!Config.empty()) { if (llvm::ErrorOr ParsedConfig =