[clang] [clang] Adjust TextDiagnostic style ranges for interesting source region (PR #164941)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 28 23:28:14 PDT 2025


https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/164941

>From cde792d4d439aeaf1bda84a929b348ba073bb017 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Fri, 24 Oct 2025 09:59:45 +0200
Subject: [PATCH] [clang] Adjust TextDiagnostic style ranges for interesting
 source region

---
 clang/lib/Frontend/TextDiagnostic.cpp | 59 ++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp
index f5add2a941f72..88d4e5e4e70d4 100644
--- a/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/clang/lib/Frontend/TextDiagnostic.cpp
@@ -316,11 +316,11 @@ struct SourceColumnMap {
 
 /// When the source code line we want to print is too long for
 /// the terminal, select the "interesting" region.
-static void selectInterestingSourceRegion(std::string &SourceLine,
-                                          std::string &CaretLine,
-                                          std::string &FixItInsertionLine,
-                                          unsigned Columns,
-                                          const SourceColumnMap &map) {
+static void selectInterestingSourceRegion(
+    std::string &SourceLine, std::string &CaretLine,
+    std::string &FixItInsertionLine, unsigned Columns,
+    const SourceColumnMap &map,
+    SmallVector<clang::TextDiagnostic::StyleRange> &Styles) {
   unsigned CaretColumns = CaretLine.size();
   unsigned FixItColumns = llvm::sys::locale::columnWidth(FixItInsertionLine);
   unsigned MaxColumns = std::max(static_cast<unsigned>(map.columns()),
@@ -409,10 +409,10 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
   if (TargetColumns > ellipses_space+CaretColumnsOutsideSource)
     TargetColumns -= ellipses_space+CaretColumnsOutsideSource;
 
-  while (SourceStart>0 || SourceEnd<SourceLine.size()) {
+  while (SourceStart > 0 || SourceEnd < SourceLine.size()) {
     bool ExpandedRegion = false;
 
-    if (SourceStart>0) {
+    if (SourceStart > 0) {
       unsigned NewStart = map.startOfPreviousColumn(SourceStart);
 
       // Skip over any whitespace we see here; we're looking for
@@ -487,8 +487,41 @@ static void selectInterestingSourceRegion(std::string &SourceLine,
   if (BackColumnsRemoved > strlen(back_ellipse))
     SourceLine.replace(SourceEnd, std::string::npos, back_ellipse);
 
+  // Since we've modified the SourceLine, we also need to adjust the line's
+  // highlighting information. In particular, if we've removed
+  // from the front of the line, we need to move the style ranges to the
+  // left and remove unneeded ranges.
+  unsigned FrontDiff = FrontColumnsRemoved > strlen(front_ellipse)
+                           ? FrontColumnsRemoved - strlen(front_ellipse)
+                           : 0;
+  unsigned CodeStart =
+      FrontColumnsRemoved > strlen(front_ellipse) ? strlen(front_ellipse) : 0;
+  unsigned CodeEnd = CodeStart + ColumnsKept;
+  for (auto &R : Styles) {
+    // Style ranges too far left. Just move them where they don't bother.
+    if (R.End < FrontDiff) {
+      R.Start = R.End = std::numeric_limits<unsigned>::max();
+      continue;
+    }
+    // Move them left. (Note that this can wrap R.Start, but that doesn't
+    // matter).
+    R.Start -= FrontDiff;
+    R.End -= FrontDiff;
+
+    // Style ranges too far to the right.
+    if (R.Start >= (ColumnsKept + strlen(front_ellipse))) {
+      R.Start = R.End = std::numeric_limits<unsigned>::max();
+      continue;
+    }
+
+    // If the range overlaps the end of the code, don't leak into the back
+    // ellipse.
+    if (R.Start < CodeEnd && R.End > CodeEnd)
+      R.End = CodeEnd;
+  }
+
   // If that's enough then we're done
-  if (FrontColumnsRemoved+ColumnsKept <= Columns)
+  if (FrontColumnsRemoved + ColumnsKept <= Columns)
     return;
 
   // Otherwise remove the front as well
@@ -1347,6 +1380,11 @@ void TextDiagnostic::emitSnippetAndCaret(
       OS.indent(MaxLineNoDisplayWidth + 2) << "| ";
   };
 
+  unsigned Columns = DiagOpts.MessageLength;
+  // If we don't have enough columns available, just abort now.
+  if (Columns && Columns <= (MaxLineNoDisplayWidth + 4))
+    return;
+
   // Prepare source highlighting information for the lines we're about to
   // emit, starting from the first line.
   std::unique_ptr<SmallVector<StyleRange>[]> SourceStyles =
@@ -1404,10 +1442,11 @@ void TextDiagnostic::emitSnippetAndCaret(
 
     // If the source line is too long for our terminal, select only the
     // "interesting" source region within that line.
-    unsigned Columns = DiagOpts.MessageLength;
     if (Columns)
       selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine,
-                                    Columns, sourceColMap);
+                                    (Columns - (MaxLineNoDisplayWidth + 4)),
+                                    sourceColMap,
+                                    SourceStyles[LineNo - Lines.first]);
 
     // If we are in -fdiagnostics-print-source-range-info mode, we are trying
     // to produce easily machine parsable output.  Add a space before the



More information about the cfe-commits mailing list