[clang] 659f4bd - [clang] Add an option for hiding line numbers in diagnostics

Raphael Isemann via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 5 07:11:03 PST 2020


Author: Raphael Isemann
Date: 2020-11-05T16:10:18+01:00
New Revision: 659f4bd87efc7cae379aa128814e03fc8b006471

URL: https://github.com/llvm/llvm-project/commit/659f4bd87efc7cae379aa128814e03fc8b006471
DIFF: https://github.com/llvm/llvm-project/commit/659f4bd87efc7cae379aa128814e03fc8b006471.diff

LOG: [clang] Add an option for hiding line numbers in diagnostics

Clang offers a `-f[no]-show-column` flag for hiding the column numbers when
printing diagnostics but there is no option for doing the same with line
numbers.

In LLDB having this option would be useful, as LLDB sometimes only knows the
file name for a SourceLocation and just assigns it the dummy line/column `1:1`.
These fake line/column numbers are confusing to the user and LLDB should be able
to tell clang to hide *both* the column and the line number when rendering text
diagnostics.

This patch adds a flag for also hiding the line numbers. It's not exposed via
the command line flags as it's most likely not very useful for any user and can
lead to ambiguous output when the user decides to only hide either the line or
the column number (where `file:1: ...` could now refer to both line 1 or column
1 depending on the compiler flags). LLDB can just access the DiagnosticOptions
directly when constructing its internal Clang instance.

The effect doesn't apply to Vi/MSVC style diagnostics because it's not defined
how these diagnostic styles would show an omitted line number (MSVC doesn't have
such an option and Vi's line mode is theory only supporting line numbers if I
understand it correctly).

Reviewed By: thakis, MaskRay

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

Added: 
    clang/unittests/Frontend/TextDiagnosticTest.cpp

Modified: 
    clang/include/clang/Basic/DiagnosticOptions.def
    clang/lib/Frontend/TextDiagnostic.cpp
    clang/unittests/Frontend/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticOptions.def b/clang/include/clang/Basic/DiagnosticOptions.def
index a946b5c6be8e..927710a0cb9a 100644
--- a/clang/include/clang/Basic/DiagnosticOptions.def
+++ b/clang/include/clang/Basic/DiagnosticOptions.def
@@ -47,6 +47,7 @@ SEMANTIC_DIAGOPT(IgnoreWarnings, 1, 0)   /// -w
 DIAGOPT(NoRewriteMacros, 1, 0)  /// -Wno-rewrite-macros
 DIAGOPT(Pedantic, 1, 0)         /// -pedantic
 DIAGOPT(PedanticErrors, 1, 0)   /// -pedantic-errors
+DIAGOPT(ShowLine, 1, 1)         /// Show line number on diagnostics.
 DIAGOPT(ShowColumn, 1, 1)       /// Show column number on diagnostics.
 DIAGOPT(ShowLocation, 1, 1)     /// Show source location information.
 DIAGOPT(ShowLevel, 1, 1)        /// Show diagnostic level.

diff  --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp
index 78acaaf9f96e..e781fd2c0229 100644
--- a/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/clang/lib/Frontend/TextDiagnostic.cpp
@@ -827,7 +827,10 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc,
 
   emitFilename(PLoc.getFilename(), Loc.getManager());
   switch (DiagOpts->getFormat()) {
-  case DiagnosticOptions::Clang: OS << ':'  << LineNo; break;
+  case DiagnosticOptions::Clang:
+    if (DiagOpts->ShowLine)
+      OS << ':' << LineNo;
+    break;
   case DiagnosticOptions::MSVC:  OS << '('  << LineNo; break;
   case DiagnosticOptions::Vi:    OS << " +" << LineNo; break;
   }

diff  --git a/clang/unittests/Frontend/CMakeLists.txt b/clang/unittests/Frontend/CMakeLists.txt
index d247089e9295..3c25b43e9530 100644
--- a/clang/unittests/Frontend/CMakeLists.txt
+++ b/clang/unittests/Frontend/CMakeLists.txt
@@ -12,6 +12,7 @@ add_clang_unittest(FrontendTests
   ParsedSourceLocationTest.cpp
   PCHPreambleTest.cpp
   OutputStreamTest.cpp
+  TextDiagnosticTest.cpp
   )
 clang_target_link_libraries(FrontendTests
   PRIVATE

diff  --git a/clang/unittests/Frontend/TextDiagnosticTest.cpp b/clang/unittests/Frontend/TextDiagnosticTest.cpp
new file mode 100644
index 000000000000..1e05104d9388
--- /dev/null
+++ b/clang/unittests/Frontend/TextDiagnosticTest.cpp
@@ -0,0 +1,100 @@
+//===- unittests/Frontend/TextDiagnosticTest.cpp - ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/TextDiagnostic.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/SmallVectorMemoryBuffer.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+/// Prints a diagnostic with the given DiagnosticOptions and the given
+/// SourceLocation and returns the printed diagnostic text.
+static std::string PrintDiag(const DiagnosticOptions &Opts, FullSourceLoc Loc) {
+  std::string Out;
+  llvm::raw_string_ostream OS(Out);
+  clang::LangOptions LangOpts;
+  // Owned by TextDiagnostic.
+  DiagnosticOptions *DiagOpts = new DiagnosticOptions(Opts);
+  TextDiagnostic Diag(OS, LangOpts, DiagOpts);
+  // Emit a dummy diagnostic that is just 'message'.
+  Diag.emitDiagnostic(Loc, DiagnosticsEngine::Level::Warning, "message",
+                      /*Ranges=*/{}, /*FixItHints=*/{});
+  OS.flush();
+  return Out;
+}
+
+TEST(TextDiagnostic, ShowLine) {
+  // Create dummy FileManager and SourceManager.
+  FileSystemOptions FSOpts;
+  FileManager FileMgr(FSOpts);
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs);
+  DiagnosticsEngine DiagEngine(DiagID, new DiagnosticOptions,
+                               new IgnoringDiagConsumer());
+  SourceManager SrcMgr(DiagEngine, FileMgr);
+
+  // Create a dummy file with some contents to produce a test SourceLocation.
+  const llvm::StringRef file_path = "main.cpp";
+  const llvm::StringRef main_file_contents = "some\nsource\ncode\n";
+  const clang::FileEntry &fe = *FileMgr.getVirtualFile(
+      file_path,
+      /*Size=*/static_cast<off_t>(main_file_contents.size()),
+      /*ModificationTime=*/0);
+
+  llvm::SmallVector<char, 64> buffer;
+  buffer.append(main_file_contents.begin(), main_file_contents.end());
+  auto file_contents = std::make_unique<llvm::SmallVectorMemoryBuffer>(
+      std::move(buffer), file_path);
+  SrcMgr.overrideFileContents(&fe, std::move(file_contents));
+
+  // Create the actual file id and use it as the main file.
+  clang::FileID fid =
+      SrcMgr.createFileID(&fe, SourceLocation(), clang::SrcMgr::C_User);
+  SrcMgr.setMainFileID(fid);
+
+  // Create the source location for the test diagnostic.
+  FullSourceLoc Loc(SrcMgr.translateLineCol(fid, /*Line=*/1, /*Col=*/2),
+                    SrcMgr);
+
+  DiagnosticOptions DiagOpts;
+  DiagOpts.ShowLine = true;
+  DiagOpts.ShowColumn = true;
+  // Hide printing the source line/caret to make the diagnostic shorter and it's
+  // not relevant for this test.
+  DiagOpts.ShowCarets = false;
+  EXPECT_EQ("main.cpp:1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
+
+  // Check that ShowLine doesn't influence the Vi/MSVC diagnostic formats as its
+  // a Clang-specific diagnostic option.
+  DiagOpts.setFormat(TextDiagnosticFormat::Vi);
+  DiagOpts.ShowLine = false;
+  EXPECT_EQ("main.cpp +1:2: warning: message\n", PrintDiag(DiagOpts, Loc));
+
+  DiagOpts.setFormat(TextDiagnosticFormat::MSVC);
+  DiagOpts.ShowLine = false;
+  EXPECT_EQ("main.cpp(1,2): warning: message\n", PrintDiag(DiagOpts, Loc));
+
+  // Reset back to the Clang format.
+  DiagOpts.setFormat(TextDiagnosticFormat::Clang);
+
+  // Hide line number but show column.
+  DiagOpts.ShowLine = false;
+  EXPECT_EQ("main.cpp:2: warning: message\n", PrintDiag(DiagOpts, Loc));
+
+  // Show line number but hide column.
+  DiagOpts.ShowLine = true;
+  DiagOpts.ShowColumn = false;
+  EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc));
+}
+
+} // anonymous namespace


        


More information about the cfe-commits mailing list