Skip to content

Commit f2dc9b2

Browse files
committed
feedback
1 parent 23b4bcd commit f2dc9b2

File tree

4 files changed

+88
-131
lines changed

4 files changed

+88
-131
lines changed

clang-tools-extra/clang-tidy/modernize/UseStartsEndsWithCheck.cpp

Lines changed: 26 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,6 @@ struct NotLengthExprForStringNode {
3030
IntegerLiteralSizeNode->getValue().getZExtValue();
3131
}
3232

33-
if (const auto *DeclRefNode = Node.get<DeclRefExpr>()) {
34-
if (const auto *VD = dyn_cast<VarDecl>(DeclRefNode->getDecl())) {
35-
if (VD->hasInit() && VD->getType().isConstQualified()) {
36-
if (const auto *Init = dyn_cast<IntegerLiteral>(VD->getInit())) {
37-
return StringLiteralNode->getLength() !=
38-
Init->getValue().getZExtValue();
39-
}
40-
}
41-
}
42-
}
43-
4433
if (const auto *StrlenNode = Node.get<CallExpr>()) {
4534
if (StrlenNode->getDirectCallee()->getName() != "strlen" ||
4635
StrlenNode->getNumArgs() != 1) {
@@ -82,6 +71,18 @@ struct NotLengthExprForStringNode {
8271
ASTContext *Context;
8372
};
8473

74+
static bool isNegativeComparison(const Expr *ComparisonExpr) {
75+
// Handle direct != operator
76+
if (const auto *BO = llvm::dyn_cast<BinaryOperator>(ComparisonExpr)) {
77+
return BO->getOpcode() == BO_NE;
78+
}
79+
80+
if (const auto *Op = llvm::dyn_cast<CXXOperatorCallExpr>(ComparisonExpr)) {
81+
return Op->getOperator() == OO_ExclaimEqual;
82+
}
83+
return false;
84+
}
85+
8586
AST_MATCHER_P(Expr, lengthExprForStringNode, std::string, ID) {
8687
return Builder->removeBindings(NotLengthExprForStringNode(
8788
ID, DynTypedNode::create(Node), &(Finder->getASTContext())));
@@ -186,58 +187,19 @@ void UseStartsEndsWithCheck::registerMatchers(MatchFinder *Finder) {
186187
Finder->addMatcher(
187188
cxxOperatorCallExpr(
188189
hasAnyOperatorName("==", "!="),
189-
anyOf(
190-
hasOperands(
191-
cxxMemberCallExpr(
192-
argumentCountIs(2), hasArgument(0, ZeroLiteral),
193-
hasArgument(1, lengthExprForStringNode("needle")),
194-
callee(
195-
cxxMethodDecl(hasName("substr"),
196-
ofClass(OnClassWithStartsWithFunction))
197-
.bind("find_fun")))
198-
.bind("find_expr"),
199-
expr().bind("needle")),
200-
hasOperands(expr().bind("needle"),
201-
cxxMemberCallExpr(
202-
argumentCountIs(2), hasArgument(0, ZeroLiteral),
203-
hasArgument(1, lengthExprForStringNode("needle")),
204-
callee(cxxMethodDecl(
205-
hasName("substr"),
206-
ofClass(OnClassWithStartsWithFunction))
207-
.bind("find_fun")))
208-
.bind("find_expr"))))
190+
hasOperands(
191+
expr().bind("needle"),
192+
cxxMemberCallExpr(
193+
argumentCountIs(2), hasArgument(0, ZeroLiteral),
194+
hasArgument(1, lengthExprForStringNode("needle")),
195+
callee(cxxMethodDecl(hasName("substr"),
196+
ofClass(OnClassWithStartsWithFunction))
197+
.bind("find_fun")))
198+
.bind("find_expr")))
209199
.bind("expr"),
210200
this);
211201
}
212202

213-
bool UseStartsEndsWithCheck::isNegativeComparison(const Expr* ComparisonExpr) {
214-
// Handle direct != operator
215-
if (const auto *BO = llvm::dyn_cast<BinaryOperator>(ComparisonExpr)) {
216-
return BO->getOpcode() == BO_NE;
217-
}
218-
219-
// Handle operator!= call
220-
if (const auto *Op = llvm::dyn_cast<CXXOperatorCallExpr>(ComparisonExpr)) {
221-
return Op->getOperator() == OO_ExclaimEqual;
222-
}
223-
224-
// Handle rewritten !(expr == expr)
225-
if (const auto *UO = llvm::dyn_cast<UnaryOperator>(ComparisonExpr)) {
226-
if (UO->getOpcode() == UO_LNot) {
227-
if (const auto *InnerBO =
228-
llvm::dyn_cast<BinaryOperator>(UO->getSubExpr()->IgnoreParens())) {
229-
return InnerBO->getOpcode() == BO_EQ;
230-
}
231-
if (const auto *InnerOp =
232-
llvm::dyn_cast<CXXOperatorCallExpr>(UO->getSubExpr()->IgnoreParens())) {
233-
return InnerOp->getOperator() == OO_EqualEqual;
234-
}
235-
}
236-
}
237-
238-
return false;
239-
}
240-
241203
void UseStartsEndsWithCheck::check(const MatchFinder::MatchResult &Result) {
242204
const auto *ComparisonExpr = Result.Nodes.getNodeAs<Expr>("expr");
243205
const auto *FindExpr = Result.Nodes.getNodeAs<CXXMemberCallExpr>("find_expr");
@@ -262,10 +224,11 @@ void UseStartsEndsWithCheck::check(const MatchFinder::MatchResult &Result) {
262224
CharSourceRange::getTokenRange(SearchExpr->getSourceRange()),
263225
*Result.SourceManager, Result.Context->getLangOpts());
264226

265-
auto Diag = diag(ComparisonExpr->getBeginLoc(),
266-
"use %0 instead of %1 %select{==|!=}2 ")
267-
<< ReplacementFunction->getName() << FindFun->getNameAsString()
268-
<< Neg;
227+
auto Diag = diag(FindExpr->getExprLoc(),
228+
FindFun->getName() == "substr"
229+
? "use %0 instead of %1() %select{==|!=}2"
230+
: "use %0 instead of %1() %select{==|!=}2 0")
231+
<< ReplacementFunction->getName() << FindFun->getName() << Neg;
269232

270233
// Remove everything before the function call.
271234
Diag << FixItHint::CreateRemoval(CharSourceRange::getCharRange(

clang-tools-extra/clang-tidy/modernize/UseStartsEndsWithCheck.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class UseStartsEndsWithCheck : public ClangTidyCheck {
2525
UseStartsEndsWithCheck(StringRef Name, ClangTidyContext *Context);
2626
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
2727
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
28-
bool isNegativeComparison(const Expr* ComparisonExpr);
2928
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
3029
return LangOpts.CPlusPlus;
3130
}

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,9 @@ Changes in existing checks
243243
``NULL``/``__null`` (but not ``0``) when used with a templated type.
244244

245245
- Improved :doc:`modernize-use-starts-ends-with
246-
<clang-tidy/checks/modernize/use-starts-ends-with>` check to handle two cases
247-
that can be replaced with ``ends_with`` and detect patterns using ``substr``
248-
that can be replaced with ``starts_with``. Now handles cases like
249-
``str.substr(0, n) == "literal"``, with support for length determination through
250-
integer literals, ``strlen()``, and ``size()``/``length()`` member functions.
246+
<clang-tidy/checks/modernize/use-starts-ends-with>` check to handle two new
247+
cases from ``rfind`` and ``compare`` to ``ends_with``, and one new case from
248+
``substr`` to ``starts_with``.
251249

252250
- Improved :doc:`modernize-use-std-format
253251
<clang-tidy/checks/modernize/use-std-format>` check to support replacing

0 commit comments

Comments
 (0)