@@ -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+
8586AST_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-
241203void 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 (
0 commit comments