[clang-tools-extra] [clang-tidy] use specified type verbatim in modernize-use-using fix (PR #113837)

Julian Schmidt via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 1 15:16:33 PST 2024


https://github.com/5chmidti updated https://github.com/llvm/llvm-project/pull/113837

>From 8170641109c09e55b1530081e103a1e919eb8bfc Mon Sep 17 00:00:00 2001
From: Julian Schmidt <git.julian.schmidt at gmail.com>
Date: Sun, 27 Oct 2024 21:49:34 +0100
Subject: [PATCH 1/6] [clang-tidy] do not expand macros in modernize-use-using
 fix

Previously, the implementation used the printed type, which contains the
macro arguments expanded (also deleting comments). Instead, this
check can be more surgical and keep the actual written type as is,
keeping macros unexpanded.

Fixes #33760, #37846
---
 .../clang-tidy/modernize/UseUsingCheck.cpp    | 71 +++++++++++++++----
 .../clang-tidy/modernize/UseUsingCheck.h      |  1 +
 clang-tools-extra/docs/ReleaseNotes.rst       |  3 +
 .../checkers/modernize/use-using.cpp          | 36 ++++++++--
 4 files changed, 93 insertions(+), 18 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index 24eefdb082eb32..74764d95d90520 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -7,9 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "UseUsingCheck.h"
-#include "clang/AST/ASTContext.h"
+#include "../utils/LexerUtils.h"
 #include "clang/AST/DeclGroup.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Lexer.h"
+#include <string>
 
 using namespace clang::ast_matchers;
 namespace {
@@ -119,14 +122,55 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
     return;
   }
 
-  PrintingPolicy PrintPolicy(getLangOpts());
-  PrintPolicy.SuppressScope = true;
-  PrintPolicy.ConstantArraySizeAsWritten = true;
-  PrintPolicy.UseVoidForZeroParams = false;
-  PrintPolicy.PrintInjectedClassNameWithArguments = false;
+  const TypeLoc TL = MatchedDecl->getTypeSourceInfo()->getTypeLoc();
+
+  auto [Type, QualifierStr] = [MatchedDecl, &Result, this,
+                               &TL]() -> std::pair<std::string, std::string> {
+    SourceRange TypeRange = TL.getSourceRange();
+
+    // Function pointer case, get the left and right side of the identifier
+    // without the identifier.
+    if (TypeRange.fullyContains(MatchedDecl->getLocation())) {
+      return {(Lexer::getSourceText(
+                   CharSourceRange::getCharRange(TL.getBeginLoc(),
+                                                 MatchedDecl->getLocation()),
+                   *Result.SourceManager, getLangOpts()) +
+               Lexer::getSourceText(
+                   CharSourceRange::getCharRange(
+                       Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0,
+                                                  *Result.SourceManager,
+                                                  getLangOpts()),
+                       Lexer::getLocForEndOfToken(TL.getEndLoc(), 0,
+                                                  *Result.SourceManager,
+                                                  getLangOpts())),
+                   *Result.SourceManager, getLangOpts()))
+                  .str(),
+              ""};
+    }
+
+    StringRef ExtraReference = "";
+    if (MainTypeEndLoc.isValid() && TypeRange.fullyContains(MainTypeEndLoc)) {
+      const SourceLocation Tok = utils::lexer::findPreviousAnyTokenKind(
+          MatchedDecl->getLocation(), *Result.SourceManager, getLangOpts(),
+          tok::TokenKind::star, tok::TokenKind::amp, tok::TokenKind::comma,
+          tok::TokenKind::kw_typedef);
+
+      ExtraReference = Lexer::getSourceText(
+          CharSourceRange::getCharRange(Tok, Tok.getLocWithOffset(1)),
+          *Result.SourceManager, getLangOpts());
 
-  std::string Type = MatchedDecl->getUnderlyingType().getAsString(PrintPolicy);
-  std::string Name = MatchedDecl->getNameAsString();
+      if (ExtraReference != "*" && ExtraReference != "&")
+        ExtraReference = "";
+
+      if (MainTypeEndLoc.isValid())
+        TypeRange.setEnd(MainTypeEndLoc);
+    }
+    return {Lexer::getSourceText(CharSourceRange::getTokenRange(TypeRange),
+                                 *Result.SourceManager, getLangOpts())
+                .str(),
+            ExtraReference.str()};
+  }();
+  StringRef Name = MatchedDecl->getName();
   SourceRange ReplaceRange = MatchedDecl->getSourceRange();
 
   // typedefs with multiple comma-separated definitions produce multiple
@@ -143,7 +187,8 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
     // This is the first (and possibly the only) TypedefDecl in a typedef. Save
     // Type and Name in case we find subsequent TypedefDecl's in this typedef.
     FirstTypedefType = Type;
-    FirstTypedefName = Name;
+    FirstTypedefName = Name.str();
+    MainTypeEndLoc = TL.getEndLoc();
   } else {
     // This is additional TypedefDecl in a comma-separated typedef declaration.
     // Start replacement *after* prior replacement and separate with semicolon.
@@ -153,10 +198,10 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
     // If this additional TypedefDecl's Type starts with the first TypedefDecl's
     // type, make this using statement refer back to the first type, e.g. make
     // "typedef int Foo, *Foo_p;" -> "using Foo = int;\nusing Foo_p = Foo*;"
-    if (Type.size() > FirstTypedefType.size() &&
-        Type.substr(0, FirstTypedefType.size()) == FirstTypedefType)
-      Type = FirstTypedefName + Type.substr(FirstTypedefType.size() + 1);
+    if (Type == FirstTypedefType && !QualifierStr.empty())
+      Type = FirstTypedefName;
   }
+
   if (!ReplaceRange.getEnd().isMacroID()) {
     const SourceLocation::IntTy Offset =
         MatchedDecl->getFunctionType() ? 0 : Name.size();
@@ -177,7 +222,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       return;
   }
 
-  std::string Replacement = Using + Name + " = " + Type;
+  std::string Replacement = (Using + Name + " = " + Type + QualifierStr).str();
   Diag << FixItHint::CreateReplacement(ReplaceRange, Replacement);
 }
 } // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
index 7054778d84a0c6..1e54bbf23c984f 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.h
@@ -26,6 +26,7 @@ class UseUsingCheck : public ClangTidyCheck {
 
   std::string FirstTypedefType;
   std::string FirstTypedefName;
+  SourceLocation MainTypeEndLoc;
 
 public:
   UseUsingCheck(StringRef Name, ClangTidyContext *Context);
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 876689c40fcdb2..fe98aa9b9fd4b8 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -228,6 +228,9 @@ Changes in existing checks
   member function calls too and to only expand macros starting with ``PRI``
   and ``__PRI`` from ``<inttypes.h>`` in the format string.
 
+- Improved :doc:`modernize-use-using
+  <clang-tidy/checks/modernize/use-using>` check by not expanding macros.
+
 - Improved :doc:`performance-avoid-endl
   <clang-tidy/checks/performance/avoid-endl>` check to use ``std::endl`` as
   placeholder when lexer cannot get source text.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp
index 925e5f9c1ca54e..7833078f171bf8 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp
@@ -80,7 +80,7 @@ typedef Test<my_class *> another;
 
 typedef int* PInt;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: using PInt = int *;
+// CHECK-FIXES: using PInt = int*;
 
 typedef int bla1, bla2, bla3;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -112,7 +112,7 @@ TYPEDEF Foo Bak;
 typedef FOO Bam;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
 // CHECK-FIXES: #define FOO Foo
-// CHECK-FIXES: using Bam = Foo;
+// CHECK-FIXES: using Bam = FOO;
 
 typedef struct Foo Bap;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
@@ -247,7 +247,7 @@ typedef Q<T{0 < 0}.b> Q3_t;
 
 typedef TwoArgTemplate<TwoArgTemplate<int, Q<T{0 < 0}.b> >, S<(0 < 0), Q<b[0 < 0]> > > Nested_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: using Nested_t = TwoArgTemplate<TwoArgTemplate<int, Q<T{0 < 0}.b>>, S<(0 < 0), Q<b[0 < 0]>>>;
+// CHECK-FIXES: using Nested_t = TwoArgTemplate<TwoArgTemplate<int, Q<T{0 < 0}.b> >, S<(0 < 0), Q<b[0 < 0]> > >;
 
 template <typename a>
 class TemplateKeyword {
@@ -265,12 +265,12 @@ class Variadic {};
 
 typedef Variadic<Variadic<int, bool, Q<T{0 < 0}.b> >, S<(0 < 0), Variadic<Q<b[0 < 0]> > > > Variadic_t;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: using Variadic_t = Variadic<Variadic<int, bool, Q<T{0 < 0}.b>>, S<(0 < 0), Variadic<Q<b[0 < 0]>>>>
+// CHECK-FIXES: using Variadic_t = Variadic<Variadic<int, bool, Q<T{0 < 0}.b> >, S<(0 < 0), Variadic<Q<b[0 < 0]> > > >
 
 typedef Variadic<Variadic<int, bool, Q<T{0 < 0}.b> >, S<(0 < 0), Variadic<Q<b[0 < 0]> > > > Variadic_t, *Variadic_p;
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef'
 // CHECK-MESSAGES: :[[@LINE-2]]:103: warning: use 'using' instead of 'typedef'
-// CHECK-FIXES: using Variadic_t = Variadic<Variadic<int, bool, Q<T{0 < 0}.b>>, S<(0 < 0), Variadic<Q<b[0 < 0]>>>>;
+// CHECK-FIXES: using Variadic_t = Variadic<Variadic<int, bool, Q<T{0 < 0}.b> >, S<(0 < 0), Variadic<Q<b[0 < 0]> > > >;
 // CHECK-FIXES-NEXT: using Variadic_p = Variadic_t*;
 
 typedef struct { int a; } R_t, *R_p;
@@ -383,3 +383,29 @@ namespace ISSUE_72179
   // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use 'using' instead of 'typedef' [modernize-use-using]
   // CHECK-FIXES: const auto foo4 = [](int a){using d = int;};
 }
+
+
+typedef int* int_ptr, *int_ptr_ptr;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using int_ptr = int*;
+// CHECK-FIXES-NEXT: using int_ptr_ptr = int_ptr*;
+
+#ifndef SpecialMode
+#define SomeMacro(x) x
+#else
+#define SomeMacro(x) SpecialType
+#endif
+
+class SomeMacro(GH33760) { };
+
+typedef void(SomeMacro(GH33760)::* FunctionType)(float, int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using FunctionType = void(SomeMacro(GH33760)::* )(float, int);
+
+#define CDECL __attribute((cdecl))
+
+typedef void (CDECL *GH37846)(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using GH37846 = void (CDECL *)(int);
+

>From 14ff78ef0f4af62ba0ec978e7543a6dc753bc904 Mon Sep 17 00:00:00 2001
From: Julian Schmidt <git.julian.schmidt at gmail.com>
Date: Sun, 1 Dec 2024 02:37:23 +0100
Subject: [PATCH 2/6] add tests for additionally fixed issues

---
 .../checkers/modernize/use-using.cpp          | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp
index 7833078f171bf8..214a66f3dcc889 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-using.cpp
@@ -405,7 +405,35 @@ typedef void(SomeMacro(GH33760)::* FunctionType)(float, int);
 
 #define CDECL __attribute((cdecl))
 
+// GH37846 & GH41685
 typedef void (CDECL *GH37846)(int);
 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
 // CHECK-FIXES: using GH37846 = void (CDECL *)(int);
 
+typedef void (__attribute((cdecl)) *GH41685)(int);
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using GH41685 = void (__attribute((cdecl)) *)(int);
+
+namespace GH83568 {
+  typedef int(*name)(int arg1, int arg2);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using name = int(*)(int arg1, int arg2);
+}
+
+#ifdef FOO
+#define GH95716 float
+#else
+#define GH95716 double
+#endif
+
+typedef GH95716 foo;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using foo = GH95716;
+
+namespace GH97009 {
+  typedef double PointType[3];
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef' [modernize-use-using]
+  typedef bool (*Function)(PointType, PointType);
+// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use 'using' instead of 'typedef' [modernize-use-using]
+// CHECK-FIXES: using Function = bool (*)(PointType, PointType);
+}

>From 91d4465e65abaf889edcf7901ca1f6231d9d9cbc Mon Sep 17 00:00:00 2001
From: Julian Schmidt <git.julian.schmidt at gmail.com>
Date: Sun, 1 Dec 2024 02:37:42 +0100
Subject: [PATCH 3/6] address review comment regarding readability of getting
 the source text

---
 .../clang-tidy/modernize/UseUsingCheck.cpp    | 32 ++++++++++---------
 1 file changed, 17 insertions(+), 15 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index 74764d95d90520..c96ad5fa32bb13 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -131,25 +131,27 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
     // Function pointer case, get the left and right side of the identifier
     // without the identifier.
     if (TypeRange.fullyContains(MatchedDecl->getLocation())) {
-      return {(Lexer::getSourceText(
-                   CharSourceRange::getCharRange(TL.getBeginLoc(),
-                                                 MatchedDecl->getLocation()),
-                   *Result.SourceManager, getLangOpts()) +
-               Lexer::getSourceText(
-                   CharSourceRange::getCharRange(
-                       Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0,
-                                                  *Result.SourceManager,
-                                                  getLangOpts()),
-                       Lexer::getLocForEndOfToken(TL.getEndLoc(), 0,
-                                                  *Result.SourceManager,
-                                                  getLangOpts())),
-                   *Result.SourceManager, getLangOpts()))
-                  .str(),
-              ""};
+      const auto RangeLeftOfIdentifier = CharSourceRange::getCharRange(
+          TypeRange.getBegin(), MatchedDecl->getLocation());
+      const auto RangeRightOfIdentifier = CharSourceRange::getCharRange(
+          Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0,
+                                     *Result.SourceManager, getLangOpts()),
+          Lexer::getLocForEndOfToken(TypeRange.getEnd(), 0,
+                                     *Result.SourceManager, getLangOpts()));
+      const std::string VerbatimType =
+          (Lexer::getSourceText(RangeLeftOfIdentifier, *Result.SourceManager,
+                                getLangOpts()) +
+           Lexer::getSourceText(RangeRightOfIdentifier, *Result.SourceManager,
+                                getLangOpts()))
+              .str();
+      return {VerbatimType, ""};
     }
 
     StringRef ExtraReference = "";
     if (MainTypeEndLoc.isValid() && TypeRange.fullyContains(MainTypeEndLoc)) {
+      // Each type introduced in a typedef can specify being a reference or
+      // pointer type seperately, so we need to sigure out if the new using-decl
+      // needs to be to a reference or pointer as well.
       const SourceLocation Tok = utils::lexer::findPreviousAnyTokenKind(
           MatchedDecl->getLocation(), *Result.SourceManager, getLangOpts(),
           tok::TokenKind::star, tok::TokenKind::amp, tok::TokenKind::comma,

>From d722beb512e3f4c408c1d4c009bc76e056f3239d Mon Sep 17 00:00:00 2001
From: Julian Schmidt <git.julian.schmidt at gmail.com>
Date: Sun, 1 Dec 2024 02:38:07 +0100
Subject: [PATCH 4/6] remove already checked condition

---
 clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index c96ad5fa32bb13..7b62d29b2d8175 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -164,8 +164,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       if (ExtraReference != "*" && ExtraReference != "&")
         ExtraReference = "";
 
-      if (MainTypeEndLoc.isValid())
-        TypeRange.setEnd(MainTypeEndLoc);
+      TypeRange.setEnd(MainTypeEndLoc);
     }
     return {Lexer::getSourceText(CharSourceRange::getTokenRange(TypeRange),
                                  *Result.SourceManager, getLangOpts())

>From ded9e5e6a06528c0630c12a4aaac27bb55816abe Mon Sep 17 00:00:00 2001
From: Julian Schmidt <git.julian.schmidt at gmail.com>
Date: Sun, 1 Dec 2024 02:40:28 +0100
Subject: [PATCH 5/6] create SM local var

---
 .../clang-tidy/modernize/UseUsingCheck.cpp    | 36 +++++++++----------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index 7b62d29b2d8175..321aaf3666cbe7 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -10,6 +10,7 @@
 #include "../utils/LexerUtils.h"
 #include "clang/AST/DeclGroup.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
 #include "clang/Lex/Lexer.h"
 #include <string>
@@ -86,6 +87,8 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
   if (!ParentDecl)
     return;
 
+  const SourceManager &SM = *Result.SourceManager;
+
   // Match CXXRecordDecl only to store the range of the last non-implicit full
   // declaration, to later check whether it's within the typdef itself.
   const auto *MatchedTagDecl = Result.Nodes.getNodeAs<TagDecl>(TagDeclName);
@@ -124,8 +127,8 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
 
   const TypeLoc TL = MatchedDecl->getTypeSourceInfo()->getTypeLoc();
 
-  auto [Type, QualifierStr] = [MatchedDecl, &Result, this,
-                               &TL]() -> std::pair<std::string, std::string> {
+  auto [Type, QualifierStr] = [MatchedDecl, this, &TL,
+                               &SM]() -> std::pair<std::string, std::string> {
     SourceRange TypeRange = TL.getSourceRange();
 
     // Function pointer case, get the left and right side of the identifier
@@ -134,15 +137,12 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       const auto RangeLeftOfIdentifier = CharSourceRange::getCharRange(
           TypeRange.getBegin(), MatchedDecl->getLocation());
       const auto RangeRightOfIdentifier = CharSourceRange::getCharRange(
-          Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0,
-                                     *Result.SourceManager, getLangOpts()),
-          Lexer::getLocForEndOfToken(TypeRange.getEnd(), 0,
-                                     *Result.SourceManager, getLangOpts()));
+          Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0, SM,
+                                     getLangOpts()),
+          Lexer::getLocForEndOfToken(TypeRange.getEnd(), 0, SM, getLangOpts()));
       const std::string VerbatimType =
-          (Lexer::getSourceText(RangeLeftOfIdentifier, *Result.SourceManager,
-                                getLangOpts()) +
-           Lexer::getSourceText(RangeRightOfIdentifier, *Result.SourceManager,
-                                getLangOpts()))
+          (Lexer::getSourceText(RangeLeftOfIdentifier, SM, getLangOpts()) +
+           Lexer::getSourceText(RangeRightOfIdentifier, SM, getLangOpts()))
               .str();
       return {VerbatimType, ""};
     }
@@ -153,21 +153,21 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       // pointer type seperately, so we need to sigure out if the new using-decl
       // needs to be to a reference or pointer as well.
       const SourceLocation Tok = utils::lexer::findPreviousAnyTokenKind(
-          MatchedDecl->getLocation(), *Result.SourceManager, getLangOpts(),
-          tok::TokenKind::star, tok::TokenKind::amp, tok::TokenKind::comma,
+          MatchedDecl->getLocation(), SM, getLangOpts(), tok::TokenKind::star,
+          tok::TokenKind::amp, tok::TokenKind::comma,
           tok::TokenKind::kw_typedef);
 
       ExtraReference = Lexer::getSourceText(
-          CharSourceRange::getCharRange(Tok, Tok.getLocWithOffset(1)),
-          *Result.SourceManager, getLangOpts());
+          CharSourceRange::getCharRange(Tok, Tok.getLocWithOffset(1)), SM,
+          getLangOpts());
 
       if (ExtraReference != "*" && ExtraReference != "&")
         ExtraReference = "";
 
       TypeRange.setEnd(MainTypeEndLoc);
     }
-    return {Lexer::getSourceText(CharSourceRange::getTokenRange(TypeRange),
-                                 *Result.SourceManager, getLangOpts())
+    return {Lexer::getSourceText(CharSourceRange::getTokenRange(TypeRange), SM,
+                                 getLangOpts())
                 .str(),
             ExtraReference.str()};
   }();
@@ -217,8 +217,8 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       LastTagDeclRange->second.isValid() &&
       ReplaceRange.fullyContains(LastTagDeclRange->second)) {
     Type = std::string(Lexer::getSourceText(
-        CharSourceRange::getTokenRange(LastTagDeclRange->second),
-        *Result.SourceManager, getLangOpts()));
+        CharSourceRange::getTokenRange(LastTagDeclRange->second), SM,
+        getLangOpts()));
     if (Type.empty())
       return;
   }

>From cf95ee22c60296628aba6c5e56de12cb30143b4a Mon Sep 17 00:00:00 2001
From: Julian Schmidt <git.julian.schmidt at gmail.com>
Date: Sun, 1 Dec 2024 02:41:07 +0100
Subject: [PATCH 6/6] create LO var for lang opts

---
 .../clang-tidy/modernize/UseUsingCheck.cpp    | 31 +++++++++----------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
index 321aaf3666cbe7..30fcba367db67e 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
@@ -9,6 +9,7 @@
 #include "UseUsingCheck.h"
 #include "../utils/LexerUtils.h"
 #include "clang/AST/DeclGroup.h"
+#include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
@@ -88,6 +89,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
     return;
 
   const SourceManager &SM = *Result.SourceManager;
+  const LangOptions &LO = getLangOpts();
 
   // Match CXXRecordDecl only to store the range of the last non-implicit full
   // declaration, to later check whether it's within the typdef itself.
@@ -127,8 +129,8 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
 
   const TypeLoc TL = MatchedDecl->getTypeSourceInfo()->getTypeLoc();
 
-  auto [Type, QualifierStr] = [MatchedDecl, this, &TL,
-                               &SM]() -> std::pair<std::string, std::string> {
+  auto [Type, QualifierStr] = [MatchedDecl, this, &TL, &SM,
+                               &LO]() -> std::pair<std::string, std::string> {
     SourceRange TypeRange = TL.getSourceRange();
 
     // Function pointer case, get the left and right side of the identifier
@@ -137,12 +139,11 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       const auto RangeLeftOfIdentifier = CharSourceRange::getCharRange(
           TypeRange.getBegin(), MatchedDecl->getLocation());
       const auto RangeRightOfIdentifier = CharSourceRange::getCharRange(
-          Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0, SM,
-                                     getLangOpts()),
-          Lexer::getLocForEndOfToken(TypeRange.getEnd(), 0, SM, getLangOpts()));
+          Lexer::getLocForEndOfToken(MatchedDecl->getLocation(), 0, SM, LO),
+          Lexer::getLocForEndOfToken(TypeRange.getEnd(), 0, SM, LO));
       const std::string VerbatimType =
-          (Lexer::getSourceText(RangeLeftOfIdentifier, SM, getLangOpts()) +
-           Lexer::getSourceText(RangeRightOfIdentifier, SM, getLangOpts()))
+          (Lexer::getSourceText(RangeLeftOfIdentifier, SM, LO) +
+           Lexer::getSourceText(RangeRightOfIdentifier, SM, LO))
               .str();
       return {VerbatimType, ""};
     }
@@ -153,23 +154,22 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       // pointer type seperately, so we need to sigure out if the new using-decl
       // needs to be to a reference or pointer as well.
       const SourceLocation Tok = utils::lexer::findPreviousAnyTokenKind(
-          MatchedDecl->getLocation(), SM, getLangOpts(), tok::TokenKind::star,
+          MatchedDecl->getLocation(), SM, LO, tok::TokenKind::star,
           tok::TokenKind::amp, tok::TokenKind::comma,
           tok::TokenKind::kw_typedef);
 
       ExtraReference = Lexer::getSourceText(
-          CharSourceRange::getCharRange(Tok, Tok.getLocWithOffset(1)), SM,
-          getLangOpts());
+          CharSourceRange::getCharRange(Tok, Tok.getLocWithOffset(1)), SM, LO);
 
       if (ExtraReference != "*" && ExtraReference != "&")
         ExtraReference = "";
 
       TypeRange.setEnd(MainTypeEndLoc);
     }
-    return {Lexer::getSourceText(CharSourceRange::getTokenRange(TypeRange), SM,
-                                 getLangOpts())
-                .str(),
-            ExtraReference.str()};
+    return {
+        Lexer::getSourceText(CharSourceRange::getTokenRange(TypeRange), SM, LO)
+            .str(),
+        ExtraReference.str()};
   }();
   StringRef Name = MatchedDecl->getName();
   SourceRange ReplaceRange = MatchedDecl->getSourceRange();
@@ -217,8 +217,7 @@ void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
       LastTagDeclRange->second.isValid() &&
       ReplaceRange.fullyContains(LastTagDeclRange->second)) {
     Type = std::string(Lexer::getSourceText(
-        CharSourceRange::getTokenRange(LastTagDeclRange->second), SM,
-        getLangOpts()));
+        CharSourceRange::getTokenRange(LastTagDeclRange->second), SM, LO));
     if (Type.empty())
       return;
   }



More information about the cfe-commits mailing list