diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -221,6 +221,54 @@ EXPECT_TRUE(Invocation.run()); } +class LogDiagnosticConsumer : public DiagnosticConsumer { +public: + LogDiagnosticConsumer() = default; + + void HandleDiagnostic(clang::DiagnosticsEngine::Level, + const clang::Diagnostic &info) override { + llvm::SmallString<40> diagnostic_string; + + info.FormatDiagnostic(diagnostic_string); + Diagnostics += diagnostic_string.str(); + + // The next expression triggers: + // Assertion `SourceMgr && "SourceManager not set!"' failed. + // When commented out, will log the diagnostic as normal, which is an + // invalid flag: + // "invalid integral value '-1' in '-ferror-limit -1'" + info.getSourceManager(); + } + std::string Diagnostics; +}; + +TEST(ToolInvocation, DiagCallback) { + llvm::IntrusiveRefCntPtr OverlayFileSystem( + new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); + llvm::IntrusiveRefCntPtr InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + OverlayFileSystem->pushOverlay(InMemoryFileSystem); + llvm::IntrusiveRefCntPtr Files( + new FileManager(FileSystemOptions(), OverlayFileSystem)); + std::vector Args; + Args.push_back("tool-executable"); + // Note: intentional error; user probably meant -ferror-limit=0. + Args.push_back("-ferror-limit=-1"); + Args.push_back("-fsyntax-only"); + Args.push_back("test.cpp"); + clang::tooling::ToolInvocation Invocation( + Args, std::make_unique(), Files.get()); + InMemoryFileSystem->addFile( + "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main(){}\n")); + + LogDiagnosticConsumer LDC; + Invocation.setDiagnosticConsumer(&LDC); + + EXPECT_TRUE(Invocation.run()); + + EXPECT_EQ("", LDC.Diagnostics); +} + struct VerifyEndCallback : public SourceFileCallbacks { VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {} bool handleBeginSource(CompilerInstance &CI) override {