[llvm-branch-commits] [clang] [clang] Reject ranges getExpansionRangeInFile cannot represent (PR #214461)

Balázs Benics via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Aug 6 05:02:41 PDT 2026


https://github.com/steakhal created https://github.com/llvm/llvm-project/pull/214461

getExpansionRangeInFile was extracted verbatim and inherited two shortcomings
of the original loop, fixed here before the analyzer's SARIF and HTML consumers
depend on it:

- It mapped the end with getExpansionRange(SourceLocation), which always
  reports a token range, so a char-range input was widened by a whole token.
  Now using the getExpansionRange(CharSourceRange) overload, which keeps the flag.
- It passed reversed ranges through. Consumers walk begin->end; now returning
  nullopt for those, as Lexer::makeFileCharRange already does.

Separate from the extraction so that stays NFC, and out of the consumer fixes
because it changes the shared helper's contract rather than one output.

Assisted-By: claude

---

<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

>From 0ebe256501fa9779b0aed888e2d7469f26f5ed63 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 6 Aug 2026 11:02:08 +0100
Subject: [PATCH] [clang] Reject ranges getExpansionRangeInFile cannot
 represent

getExpansionRangeInFile was extracted verbatim and inherited two shortcomings
of the original loop, fixed here before the analyzer's SARIF and HTML consumers
depend on it:

- It mapped the end with getExpansionRange(SourceLocation), which always
  reports a token range, so a char-range input was widened by a whole token.
  Now using the getExpansionRange(CharSourceRange) overload, which keeps the flag.
- It passed reversed ranges through. Consumers walk begin->end; now returning
  nullopt for those, as Lexer::makeFileCharRange already does.

Separate from the extraction so that stays NFC, and out of the consumer fixes
because it changes the shared helper's contract rather than one output.

Assisted-By: claude
---
 clang/include/clang/Frontend/DiagnosticRenderer.h |  4 ++--
 clang/lib/Frontend/DiagnosticRenderer.cpp         | 13 ++++++++-----
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Frontend/DiagnosticRenderer.h b/clang/include/clang/Frontend/DiagnosticRenderer.h
index 6f9fe0422088f..2adec4da12cb2 100644
--- a/clang/include/clang/Frontend/DiagnosticRenderer.h
+++ b/clang/include/clang/Frontend/DiagnosticRenderer.h
@@ -34,8 +34,8 @@ 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 std::nullopt if \p Range is invalid or an
-/// endpoint lies outside \p FID.
+/// can be shown to a user. Returns std::nullopt if \p Range is invalid, if an
+/// endpoint lies outside \p FID, or if the endpoints come out reversed.
 ///
 /// Unlike Lexer::makeFileCharRange(), which gives up when an endpoint is
 /// strictly inside an expansion, this points at the expansion; prefer
diff --git a/clang/lib/Frontend/DiagnosticRenderer.cpp b/clang/lib/Frontend/DiagnosticRenderer.cpp
index c0c6e15ec0378..c8e9314d989f6 100644
--- a/clang/lib/Frontend/DiagnosticRenderer.cpp
+++ b/clang/lib/Frontend/DiagnosticRenderer.cpp
@@ -40,14 +40,17 @@ clang::getExpansionRangeInFile(CharSourceRange Range, FileID FID,
   if (Range.isInvalid())
     return std::nullopt;
 
-  SourceLocation Begin = SM.getExpansionLoc(Range.getBegin());
-  CharSourceRange EndRange = SM.getExpansionRange(Range.getEnd());
-  SourceLocation End = EndRange.getEnd();
+  CharSourceRange Expansion = SM.getExpansionRange(Range);
+  if (SM.getFileID(Expansion.getBegin()) != FID ||
+      SM.getFileID(Expansion.getEnd()) != FID)
+    return std::nullopt;
 
-  if (SM.getFileID(Begin) != FID || SM.getFileID(End) != FID)
+  // Both endpoints are in FID, so comparing their offsets is meaningful.
+  if (SM.getFileOffset(Expansion.getBegin()) >
+      SM.getFileOffset(Expansion.getEnd()))
     return std::nullopt;
 
-  return CharSourceRange(SourceRange(Begin, End), EndRange.isTokenRange());
+  return Expansion;
 }
 
 namespace {



More information about the llvm-branch-commits mailing list