77// ===----------------------------------------------------------------------===//
88
99#include " PosixReturnCheck.h"
10- #include " ../utils/Matchers.h"
1110#include " clang/AST/ASTContext.h"
1211#include " clang/ASTMatchers/ASTMatchFinder.h"
12+ #include " clang/ASTMatchers/ASTMatchers.h"
1313#include " clang/Lex/Lexer.h"
1414
1515using namespace clang ::ast_matchers;
1616
1717namespace clang ::tidy::bugprone {
1818
19- static StringRef getFunctionSpelling (const MatchFinder::MatchResult &Result,
20- const char *BindingStr) {
21- const CallExpr *MatchedCall = cast<CallExpr>(
22- (Result.Nodes .getNodeAs <BinaryOperator>(BindingStr))->getLHS ());
19+ static StringRef getFunctionSpelling (const MatchFinder::MatchResult &Result) {
20+ const auto *MatchedCall = Result.Nodes .getNodeAs <CallExpr>(" call" );
2321 const SourceManager &SM = *Result.SourceManager ;
2422 return Lexer::getSourceText (CharSourceRange::getTokenRange (
2523 MatchedCall->getCallee ()->getSourceRange ()),
2624 SM, Result.Context ->getLangOpts ());
2725}
2826
2927void PosixReturnCheck::registerMatchers (MatchFinder *Finder) {
28+ const auto PosixCall =
29+ callExpr (callee (functionDecl (
30+ anyOf (matchesName (" ^::posix_" ), matchesName (" ^::pthread_" )),
31+ unless (hasName (" ::posix_openpt" )))))
32+ .bind (" call" );
33+ const auto ZeroIntegerLiteral = integerLiteral (equals (0 ));
34+ const auto NegIntegerLiteral =
35+ unaryOperator (hasOperatorName (" -" ), hasUnaryOperand (integerLiteral ()));
36+
3037 Finder->addMatcher (
3138 binaryOperator (
32- hasOperatorName (" <" ),
33- hasLHS (callExpr (callee (functionDecl (
34- anyOf (matchesName (" ^::posix_" ), matchesName (" ^::pthread_" )),
35- unless (hasName (" ::posix_openpt" )))))),
36- hasRHS (integerLiteral (equals (0 ))))
39+ anyOf (allOf (hasOperatorName (" <" ), hasLHS (PosixCall),
40+ hasRHS (ZeroIntegerLiteral)),
41+ allOf (hasOperatorName (" >" ), hasLHS (ZeroIntegerLiteral),
42+ hasRHS (PosixCall))))
3743 .bind (" ltzop" ),
3844 this );
3945 Finder->addMatcher (
4046 binaryOperator (
41- hasOperatorName (" >=" ),
42- hasLHS (callExpr (callee (functionDecl (
43- anyOf (matchesName (" ^::posix_" ), matchesName (" ^::pthread_" )),
44- unless (hasName (" ::posix_openpt" )))))),
45- hasRHS (integerLiteral (equals (0 ))))
47+ anyOf (allOf (hasOperatorName (" >=" ), hasLHS (PosixCall),
48+ hasRHS (ZeroIntegerLiteral)),
49+ allOf (hasOperatorName (" <=" ), hasLHS (ZeroIntegerLiteral),
50+ hasRHS (PosixCall))))
4651 .bind (" atop" ),
4752 this );
53+ Finder->addMatcher (binaryOperator (hasAnyOperatorName (" ==" , " !=" ),
54+ hasOperands (PosixCall, NegIntegerLiteral))
55+ .bind (" binop" ),
56+ this );
4857 Finder->addMatcher (
49- binaryOperator (
50- hasAnyOperatorName (" ==" , " !=" , " <=" , " <" ),
51- hasLHS (callExpr (callee (functionDecl (
52- anyOf (matchesName (" ^::posix_" ), matchesName (" ^::pthread_" )),
53- unless (hasName (" ::posix_openpt" )))))),
54- hasRHS (unaryOperator (hasOperatorName (" -" ),
55- hasUnaryOperand (integerLiteral ()))))
58+ binaryOperator (anyOf (allOf (hasAnyOperatorName (" <=" , " <" ),
59+ hasLHS (PosixCall), hasRHS (NegIntegerLiteral)),
60+ allOf (hasAnyOperatorName (" >" , " >=" ),
61+ hasLHS (NegIntegerLiteral), hasRHS (PosixCall))))
5662 .bind (" binop" ),
5763 this );
5864}
@@ -61,23 +67,26 @@ void PosixReturnCheck::check(const MatchFinder::MatchResult &Result) {
6167 if (const auto *LessThanZeroOp =
6268 Result.Nodes .getNodeAs <BinaryOperator>(" ltzop" )) {
6369 SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc ();
70+ StringRef NewBinOp =
71+ LessThanZeroOp->getOpcode () == BinaryOperator::Opcode::BO_LT ? " >"
72+ : " <" ;
6473 diag (OperatorLoc, " the comparison always evaluates to false because %0 "
6574 " always returns non-negative values" )
66- << getFunctionSpelling (Result, " ltzop " )
67- << FixItHint::CreateReplacement (OperatorLoc, Twine ( " > " ). str () );
75+ << getFunctionSpelling (Result)
76+ << FixItHint::CreateReplacement (OperatorLoc, NewBinOp );
6877 return ;
6978 }
7079 if (const auto *AlwaysTrueOp =
7180 Result.Nodes .getNodeAs <BinaryOperator>(" atop" )) {
7281 diag (AlwaysTrueOp->getOperatorLoc (),
7382 " the comparison always evaluates to true because %0 always returns "
7483 " non-negative values" )
75- << getFunctionSpelling (Result, " atop " );
84+ << getFunctionSpelling (Result);
7685 return ;
7786 }
7887 const auto *BinOp = Result.Nodes .getNodeAs <BinaryOperator>(" binop" );
7988 diag (BinOp->getOperatorLoc (), " %0 only returns non-negative values" )
80- << getFunctionSpelling (Result, " binop " );
89+ << getFunctionSpelling (Result);
8190}
8291
8392} // namespace clang::tidy::bugprone
0 commit comments