[clang] 8dc76ab - [clang][tooling] Properly initialize DiagnosticsEngine for cc1 command-line construction

Jan Svoboda via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 10 04:54:44 PDT 2021


Author: Jan Svoboda
Date: 2021-09-10T13:54:24+02:00
New Revision: 8dc76ab7995b6dbc50dd9472f95c40484396b90e

URL: https://github.com/llvm/llvm-project/commit/8dc76ab7995b6dbc50dd9472f95c40484396b90e
DIFF: https://github.com/llvm/llvm-project/commit/8dc76ab7995b6dbc50dd9472f95c40484396b90e.diff

LOG: [clang][tooling] Properly initialize DiagnosticsEngine for cc1 command-line construction

In `ToolInvocation::run`, the driver -> cc1 command-line transformation uses `DiagnosticsEngine` that wasn't completely initialized. This patch ensures `ProcessWarningOptions(DiagnosticsEngine&, const DiagnosticOptions &)` is called.

Depends on D108982.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D108974

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 383fb59fd4f3b..6314615f83c86 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -354,16 +354,16 @@ bool ToolInvocation::run() {
   }
 
   TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DiagOpts);
-  DiagnosticsEngine Diagnostics(
-      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
-      DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
+  IntrusiveRefCntPtr<DiagnosticsEngine> Diagnostics =
+      CompilerInstance::createDiagnostics(
+          &*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);
+  SourceManager SrcMgr(*Diagnostics, *Files);
+  Diagnostics->setSourceManager(&SrcMgr);
 
   const std::unique_ptr<driver::Driver> Driver(
-      newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
+      newDriver(&*Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
   // The "input file not found" diagnostics from the driver are useful.
   // The driver is only aware of the VFS working directory, but some clients
   // change this at the FileManager level instead.
@@ -375,11 +375,11 @@ bool ToolInvocation::run() {
   if (!Compilation)
     return false;
   const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments(
-      &Diagnostics, Compilation.get());
+      &*Diagnostics, Compilation.get());
   if (!CC1Args)
     return false;
   std::unique_ptr<CompilerInvocation> Invocation(
-      newInvocation(&Diagnostics, *CC1Args, BinaryName));
+      newInvocation(&*Diagnostics, *CC1Args, BinaryName));
   return runInvocation(BinaryName, Compilation.get(), std::move(Invocation),
                        std::move(PCHContainerOps));
 }

diff  --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp
index fe85304860069..d5aa8b763669a 100644
--- a/clang/unittests/Tooling/ToolingTest.cpp
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -224,6 +224,82 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) {
   EXPECT_TRUE(Invocation.run());
 }
 
+struct ErrorCountingDiagnosticConsumer : public DiagnosticConsumer {
+  ErrorCountingDiagnosticConsumer() : NumErrorsSeen(0) {}
+  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                        const Diagnostic &Info) override {
+    if (DiagLevel == DiagnosticsEngine::Level::Error)
+      ++NumErrorsSeen;
+  }
+  unsigned NumErrorsSeen;
+};
+
+TEST(ToolInvocation, DiagnosticsEngineProperlyInitializedForCC1Construction) {
+  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");
+  Args.push_back("-target");
+  // Invalid argument that by default results in an error diagnostic:
+  Args.push_back("i386-apple-ios14.0-simulator");
+  // Argument that downgrades the error into a warning:
+  Args.push_back("-Wno-error=invalid-ios-deployment-target");
+  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 a() {}\n"));
+  ErrorCountingDiagnosticConsumer Consumer;
+  Invocation.setDiagnosticConsumer(&Consumer);
+  EXPECT_TRUE(Invocation.run());
+  // Check that `-Wno-error=invalid-ios-deployment-target` downgraded the error
+  // into a warning.
+  EXPECT_EQ(Consumer.NumErrorsSeen, 0u);
+}
+
+TEST(ToolInvocation, CustomDiagnosticOptionsOverwriteParsedOnes) {
+  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");
+  Args.push_back("-target");
+  // Invalid argument that by default results in an error diagnostic:
+  Args.push_back("i386-apple-ios14.0-simulator");
+  // Argument that downgrades the error into a warning:
+  Args.push_back("-Wno-error=invalid-ios-deployment-target");
+  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 a() {}\n"));
+  ErrorCountingDiagnosticConsumer Consumer;
+  Invocation.setDiagnosticConsumer(&Consumer);
+
+  auto DiagOpts = llvm::makeIntrusiveRefCnt<DiagnosticOptions>();
+  Invocation.setDiagnosticOptions(&*DiagOpts);
+
+  EXPECT_TRUE(Invocation.run());
+  // Check that `-Wno-error=invalid-ios-deployment-target` didn't downgrade the
+  // error into a warning due to being overwritten by custom diagnostic options.
+  EXPECT_EQ(Consumer.NumErrorsSeen, 1u);
+}
+
 struct DiagnosticConsumerExpectingSourceManager : public DiagnosticConsumer {
   bool SawSourceManager;
 


        


More information about the cfe-commits mailing list