[clang-tools-extra] [clang-tidy] Enhance modernize-use-starts-ends-with to handle substr patterns (PR #116033)
Nicolas van Kempen via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 15 13:08:45 PST 2024
================
@@ -189,7 +203,54 @@ void UseStartsEndsWithCheck::check(const MatchFinder::MatchResult &Result) {
if (ComparisonExpr->getBeginLoc().isMacroID())
return;
- const bool Neg = ComparisonExpr->getOpcode() == BO_NE;
+ bool Neg;
+ if (const auto *BO = llvm::dyn_cast<BinaryOperator>(ComparisonExpr)) {
+ Neg = BO->getOpcode() == BO_NE;
+ } else {
+ assert(llvm::isa<CXXOperatorCallExpr>(ComparisonExpr));
+ Neg = llvm::cast<CXXOperatorCallExpr>(ComparisonExpr)->getOperator() ==
+ OO_ExclaimEqual;
+ }
+
+ // Check if this is a substr case
+ bool IsSubstr = FindFun->getName() == "substr";
+
+ if (IsSubstr) {
+ const auto *SubstrCall = cast<CXXMemberCallExpr>(FindExpr);
+ const Expr *Object = SubstrCall->getImplicitObjectArgument();
+
+ std::string ObjectStr;
+ std::string SearchStr;
+ bool Invalid = false;
+
+ auto &SM = *Result.SourceManager;
+
+ CharSourceRange ObjectRange = CharSourceRange::getTokenRange(
+ Object->getBeginLoc(), Object->getEndLoc());
+ ObjectStr = Lexer::getSourceText(ObjectRange, SM, getLangOpts(), &Invalid).str();
+ if (Invalid)
+ return;
+
+ CharSourceRange SearchRange = CharSourceRange::getTokenRange(
+ SearchExpr->getBeginLoc(), SearchExpr->getEndLoc());
+ SearchStr = Lexer::getSourceText(SearchRange, SM, getLangOpts(), &Invalid).str();
+ if (Invalid)
+ return;
+
+ // Build the new expression: [!]Object.starts_with(SearchExpr)
+ std::string NewExpr =
+ (llvm::Twine(Neg ? "!" : "") + ObjectStr + "." +
+ ReplacementFunction->getName() + "(" + SearchStr + ")").str();
+ // Replace the entire comparison expression
+ auto Diag = diag(ComparisonExpr->getBeginLoc(),
+ "use %0 instead of substr() %select{==|!=}1")
+ << ReplacementFunction->getName() << Neg;
+ Diag << FixItHint::CreateReplacement(
+ CharSourceRange::getTokenRange(ComparisonExpr->getSourceRange()),
+ NewExpr);
+ return;
+ }
+
----------------
nicovank wrote:
Hmm, I now see why some changes here are necessary beyond the existing logic, this is for cases e.g. `v = str.subtr(0, v.size())`, because now we need to move `v` into the parenthesis.
If possible, I think this and the other existing cases should be consolidated into a single replacement strategy for every case. I'll take a quick stab at it later today, these range replacements/insertions/removals are finicky.
https://github.com/llvm/llvm-project/pull/116033
More information about the cfe-commits
mailing list