https://github.com/vbvictor created 
https://github.com/llvm/llvm-project/pull/174809

None

>From 691f1fe7b5aaa9ec474969a39412525824ae43ab Mon Sep 17 00:00:00 2001
From: Victor Baranov <[email protected]>
Date: Thu, 8 Jan 2026 01:22:51 +0800
Subject: [PATCH] [clang-tidy][NFC] Convert Lexer utils to use
 std::optional<Token>

---
 .../bugprone/ArgumentCommentCheck.cpp         |  8 +++----
 .../bugprone/OptionalValueConversionCheck.cpp |  9 ++++----
 .../bugprone/SuspiciousSemicolonCheck.cpp     |  9 ++++----
 .../ProTypeMemberInitCheck.cpp                | 22 ++++++++++---------
 .../modernize/UseConstraintsCheck.cpp         |  4 ++--
 .../readability/DeleteNullPointerCheck.cpp    | 14 +++++++-----
 .../readability/IsolateDeclarationCheck.cpp   |  4 ++--
 .../readability/RedundantMemberInitCheck.cpp  | 10 ++++-----
 .../clang-tidy/utils/FixItHintUtils.cpp       | 17 +++++++-------
 .../clang-tidy/utils/LexerUtils.cpp           | 12 +++++-----
 .../clang-tidy/utils/LexerUtils.h             | 11 ++++++----
 11 files changed, 64 insertions(+), 56 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
index 16a0fb1b037bf..2e963cd995f74 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
@@ -127,16 +127,16 @@ static std::vector<std::pair<SourceLocation, StringRef>>
 getCommentsBeforeLoc(ASTContext *Ctx, SourceLocation Loc) {
   std::vector<std::pair<SourceLocation, StringRef>> Comments;
   while (Loc.isValid()) {
-    const clang::Token Tok = utils::lexer::getPreviousToken(
+    const std::optional<Token> Tok = utils::lexer::getPreviousToken(
         Loc, Ctx->getSourceManager(), Ctx->getLangOpts(),
         /*SkipComments=*/false);
-    if (Tok.isNot(tok::comment))
+    if (!Tok || Tok->isNot(tok::comment))
       break;
-    Loc = Tok.getLocation();
+    Loc = Tok->getLocation();
     Comments.emplace_back(
         Loc,
         Lexer::getSourceText(CharSourceRange::getCharRange(
-                                 Loc, Loc.getLocWithOffset(Tok.getLength())),
+                                 Loc, Loc.getLocWithOffset(Tok->getLength())),
                              Ctx->getSourceManager(), Ctx->getLangOpts()));
   }
   return Comments;
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
index 19b4fc1c044df..c532d873a5e4c 100644
--- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp
@@ -139,10 +139,11 @@ void OptionalValueConversionCheck::check(
   }
   if (const auto *CallExpr =
           Result.Nodes.getNodeAs<CXXMemberCallExpr>("member-call")) {
-    const SourceLocation Begin =
-        utils::lexer::getPreviousToken(CallExpr->getExprLoc(),
-                                       *Result.SourceManager, getLangOpts())
-            .getLocation();
+    const std::optional<Token> Tok = utils::lexer::getPreviousToken(
+        CallExpr->getExprLoc(), *Result.SourceManager, getLangOpts());
+    if (!Tok)
+      return;
+    const SourceLocation Begin = Tok->getLocation();
     auto Diag =
         diag(CallExpr->getExprLoc(),
              "remove call to %0 to silence this warning", DiagnosticIDs::Note);
diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
index 9d37fc1e8728e..bef4359ec2e43 100644
--- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp
@@ -37,16 +37,16 @@ void SuspiciousSemicolonCheck::check(const 
MatchFinder::MatchResult &Result) {
     return;
 
   ASTContext &Ctxt = *Result.Context;
-  auto Token = utils::lexer::getPreviousToken(LocStart, 
Ctxt.getSourceManager(),
-                                              Ctxt.getLangOpts());
-  auto &SM = *Result.SourceManager;
+  const auto &SM = *Result.SourceManager;
   const unsigned SemicolonLine = SM.getSpellingLineNumber(LocStart);
 
   const auto *Statement = Result.Nodes.getNodeAs<Stmt>("stmt");
   const bool IsIfStmt = isa<IfStmt>(Statement);
 
+  const std::optional<Token> PrevTok = utils::lexer::getPreviousToken(
+      LocStart, Ctxt.getSourceManager(), Ctxt.getLangOpts());
   if (!IsIfStmt &&
-      SM.getSpellingLineNumber(Token.getLocation()) != SemicolonLine)
+      SM.getSpellingLineNumber(PrevTok->getLocation()) != SemicolonLine)
     return;
 
   const SourceLocation LocEnd = Semicolon->getEndLoc();
@@ -55,6 +55,7 @@ void SuspiciousSemicolonCheck::check(const 
MatchFinder::MatchResult &Result) {
   Lexer Lexer(SM.getLocForStartOfFile(FID), Ctxt.getLangOpts(),
               Buffer.getBufferStart(), SM.getCharacterData(LocEnd) + 1,
               Buffer.getBufferEnd());
+  Token Token;
   if (Lexer.LexFromRawLexer(Token))
     return;
 
diff --git 
a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp 
b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
index 5306690e22eeb..ab068417b869e 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeMemberInitCheck.cpp
@@ -149,18 +149,20 @@ struct InitializerInsertion {
            "insertion represents a new initializer list.");
     SourceLocation Location;
     switch (Placement) {
-    case InitializerPlacement::New:
-      Location = utils::lexer::getPreviousToken(
-                     Constructor.getBody()->getBeginLoc(),
-                     Context.getSourceManager(), Context.getLangOpts())
-                     .getLocation();
+    case InitializerPlacement::New: {
+      const std::optional<Token> Tok = utils::lexer::getPreviousToken(
+          Constructor.getBody()->getBeginLoc(), Context.getSourceManager(),
+          Context.getLangOpts());
+      Location = Tok.has_value() ? Tok->getLocation() : SourceLocation{};
       break;
-    case InitializerPlacement::Before:
-      Location = utils::lexer::getPreviousToken(
-                     Where->getSourceRange().getBegin(),
-                     Context.getSourceManager(), Context.getLangOpts())
-                     .getLocation();
+    }
+    case InitializerPlacement::Before: {
+      const std::optional<Token> Tok = utils::lexer::getPreviousToken(
+          Where->getSourceRange().getBegin(), Context.getSourceManager(),
+          Context.getLangOpts());
+      Location = Tok.has_value() ? Tok->getLocation() : SourceLocation{};
       break;
+    }
     case InitializerPlacement::After:
       Location = Where->getRParenLoc();
       break;
diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
index 3e9c0e85fe96c..518be5c5d9812 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp
@@ -318,11 +318,11 @@ static std::optional<std::string> getConditionText(const 
Expr *ConditionExpr,
     return std::nullopt;
 
   const bool SkipComments = false;
-  Token PrevToken;
+  std::optional<Token> PrevToken;
   std::tie(PrevToken, PrevTokenLoc) = utils::lexer::getPreviousTokenAndStart(
       PrevTokenLoc, SM, LangOpts, SkipComments);
   const bool EndsWithDoubleSlash =
-      PrevToken.is(tok::comment) &&
+      PrevToken && PrevToken->is(tok::comment) &&
       Lexer::getSourceText(CharSourceRange::getCharRange(
                                PrevTokenLoc, PrevTokenLoc.getLocWithOffset(2)),
                            SM, LangOpts) == "//";
diff --git 
a/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp
index e96bfe7fe7271..b7e0d9c236973 100644
--- a/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/DeleteNullPointerCheck.cpp
@@ -52,16 +52,18 @@ void DeleteNullPointerCheck::check(const 
MatchFinder::MatchResult &Result) {
   auto Diag = diag(
       IfWithDelete->getBeginLoc(),
       "'if' statement is unnecessary; deleting null pointer has no effect");
-  if (IfWithDelete->getElse())
+  if (IfWithDelete->hasElseStorage())
     return;
   // FIXME: generate fixit for this case.
 
+  const std::optional<Token> PrevTok = utils::lexer::getPreviousToken(
+      IfWithDelete->getThen()->getBeginLoc(), *Result.SourceManager,
+      Result.Context->getLangOpts());
+  if (!PrevTok)
+    return;
+
   Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange(
-      IfWithDelete->getBeginLoc(),
-      utils::lexer::getPreviousToken(IfWithDelete->getThen()->getBeginLoc(),
-                                     *Result.SourceManager,
-                                     Result.Context->getLangOpts())
-          .getLocation()));
+      IfWithDelete->getBeginLoc(), PrevTok->getLocation()));
 
   if (Compound) {
     Diag << FixItHint::CreateRemoval(
diff --git 
a/clang-tools-extra/clang-tidy/readability/IsolateDeclarationCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/IsolateDeclarationCheck.cpp
index fa5a0b7cd3647..5e3f3f6777279 100644
--- a/clang-tools-extra/clang-tidy/readability/IsolateDeclarationCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/IsolateDeclarationCheck.cpp
@@ -157,8 +157,8 @@ declRanges(const DeclStmt *DS, const SourceManager &SM,
     if (Start.isInvalid() || Start.isMacroID())
       break;
 
-    const Token T = getPreviousToken(Start, SM, LangOpts);
-    if (T.is(tok::l_paren)) {
+    const std::optional<Token> T = getPreviousToken(Start, SM, LangOpts);
+    if (T && T->is(tok::l_paren)) {
       Start = findPreviousTokenStart(Start, SM, LangOpts);
       continue;
     }
diff --git 
a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
index 1bbb9c86fee14..f891c954b19ea 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
@@ -21,16 +21,16 @@ namespace clang::tidy::readability {
 static SourceRange
 getFullInitRangeInclWhitespaces(SourceRange Range, const SourceManager &SM,
                                 const LangOptions &LangOpts) {
-  const Token PrevToken =
+  const std::optional<Token> PrevToken =
       utils::lexer::getPreviousToken(Range.getBegin(), SM, LangOpts, false);
-  if (PrevToken.is(tok::unknown))
+  if (!PrevToken)
     return Range;
 
-  if (PrevToken.isNot(tok::equal))
-    return {PrevToken.getEndLoc(), Range.getEnd()};
+  if (PrevToken->isNot(tok::equal))
+    return {PrevToken->getEndLoc(), Range.getEnd()};
 
   return getFullInitRangeInclWhitespaces(
-      {PrevToken.getLocation(), Range.getEnd()}, SM, LangOpts);
+      {PrevToken->getLocation(), Range.getEnd()}, SM, LangOpts);
 }
 
 void RedundantMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) 
{
diff --git a/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp 
b/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
index 5fcf5ed30fb81..9eca12fe19bf1 100644
--- a/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
+++ b/clang-tools-extra/clang-tidy/utils/FixItHintUtils.cpp
@@ -19,15 +19,15 @@ namespace clang::tidy::utils::fixit {
 
 FixItHint changeVarDeclToReference(const VarDecl &Var, ASTContext &Context) {
   SourceLocation AmpLocation = Var.getLocation();
-  auto Token = utils::lexer::getPreviousToken(
+  const std::optional<Token> Token = utils::lexer::getPreviousToken(
       AmpLocation, Context.getSourceManager(), Context.getLangOpts());
 
   // For parameter packs the '&' must go before the '...' token
-  if (Token.is(tok::ellipsis))
-    return FixItHint::CreateInsertion(Token.getLocation(), "&");
+  if (Token && Token->is(tok::ellipsis))
+    return FixItHint::CreateInsertion(Token->getLocation(), "&");
 
-  if (!Token.is(tok::unknown))
-    AmpLocation = Lexer::getLocForEndOfToken(Token.getLocation(), 0,
+  if (Token)
+    AmpLocation = Lexer::getLocForEndOfToken(Token->getLocation(), 0,
                                              Context.getSourceManager(),
                                              Context.getLangOpts());
   return FixItHint::CreateInsertion(AmpLocation, "&");
@@ -53,10 +53,9 @@ skipLParensBackwards(SourceLocation Start, const ASTContext 
&Context) {
     return std::nullopt;
 
   auto PreviousTokenLParen = [&Start, &Context]() {
-    Token T;
-    T = lexer::getPreviousToken(Start, Context.getSourceManager(),
-                                Context.getLangOpts());
-    return T.is(tok::l_paren);
+    const std::optional<Token> T = lexer::getPreviousToken(
+        Start, Context.getSourceManager(), Context.getLangOpts());
+    return T && T->is(tok::l_paren);
   };
 
   while (Start.isValid() && PreviousTokenLParen())
diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp 
b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
index e759c0b8b9fdc..b77d985b76d77 100644
--- a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
+++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp
@@ -13,7 +13,7 @@
 
 namespace clang::tidy::utils::lexer {
 
-std::pair<Token, SourceLocation>
+std::pair<std::optional<Token>, SourceLocation>
 getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
                          const LangOptions &LangOpts, bool SkipComments) {
   const std::optional<Token> Tok =
@@ -22,13 +22,13 @@ getPreviousTokenAndStart(SourceLocation Location, const 
SourceManager &SM,
   if (Tok.has_value())
     return {*Tok, Lexer::GetBeginningOfToken(Tok->getLocation(), SM, 
LangOpts)};
 
-  Token Token;
-  Token.setKind(tok::unknown);
-  return {Token, SourceLocation()};
+  return {std::nullopt, SourceLocation()};
 }
 
-Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
-                       const LangOptions &LangOpts, bool SkipComments) {
+std::optional<Token> getPreviousToken(SourceLocation Location,
+                                      const SourceManager &SM,
+                                      const LangOptions &LangOpts,
+                                      bool SkipComments) {
   auto [Token, Start] =
       getPreviousTokenAndStart(Location, SM, LangOpts, SkipComments);
   return Token;
diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.h 
b/clang-tools-extra/clang-tidy/utils/LexerUtils.h
index e698ef68441ce..94d26ec8f07d7 100644
--- a/clang-tools-extra/clang-tidy/utils/LexerUtils.h
+++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.h
@@ -21,10 +21,13 @@ class Stmt;
 
 namespace tidy::utils::lexer {
 
-/// Returns previous token or ``tok::unknown`` if not found.
-Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
-                       const LangOptions &LangOpts, bool SkipComments = true);
-std::pair<Token, SourceLocation>
+/// Returns previous token.
+std::optional<Token> getPreviousToken(SourceLocation Location,
+                                      const SourceManager &SM,
+                                      const LangOptions &LangOpts,
+                                      bool SkipComments = true);
+
+std::pair<std::optional<Token>, SourceLocation>
 getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
                          const LangOptions &LangOpts, bool SkipComments = 
true);
 

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

Reply via email to