jansvoboda11 created this revision. jansvoboda11 added a reviewer: rupprecht. jansvoboda11 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
In D84673 <https://reviews.llvm.org/D84673>, we started using `DiagnosticsEngine` during command-line parsing in more contexts. When using `ToolInvocation`, a custom `DiagnosticsConsumer` can be specified and it might expect `SourceManager` to be present on the emitted diagnostics. This patch ensures the `SourceManager` is set up in such scenarios. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D99414 Files: clang/lib/Tooling/Tooling.cpp clang/unittests/Tooling/ToolingTest.cpp Index: clang/unittests/Tooling/ToolingTest.cpp =================================================================== --- clang/unittests/Tooling/ToolingTest.cpp +++ clang/unittests/Tooling/ToolingTest.cpp @@ -221,6 +221,43 @@ EXPECT_TRUE(Invocation.run()); } +struct DiagnosticConsumerExpectingSourceManager : public DiagnosticConsumer { + bool SawSourceManager; + + DiagnosticConsumerExpectingSourceManager() : SawSourceManager(false) {} + + void HandleDiagnostic(clang::DiagnosticsEngine::Level, + const clang::Diagnostic &info) override { + SawSourceManager = info.hasSourceManager(); + } +}; + +TEST(ToolInvocation, DiagConsumerExpectingSourceManager) { + llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( + new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + OverlayFileSystem->pushOverlay(InMemoryFileSystem); + llvm::IntrusiveRefCntPtr<FileManager> Files( + new FileManager(FileSystemOptions(), OverlayFileSystem)); + std::vector<std::string> 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<SyntaxOnlyAction>(), Files.get()); + InMemoryFileSystem->addFile( + "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main() {}\n")); + + DiagnosticConsumerExpectingSourceManager Consumer; + Invocation.setDiagnosticConsumer(&Consumer); + + EXPECT_TRUE(Invocation.run()); + EXPECT_TRUE(Consumer.SawSourceManager); +} + struct VerifyEndCallback : public SourceFileCallbacks { VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {} bool handleBeginSource(CompilerInstance &CI) override { Index: clang/lib/Tooling/Tooling.cpp =================================================================== --- clang/lib/Tooling/Tooling.cpp +++ clang/lib/Tooling/Tooling.cpp @@ -334,6 +334,10 @@ DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); + // Although `Diagnostics` are used only for command-line parsing, the custom + // `DiagConsumer` might expect a `SourceManager` to be present. + SourceManager SrcMgr(Diagnostics, *Files); + Diagnostics.setSourceManager(&SrcMgr); const std::unique_ptr<driver::Driver> Driver( newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
Index: clang/unittests/Tooling/ToolingTest.cpp =================================================================== --- clang/unittests/Tooling/ToolingTest.cpp +++ clang/unittests/Tooling/ToolingTest.cpp @@ -221,6 +221,43 @@ EXPECT_TRUE(Invocation.run()); } +struct DiagnosticConsumerExpectingSourceManager : public DiagnosticConsumer { + bool SawSourceManager; + + DiagnosticConsumerExpectingSourceManager() : SawSourceManager(false) {} + + void HandleDiagnostic(clang::DiagnosticsEngine::Level, + const clang::Diagnostic &info) override { + SawSourceManager = info.hasSourceManager(); + } +}; + +TEST(ToolInvocation, DiagConsumerExpectingSourceManager) { + llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( + new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); + llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + OverlayFileSystem->pushOverlay(InMemoryFileSystem); + llvm::IntrusiveRefCntPtr<FileManager> Files( + new FileManager(FileSystemOptions(), OverlayFileSystem)); + std::vector<std::string> 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<SyntaxOnlyAction>(), Files.get()); + InMemoryFileSystem->addFile( + "test.cpp", 0, llvm::MemoryBuffer::getMemBuffer("int main() {}\n")); + + DiagnosticConsumerExpectingSourceManager Consumer; + Invocation.setDiagnosticConsumer(&Consumer); + + EXPECT_TRUE(Invocation.run()); + EXPECT_TRUE(Consumer.SawSourceManager); +} + struct VerifyEndCallback : public SourceFileCallbacks { VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {} bool handleBeginSource(CompilerInstance &CI) override { Index: clang/lib/Tooling/Tooling.cpp =================================================================== --- clang/lib/Tooling/Tooling.cpp +++ clang/lib/Tooling/Tooling.cpp @@ -334,6 +334,10 @@ DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); + // Although `Diagnostics` are used only for command-line parsing, the custom + // `DiagConsumer` might expect a `SourceManager` to be present. + SourceManager SrcMgr(Diagnostics, *Files); + Diagnostics.setSourceManager(&SrcMgr); const std::unique_ptr<driver::Driver> Driver( newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits