https://github.com/upsj updated https://github.com/llvm/llvm-project/pull/177442

>From 0b997c6786c68aa29278d27900ce1ecd2e09bb32 Mon Sep 17 00:00:00 2001
From: Tobias Ribizel <[email protected]>
Date: Thu, 22 Jan 2026 20:20:45 +0100
Subject: [PATCH 1/3] format files

---
 clang/lib/Tooling/Transformer/RangeSelector.cpp | 3 +--
 clang/unittests/Tooling/RangeSelectorTest.cpp   | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp 
b/clang/lib/Tooling/Transformer/RangeSelector.cpp
index 68b16f91652fb..8ba065f98864e 100644
--- a/clang/lib/Tooling/Transformer/RangeSelector.cpp
+++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp
@@ -405,8 +405,7 @@ RangeSelector transformer::constructExprArgs(std::string 
ID) {
 namespace {
 // Returns the range of the elements of the initializer list. Includes all
 // source between the braces.
-CharSourceRange getElementsRange(const MatchResult &,
-                                 const InitListExpr &E) {
+CharSourceRange getElementsRange(const MatchResult &, const InitListExpr &E) {
   return CharSourceRange::getCharRange(E.getLBraceLoc().getLocWithOffset(1),
                                        E.getRBraceLoc());
 }
diff --git a/clang/unittests/Tooling/RangeSelectorTest.cpp 
b/clang/unittests/Tooling/RangeSelectorTest.cpp
index 9e83fa1dc92ff..543902bcafeab 100644
--- a/clang/unittests/Tooling/RangeSelectorTest.cpp
+++ b/clang/unittests/Tooling/RangeSelectorTest.cpp
@@ -173,7 +173,7 @@ TEST(RangeSelectorTest, AfterOp) {
   )cc";
   StringRef Call = "call";
   TestMatch Match = matchCode(Code, callExpr().bind(Call));
-  const auto* E = Match.Result.Nodes.getNodeAs<Expr>(Call);
+  const auto *E = Match.Result.Nodes.getNodeAs<Expr>(Call);
   assert(E != nullptr);
   const SourceRange Range = E->getSourceRange();
   // The end token, a right paren, is one character wide, so advance by one,

>From 6c2dbd6cbf7df3998c6121d9902cb77e1310c217 Mon Sep 17 00:00:00 2001
From: Tobias Ribizel <[email protected]>
Date: Thu, 22 Jan 2026 20:22:37 +0100
Subject: [PATCH 2/3] [clang] add transformer range selector for spelled ranges

This supports transformer-based text replacements inside
macro definitions using the new spelled(...) function
as well as retrieving names of declarations inside
macro definitions using the existing name(...) function
---
 .../clang/Tooling/Transformer/RangeSelector.h |  5 ++
 .../lib/Tooling/Transformer/RangeSelector.cpp | 23 +++++++++
 clang/unittests/Tooling/RangeSelectorTest.cpp | 48 +++++++++++++++----
 3 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/Tooling/Transformer/RangeSelector.h 
b/clang/include/clang/Tooling/Transformer/RangeSelector.h
index c76a5106edd65..24cdc9133b5f3 100644
--- a/clang/include/clang/Tooling/Transformer/RangeSelector.h
+++ b/clang/include/clang/Tooling/Transformer/RangeSelector.h
@@ -111,6 +111,11 @@ RangeSelector elseBranch(std::string ID);
 /// source), if `S` is an expansion, and `S` itself, otherwise.  Corresponds to
 /// `SourceManager::getExpansionRange`.
 RangeSelector expansion(RangeSelector S);
+
+/// Selects the spelling range of `S` if it is spelled inside a macro
+/// definition, and `S` itself, otherwise. Corresponds to calling
+/// `SourceManager::getSpellingLoc` on both endpoints.
+RangeSelector spelled(RangeSelector S);
 } // namespace transformer
 } // namespace clang
 
diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp 
b/clang/lib/Tooling/Transformer/RangeSelector.cpp
index 8ba065f98864e..9e40620e1f91d 100644
--- a/clang/lib/Tooling/Transformer/RangeSelector.cpp
+++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp
@@ -257,6 +257,8 @@ RangeSelector transformer::name(std::string ID) {
       if (!D->getDeclName().isIdentifier())
         return missingPropertyError(ID, "name", "identifier");
       SourceLocation L = D->getLocation();
+      // the name may be spelled in a macro
+      L = Result.SourceManager->getSpellingLoc(L);
       auto R = CharSourceRange::getTokenRange(L, L);
       // Verify that the range covers exactly the name.
       // FIXME: extend this code to support cases like `operator +` or
@@ -436,3 +438,24 @@ RangeSelector transformer::expansion(RangeSelector S) {
     return Result.SourceManager->getExpansionRange(*SRange);
   };
 }
+
+RangeSelector transformer::spelled(RangeSelector S) {
+  return [S](const MatchResult &Result) -> Expected<CharSourceRange> {
+    Expected<CharSourceRange> SRange = S(Result);
+    if (!SRange)
+      return SRange.takeError();
+    if (!SRange->isTokenRange()) {
+      return invalidArgumentError("spelled: only supports token ranges");
+    }
+    const auto &SM = *Result.SourceManager;
+    const auto B = SRange->getBegin();
+    const auto E = SRange->getEnd();
+    if (SM.getFileID(B) != SM.getFileID(E)) {
+      return invalidArgumentError(
+          "spelled: range crosses file/macro boundaries");
+    }
+    return CharSourceRange(
+        SourceRange(SM.getSpellingLoc(B), SM.getSpellingLoc(E)),
+        SRange->isTokenRange());
+  };
+}
diff --git a/clang/unittests/Tooling/RangeSelectorTest.cpp 
b/clang/unittests/Tooling/RangeSelectorTest.cpp
index 543902bcafeab..7fd71177dfc03 100644
--- a/clang/unittests/Tooling/RangeSelectorTest.cpp
+++ b/clang/unittests/Tooling/RangeSelectorTest.cpp
@@ -583,19 +583,14 @@ TEST(RangeSelectorTest, NameOpDeclInMacroArg) {
   EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("x"));
 }
 
-TEST(RangeSelectorTest, NameOpDeclInMacroBodyError) {
+TEST(RangeSelectorTest, NameSpelledInMacro) {
   StringRef Code = R"cc(
-  #define MACRO int x;
-  MACRO
+  #define NAME foo;
+  int NAME;
   )cc";
   const char *ID = "id";
   TestMatch Match = matchCode(Code, varDecl().bind(ID));
-  EXPECT_THAT_EXPECTED(
-      name(ID)(Match.Result),
-      Failed<StringError>(testing::Property(
-          &StringError::getMessage,
-          AllOf(HasSubstr("range selected by name(node id="),
-                HasSubstr("' is different from decl name 'x'")))));
+  EXPECT_THAT_EXPECTED(select(name(ID), Match), HasValue("foo"));
 }
 
 TEST(RangeSelectorTest, CallArgsOp) {
@@ -924,6 +919,41 @@ TEST(RangeSelectorTest, ExpansionOpPartial) {
                        HasValue("BADDECL(x * x)"));
 }
 
+TEST(RangeSelectorTest, SpelledFullyInMacro) {
+  StringRef Code = R"cc(
+    #define MACRO int i;
+    MACRO
+  )cc";
+  const char *ID = "id";
+  TestMatch Match = matchCode(Code, varDecl().bind(ID));
+  EXPECT_THAT_EXPECTED(select(spelled(node(ID)), Match), HasValue("int i"));
+}
+
+TEST(RangeSelectorTest, SpelledWithArgumentInMacro) {
+  StringRef Code = R"cc(
+    #define MACRO(T) void foo(T t);
+    MACRO(int)
+  )cc";
+  const char *ID = "id";
+  TestMatch Match = matchCode(Code, functionDecl().bind(ID));
+  EXPECT_THAT_EXPECTED(select(spelled(node(ID)), Match),
+                       HasValue("void foo(T t)"));
+}
+
+TEST(RangeSelectorTest, SpelledPartiallyInMacro) {
+  StringRef Code = R"cc(
+    #define MACRO(T) foo(T t); int i;
+    void MACRO(int);
+  )cc";
+  const char *ID = "id";
+  TestMatch Match = matchCode(Code, functionDecl().bind(ID));
+  EXPECT_THAT_EXPECTED(
+      select(spelled(node(ID)), Match),
+      Failed<StringError>(testing::Property(
+          &StringError::getMessage,
+          HasSubstr("spelled: range crosses file/macro boundaries"))));
+}
+
 TEST(RangeSelectorTest, IfBoundOpBound) {
   StringRef Code = R"cc(
     int f() {

>From 93fdc614c2940054ae07c51a299783b696c6d2a3 Mon Sep 17 00:00:00 2001
From: Tobias Ribizel <[email protected]>
Date: Fri, 23 Jan 2026 17:14:43 +0100
Subject: [PATCH 3/3] [clang] less restrictive spelled(...) selector

---
 clang/lib/Tooling/Transformer/RangeSelector.cpp | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/clang/lib/Tooling/Transformer/RangeSelector.cpp 
b/clang/lib/Tooling/Transformer/RangeSelector.cpp
index 9e40620e1f91d..6e5d12a500bac 100644
--- a/clang/lib/Tooling/Transformer/RangeSelector.cpp
+++ b/clang/lib/Tooling/Transformer/RangeSelector.cpp
@@ -444,16 +444,9 @@ RangeSelector transformer::spelled(RangeSelector S) {
     Expected<CharSourceRange> SRange = S(Result);
     if (!SRange)
       return SRange.takeError();
-    if (!SRange->isTokenRange()) {
-      return invalidArgumentError("spelled: only supports token ranges");
-    }
     const auto &SM = *Result.SourceManager;
     const auto B = SRange->getBegin();
     const auto E = SRange->getEnd();
-    if (SM.getFileID(B) != SM.getFileID(E)) {
-      return invalidArgumentError(
-          "spelled: range crosses file/macro boundaries");
-    }
     return CharSourceRange(
         SourceRange(SM.getSpellingLoc(B), SM.getSpellingLoc(E)),
         SRange->isTokenRange());

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

Reply via email to