Skip to content

Commit

Permalink
[clang-tidy][bugprone-posix-return] support integer literals as LHS (l…
Browse files Browse the repository at this point in the history
…lvm#109302)

Refactor matches to give more generic checker.

---------

Co-authored-by: EugeneZelenko <eugene.zelenko@gmail.com>
  • Loading branch information
HerrCai0907 and EugeneZelenko authored Sep 27, 2024
1 parent 3b96294 commit d9853a8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 28 deletions.
61 changes: 35 additions & 26 deletions clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,52 +7,58 @@
//===----------------------------------------------------------------------===//

#include "PosixReturnCheck.h"
#include "../utils/Matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;

namespace clang::tidy::bugprone {

static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result,
const char *BindingStr) {
const CallExpr *MatchedCall = cast<CallExpr>(
(Result.Nodes.getNodeAs<BinaryOperator>(BindingStr))->getLHS());
static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result) {
const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>("call");
const SourceManager &SM = *Result.SourceManager;
return Lexer::getSourceText(CharSourceRange::getTokenRange(
MatchedCall->getCallee()->getSourceRange()),
SM, Result.Context->getLangOpts());
}

void PosixReturnCheck::registerMatchers(MatchFinder *Finder) {
const auto PosixCall =
callExpr(callee(functionDecl(
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))
.bind("call");
const auto ZeroIntegerLiteral = integerLiteral(equals(0));
const auto NegIntegerLiteral =
unaryOperator(hasOperatorName("-"), hasUnaryOperand(integerLiteral()));

Finder->addMatcher(
binaryOperator(
hasOperatorName("<"),
hasLHS(callExpr(callee(functionDecl(
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))),
hasRHS(integerLiteral(equals(0))))
anyOf(allOf(hasOperatorName("<"), hasLHS(PosixCall),
hasRHS(ZeroIntegerLiteral)),
allOf(hasOperatorName(">"), hasLHS(ZeroIntegerLiteral),
hasRHS(PosixCall))))
.bind("ltzop"),
this);
Finder->addMatcher(
binaryOperator(
hasOperatorName(">="),
hasLHS(callExpr(callee(functionDecl(
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))),
hasRHS(integerLiteral(equals(0))))
anyOf(allOf(hasOperatorName(">="), hasLHS(PosixCall),
hasRHS(ZeroIntegerLiteral)),
allOf(hasOperatorName("<="), hasLHS(ZeroIntegerLiteral),
hasRHS(PosixCall))))
.bind("atop"),
this);
Finder->addMatcher(binaryOperator(hasAnyOperatorName("==", "!="),
hasOperands(PosixCall, NegIntegerLiteral))
.bind("binop"),
this);
Finder->addMatcher(
binaryOperator(
hasAnyOperatorName("==", "!=", "<=", "<"),
hasLHS(callExpr(callee(functionDecl(
anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
unless(hasName("::posix_openpt")))))),
hasRHS(unaryOperator(hasOperatorName("-"),
hasUnaryOperand(integerLiteral()))))
binaryOperator(anyOf(allOf(hasAnyOperatorName("<=", "<"),
hasLHS(PosixCall), hasRHS(NegIntegerLiteral)),
allOf(hasAnyOperatorName(">", ">="),
hasLHS(NegIntegerLiteral), hasRHS(PosixCall))))
.bind("binop"),
this);
}
Expand All @@ -61,23 +67,26 @@ void PosixReturnCheck::check(const MatchFinder::MatchResult &Result) {
if (const auto *LessThanZeroOp =
Result.Nodes.getNodeAs<BinaryOperator>("ltzop")) {
SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc();
StringRef NewBinOp =
LessThanZeroOp->getOpcode() == BinaryOperator::Opcode::BO_LT ? ">"
: "<";
diag(OperatorLoc, "the comparison always evaluates to false because %0 "
"always returns non-negative values")
<< getFunctionSpelling(Result, "ltzop")
<< FixItHint::CreateReplacement(OperatorLoc, Twine(">").str());
<< getFunctionSpelling(Result)
<< FixItHint::CreateReplacement(OperatorLoc, NewBinOp);
return;
}
if (const auto *AlwaysTrueOp =
Result.Nodes.getNodeAs<BinaryOperator>("atop")) {
diag(AlwaysTrueOp->getOperatorLoc(),
"the comparison always evaluates to true because %0 always returns "
"non-negative values")
<< getFunctionSpelling(Result, "atop");
<< getFunctionSpelling(Result);
return;
}
const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binop");
diag(BinOp->getOperatorLoc(), "%0 only returns non-negative values")
<< getFunctionSpelling(Result, "binop");
<< getFunctionSpelling(Result);
}

} // namespace clang::tidy::bugprone
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ Changes in existing checks
<clang-tidy/checks/bugprone/forwarding-reference-overload>` check by fixing
a crash when determining if an ``enable_if[_t]`` was found.

- Improved :doc:`bugprone-posix-return
<clang-tidy/checks/bugprone/posix-return>` check to support integer literals
as LHS and posix call as RHS of comparison.

- Improved :doc:`bugprone-sizeof-expression
<clang-tidy/checks/bugprone/sizeof-expression>` check to find suspicious
usages of ``sizeof()``, ``alignof()``, and ``offsetof()`` when adding or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ void warningLessThanZero() {
if (pthread_yield() < 0) {}
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning:
// CHECK-FIXES: pthread_yield() > 0
if (0 > pthread_yield() ) {}
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning:
// CHECK-FIXES: 0 < pthread_yield()

}

Expand All @@ -90,7 +93,8 @@ void warningAlwaysTrue() {
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning:
if (pthread_yield() >= 0) {}
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning:

if (0 <= pthread_yield()) {}
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning:
}

void warningEqualsNegative() {
Expand Down Expand Up @@ -120,7 +124,14 @@ void warningEqualsNegative() {
// CHECK-MESSAGES: :[[@LINE-1]]:46: warning:
if (pthread_create(NULL, NULL, NULL, NULL) < -1) {}
// CHECK-MESSAGES: :[[@LINE-1]]:46: warning:

if (-1 == pthread_create(NULL, NULL, NULL, NULL)) {}
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning:
if (-1 != pthread_create(NULL, NULL, NULL, NULL)) {}
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning:
if (-1 >= pthread_create(NULL, NULL, NULL, NULL)) {}
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning:
if (-1 > pthread_create(NULL, NULL, NULL, NULL)) {}
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning:
}

void WarningWithMacro() {
Expand Down Expand Up @@ -162,6 +173,16 @@ void noWarning() {
if (posix_openpt(0) < -1) {}
if (posix_fadvise(0, 0, 0, 0) <= 0) {}
if (posix_fadvise(0, 0, 0, 0) == 1) {}
if (0 > posix_openpt(0)) {}
if (0 >= posix_openpt(0)) {}
if (-1 == posix_openpt(0)) {}
if (-1 != posix_openpt(0)) {}
if (-1 >= posix_openpt(0)) {}
if (-1 > posix_openpt(0)) {}
if (posix_fadvise(0, 0, 0, 0) <= 0) {}
if (posix_fadvise(0, 0, 0, 0) == 1) {}
if (0 >= posix_fadvise(0, 0, 0, 0)) {}
if (1 == posix_fadvise(0, 0, 0, 0)) {}
}

namespace i {
Expand Down

0 comments on commit d9853a8

Please sign in to comment.