7
7
// ===----------------------------------------------------------------------===//
8
8
9
9
#include " PosixReturnCheck.h"
10
- #include " ../utils/Matchers.h"
11
10
#include " clang/AST/ASTContext.h"
12
11
#include " clang/ASTMatchers/ASTMatchFinder.h"
12
+ #include " clang/ASTMatchers/ASTMatchers.h"
13
13
#include " clang/Lex/Lexer.h"
14
14
15
15
using namespace clang ::ast_matchers;
16
16
17
17
namespace clang ::tidy::bugprone {
18
18
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" );
23
21
const SourceManager &SM = *Result.SourceManager ;
24
22
return Lexer::getSourceText (CharSourceRange::getTokenRange (
25
23
MatchedCall->getCallee ()->getSourceRange ()),
26
24
SM, Result.Context ->getLangOpts ());
27
25
}
28
26
29
27
void 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
+
30
37
Finder->addMatcher (
31
38
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))))
37
43
.bind (" ltzop" ),
38
44
this );
39
45
Finder->addMatcher (
40
46
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))))
46
51
.bind (" atop" ),
47
52
this );
53
+ Finder->addMatcher (binaryOperator (hasAnyOperatorName (" ==" , " !=" ),
54
+ hasOperands (PosixCall, NegIntegerLiteral))
55
+ .bind (" binop" ),
56
+ this );
48
57
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))))
56
62
.bind (" binop" ),
57
63
this );
58
64
}
@@ -61,23 +67,26 @@ void PosixReturnCheck::check(const MatchFinder::MatchResult &Result) {
61
67
if (const auto *LessThanZeroOp =
62
68
Result.Nodes .getNodeAs <BinaryOperator>(" ltzop" )) {
63
69
SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc ();
70
+ StringRef NewBinOp =
71
+ LessThanZeroOp->getOpcode () == BinaryOperator::Opcode::BO_LT ? " >"
72
+ : " <" ;
64
73
diag (OperatorLoc, " the comparison always evaluates to false because %0 "
65
74
" always returns non-negative values" )
66
- << getFunctionSpelling (Result, " ltzop " )
67
- << FixItHint::CreateReplacement (OperatorLoc, Twine ( " > " ). str () );
75
+ << getFunctionSpelling (Result)
76
+ << FixItHint::CreateReplacement (OperatorLoc, NewBinOp );
68
77
return ;
69
78
}
70
79
if (const auto *AlwaysTrueOp =
71
80
Result.Nodes .getNodeAs <BinaryOperator>(" atop" )) {
72
81
diag (AlwaysTrueOp->getOperatorLoc (),
73
82
" the comparison always evaluates to true because %0 always returns "
74
83
" non-negative values" )
75
- << getFunctionSpelling (Result, " atop " );
84
+ << getFunctionSpelling (Result);
76
85
return ;
77
86
}
78
87
const auto *BinOp = Result.Nodes .getNodeAs <BinaryOperator>(" binop" );
79
88
diag (BinOp->getOperatorLoc (), " %0 only returns non-negative values" )
80
- << getFunctionSpelling (Result, " binop " );
89
+ << getFunctionSpelling (Result);
81
90
}
82
91
83
92
} // namespace clang::tidy::bugprone
0 commit comments