10 #include "../utils/Matchers.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
22 const char *BindingStr) {
23 const CallExpr *MatchedCall = cast<CallExpr>(
24 (Result.Nodes.getNodeAs<BinaryOperator>(BindingStr))->getLHS());
25 const SourceManager &SM = *Result.SourceManager;
26 return Lexer::getSourceText(CharSourceRange::getTokenRange(
27 MatchedCall->getCallee()->getSourceRange()),
28 SM, Result.Context->getLangOpts());
31 void PosixReturnCheck::registerMatchers(MatchFinder *Finder) {
35 hasLHS(callExpr(callee(functionDecl(
36 anyOf(matchesName(
"^::posix_"), matchesName(
"^::pthread_")),
37 unless(hasName(
"::posix_openpt")))))),
38 hasRHS(integerLiteral(equals(0))))
43 hasOperatorName(
">="),
44 hasLHS(callExpr(callee(functionDecl(
45 anyOf(matchesName(
"^::posix_"), matchesName(
"^::pthread_")),
46 unless(hasName(
"::posix_openpt")))))),
47 hasRHS(integerLiteral(equals(0))))
52 hasAnyOperatorName(
"==",
"!=",
"<=",
"<"),
53 hasLHS(callExpr(callee(functionDecl(
54 anyOf(matchesName(
"^::posix_"), matchesName(
"^::pthread_")),
55 unless(hasName(
"::posix_openpt")))))),
56 hasRHS(unaryOperator(hasOperatorName(
"-"),
57 hasUnaryOperand(integerLiteral()))))
62 void PosixReturnCheck::check(
const MatchFinder::MatchResult &Result) {
63 if (
const auto *LessThanZeroOp =
64 Result.Nodes.getNodeAs<BinaryOperator>(
"ltzop")) {
65 SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc();
66 diag(OperatorLoc,
"the comparison always evaluates to false because %0 "
67 "always returns non-negative values")
69 << FixItHint::CreateReplacement(OperatorLoc, Twine(
">").str());
72 if (
const auto *AlwaysTrueOp =
73 Result.Nodes.getNodeAs<BinaryOperator>(
"atop")) {
74 diag(AlwaysTrueOp->getOperatorLoc(),
75 "the comparison always evaluates to true because %0 always returns "
76 "non-negative values")
80 const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"binop");
81 diag(BinOp->getOperatorLoc(),
"%0 only returns non-negative values")