10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/ASTMatchers/ASTMatchers.h"
13#include "clang/Lex/Lexer.h"
20 const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>(
"call");
21 const SourceManager &SM = *Result.SourceManager;
22 return Lexer::getSourceText(CharSourceRange::getTokenRange(
23 MatchedCall->getCallee()->getSourceRange()),
24 SM, Result.Context->getLangOpts());
28 const auto PosixCall =
29 callExpr(callee(functionDecl(
30 anyOf(matchesName(
"^::posix_"), matchesName(
"^::pthread_")),
31 unless(hasName(
"::posix_openpt")))))
33 const auto ZeroIntegerLiteral = integerLiteral(equals(0));
34 const auto NegIntegerLiteral =
35 unaryOperator(hasOperatorName(
"-"), hasUnaryOperand(integerLiteral()));
39 anyOf(allOf(hasOperatorName(
"<"), hasLHS(PosixCall),
40 hasRHS(ZeroIntegerLiteral)),
41 allOf(hasOperatorName(
">"), hasLHS(ZeroIntegerLiteral),
47 anyOf(allOf(hasOperatorName(
">="), hasLHS(PosixCall),
48 hasRHS(ZeroIntegerLiteral)),
49 allOf(hasOperatorName(
"<="), hasLHS(ZeroIntegerLiteral),
53 Finder->addMatcher(binaryOperator(hasAnyOperatorName(
"==",
"!="),
54 hasOperands(PosixCall, NegIntegerLiteral))
58 binaryOperator(anyOf(allOf(hasAnyOperatorName(
"<=",
"<"),
59 hasLHS(PosixCall), hasRHS(NegIntegerLiteral)),
60 allOf(hasAnyOperatorName(
">",
">="),
61 hasLHS(NegIntegerLiteral), hasRHS(PosixCall))))
67 if (
const auto *LessThanZeroOp =
68 Result.Nodes.getNodeAs<BinaryOperator>(
"ltzop")) {
69 SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc();
71 LessThanZeroOp->getOpcode() == BinaryOperator::Opcode::BO_LT ?
">"
73 diag(OperatorLoc,
"the comparison always evaluates to false because %0 "
74 "always returns non-negative values")
76 << FixItHint::CreateReplacement(OperatorLoc, NewBinOp);
79 if (
const auto *AlwaysTrueOp =
80 Result.Nodes.getNodeAs<BinaryOperator>(
"atop")) {
81 diag(AlwaysTrueOp->getOperatorLoc(),
82 "the comparison always evaluates to true because %0 always returns "
83 "non-negative values")
87 const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"binop");
88 diag(BinOp->getOperatorLoc(),
"%0 only returns non-negative values")
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result)