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
