Author: Balázs Benics
Date: 2026-08-10T14:11:50+01:00
New Revision: 4aa2d83fa19b11382917eaedfd10a495ac6feede

URL: 
https://github.com/llvm/llvm-project/commit/4aa2d83fa19b11382917eaedfd10a495ac6feede
DIFF: 
https://github.com/llvm/llvm-project/commit/4aa2d83fa19b11382917eaedfd10a495ac6feede.diff

LOG: [clang][NFC] Extract getExpansionRangeInFile out of the diagnostic 
renderers (#214460)

Prep for the following commits, which fix crashes in the analyzer's
SARIF and HTML output on ranges that end inside a macro expansion.
Fixing them means mapping such a range into the reported file - the
normalization the frontend text and SARIF renderers already do, and that
the two analyzer consumers each do differently and incorrectly.

Hoist that logic into getExpansionRangeInFile, beside the DiagnosticRenderer
base both frontend renderers derive from, so the fixes reuse one
implementation instead of adding two more copies. TextDiagnostic and
SARIFDiagnostic move onto it here with no behavior change; the analyzer
consumers follow in later commits.

getFileID() replaces SARIFDiagnostic's getDecomposedLoc(...).first - equivalent
here, and what TextDiagnostic has used since c113cbb51005.

Assisted-By: claude

Added: 
    

Modified: 
    clang/include/clang/Frontend/DiagnosticRenderer.h
    clang/lib/Frontend/DiagnosticRenderer.cpp
    clang/lib/Frontend/SARIFDiagnostic.cpp
    clang/lib/Frontend/TextDiagnostic.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Frontend/DiagnosticRenderer.h 
b/clang/include/clang/Frontend/DiagnosticRenderer.h
index 3f03a6e02da4b..0b123a87131ff 100644
--- a/clang/include/clang/Frontend/DiagnosticRenderer.h
+++ b/clang/include/clang/Frontend/DiagnosticRenderer.h
@@ -23,6 +23,7 @@
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/StringRef.h"
+#include <optional>
 
 namespace clang {
 
@@ -32,6 +33,14 @@ class SourceManager;
 using DiagOrStoredDiag =
     llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>;
 
+/// Maps both endpoints of \p Range to their macro expansion, so that the range
+/// can be shown to a user.
+///
+/// \returns nullopt if \p Range is invalid, if an endpoint lies outside \p 
FID.
+std::optional<CharSourceRange> getExpansionRangeInFile(CharSourceRange Range,
+                                                       FileID FID,
+                                                       const SourceManager 
&SM);
+
 /// Class to encapsulate the logic for formatting a diagnostic message.
 ///
 /// Actual "printing" logic is implemented by subclasses.

diff  --git a/clang/lib/Frontend/DiagnosticRenderer.cpp 
b/clang/lib/Frontend/DiagnosticRenderer.cpp
index 2b6fbc274e587..910aa1054b602 100644
--- a/clang/lib/Frontend/DiagnosticRenderer.cpp
+++ b/clang/lib/Frontend/DiagnosticRenderer.cpp
@@ -34,6 +34,21 @@ DiagnosticRenderer::DiagnosticRenderer(const LangOptions 
&LangOpts,
 
 DiagnosticRenderer::~DiagnosticRenderer() = default;
 
+std::optional<CharSourceRange>
+clang::getExpansionRangeInFile(CharSourceRange Range, FileID FID,
+                               const SourceManager &SM) {
+  if (Range.isInvalid())
+    return std::nullopt;
+
+  CharSourceRange Expansion = SM.getExpansionRange(Range);
+  if (SM.getFileID(Expansion.getBegin()) != FID ||
+      SM.getFileID(Expansion.getEnd()) != FID) {
+    return std::nullopt;
+  }
+
+  return Expansion;
+}
+
 namespace {
 
 class FixitReceiver : public edit::EditsReceiver {

diff  --git a/clang/lib/Frontend/SARIFDiagnostic.cpp 
b/clang/lib/Frontend/SARIFDiagnostic.cpp
index 04ee14edfe74c..5183462b76f41 100644
--- a/clang/lib/Frontend/SARIFDiagnostic.cpp
+++ b/clang/lib/Frontend/SARIFDiagnostic.cpp
@@ -120,29 +120,20 @@ SARIFDiagnostic::getSarifLocation(FullSourceLoc Loc, 
PresumedLoc PLoc,
 
   FileID CaretFileID = Loc.getExpansionLoc().getFileID();
 
+  auto &SM = Loc.getManager();
   for (const CharSourceRange Range : Ranges) {
-    // Ignore invalid ranges.
-    if (Range.isInvalid())
+    std::optional<CharSourceRange> FileRange =
+        getExpansionRangeInFile(Range, CaretFileID, SM);
+    if (!FileRange)
       continue;
 
-    auto &SM = Loc.getManager();
-    SourceLocation B = SM.getExpansionLoc(Range.getBegin());
-    CharSourceRange ERange = SM.getExpansionRange(Range.getEnd());
-    SourceLocation E = ERange.getEnd();
-    bool IsTokenRange = ERange.isTokenRange();
-
-    FileIDAndOffset BInfo = SM.getDecomposedLoc(B);
-    FileIDAndOffset EInfo = SM.getDecomposedLoc(E);
-
-    // If the start or end of the range is in another file, just discard
-    // it.
-    if (BInfo.first != CaretFileID || EInfo.first != CaretFileID)
-      continue;
+    SourceLocation B = FileRange->getBegin();
+    SourceLocation E = FileRange->getEnd();
 
     // Add in the length of the token, so that we cover multi-char
     // tokens.
     unsigned TokSize = 0;
-    if (IsTokenRange)
+    if (FileRange->isTokenRange())
       TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
 
     FullSourceLoc BF(B, SM), EF(E, SM);
@@ -157,7 +148,6 @@ SARIFDiagnostic::getSarifLocation(FullSourceLoc Loc, 
PresumedLoc PLoc,
     // Text and SARIF diagnostics.
   }
 
-  auto &SM = Loc.getManager();
   auto FID = PLoc.getFileID();
   // Visual Studio 2010 or earlier expects column number to be off by one.
   unsigned int ColNo = (LangOpts.MSCompatibilityVersion &&

diff  --git a/clang/lib/Frontend/TextDiagnostic.cpp 
b/clang/lib/Frontend/TextDiagnostic.cpp
index 01a4d2f6392d3..5221ed4de02ff 100644
--- a/clang/lib/Frontend/TextDiagnostic.cpp
+++ b/clang/lib/Frontend/TextDiagnostic.cpp
@@ -921,23 +921,18 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, 
PresumedLoc PLoc,
     const SourceManager &SM = Loc.getManager();
 
     for (const auto &R : Ranges) {
-      // Ignore invalid ranges.
-      if (!R.isValid())
+      std::optional<CharSourceRange> FileRange =
+          getExpansionRangeInFile(R, CaretFileID, SM);
+      if (!FileRange)
         continue;
 
-      SourceLocation B = SM.getExpansionLoc(R.getBegin());
-      CharSourceRange ERange = SM.getExpansionRange(R.getEnd());
-      SourceLocation E = ERange.getEnd();
-
-      // If the start or end of the range is in another file, just
-      // discard it.
-      if (SM.getFileID(B) != CaretFileID || SM.getFileID(E) != CaretFileID)
-        continue;
+      SourceLocation B = FileRange->getBegin();
+      SourceLocation E = FileRange->getEnd();
 
       // Add in the length of the token, so that we cover multi-char
       // tokens.
       unsigned TokSize = 0;
-      if (ERange.isTokenRange())
+      if (FileRange->isTokenRange())
         TokSize = Lexer::MeasureTokenLength(E, SM, LangOpts);
 
       FullSourceLoc BF(B, SM), EF(E, SM);


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to