Author: Jan Svoboda Date: 2021-04-06T10:40:47+02:00 New Revision: 2935737da32dd21bf02e1a3c912a340de660d557
URL: https://github.com/llvm/llvm-project/commit/2935737da32dd21bf02e1a3c912a340de660d557 DIFF: https://github.com/llvm/llvm-project/commit/2935737da32dd21bf02e1a3c912a340de660d557.diff LOG: [clang][tooling] Create SourceManager for DiagnosticsEngine before command-line parsing In 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. Test authored by Jordan Rupprecht. Reviewed By: rupprecht Differential Revision: https://reviews.llvm.org/D99414 Added: Modified: clang/lib/Tooling/Tooling.cpp clang/unittests/Tooling/ToolingTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index b28e8f6a7c96..463f466d9b76 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -334,6 +334,10 @@ bool ToolInvocation::run() { 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())); diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index 691a847d5a71..313e8325c615 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -221,6 +221,43 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) { 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 { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits