clang-tools  14.0.0git
PosixReturnCheck.cpp
Go to the documentation of this file.
1 //===--- PosixReturnCheck.cpp - clang-tidy---------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "PosixReturnCheck.h"
10 #include "../utils/Matchers.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14 
15 using namespace clang::ast_matchers;
16 
17 namespace clang {
18 namespace tidy {
19 namespace bugprone {
20 
21 static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result,
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());
29 }
30 
31 void PosixReturnCheck::registerMatchers(MatchFinder *Finder) {
32  Finder->addMatcher(
33  binaryOperator(
34  hasOperatorName("<"),
35  hasLHS(callExpr(callee(functionDecl(
36  anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
37  unless(hasName("::posix_openpt")))))),
38  hasRHS(integerLiteral(equals(0))))
39  .bind("ltzop"),
40  this);
41  Finder->addMatcher(
42  binaryOperator(
43  hasOperatorName(">="),
44  hasLHS(callExpr(callee(functionDecl(
45  anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
46  unless(hasName("::posix_openpt")))))),
47  hasRHS(integerLiteral(equals(0))))
48  .bind("atop"),
49  this);
50  Finder->addMatcher(
51  binaryOperator(
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()))))
58  .bind("binop"),
59  this);
60 }
61 
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")
68  << getFunctionSpelling(Result, "ltzop")
69  << FixItHint::CreateReplacement(OperatorLoc, Twine(">").str());
70  return;
71  }
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")
77  << getFunctionSpelling(Result, "atop");
78  return;
79  }
80  const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binop");
81  diag(BinOp->getOperatorLoc(), "%0 only returns non-negative values")
82  << getFunctionSpelling(Result, "binop");
83 }
84 
85 } // namespace bugprone
86 } // namespace tidy
87 } // namespace clang
clang::tidy::cppcoreguidelines::getSourceText
static std::string getSourceText(const CXXDestructorDecl &Destructor)
Definition: VirtualClassDestructorCheck.cpp:112
PosixReturnCheck.h
clang::ast_matchers
Definition: AbseilMatcher.h:14
clang::clangd::check
bool check(llvm::StringRef File, llvm::function_ref< bool(const Position &)> ShouldCheckLine, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:259
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::bugprone::getFunctionSpelling
static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result, const char *BindingStr)
Definition: PosixReturnCheck.cpp:21