clang-tools  10.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 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace bugprone {
19 
20 static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result,
21  const char *BindingStr) {
22  const CallExpr *MatchedCall = cast<CallExpr>(
23  (Result.Nodes.getNodeAs<BinaryOperator>(BindingStr))->getLHS());
24  const SourceManager &SM = *Result.SourceManager;
25  return Lexer::getSourceText(CharSourceRange::getTokenRange(
26  MatchedCall->getCallee()->getSourceRange()),
27  SM, Result.Context->getLangOpts());
28 }
29 
30 void PosixReturnCheck::registerMatchers(MatchFinder *Finder) {
31  Finder->addMatcher(
32  binaryOperator(
33  hasOperatorName("<"),
34  hasLHS(callExpr(callee(functionDecl(
35  anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
36  unless(hasName("::posix_openpt")))))),
37  hasRHS(integerLiteral(equals(0))))
38  .bind("ltzop"),
39  this);
40  Finder->addMatcher(
41  binaryOperator(
42  hasOperatorName(">="),
43  hasLHS(callExpr(callee(functionDecl(
44  anyOf(matchesName("^::posix_"), matchesName("^::pthread_")),
45  unless(hasName("::posix_openpt")))))),
46  hasRHS(integerLiteral(equals(0))))
47  .bind("atop"),
48  this);
49  Finder->addMatcher(
50  binaryOperator(
51  anyOf(hasOperatorName("=="), hasOperatorName("!="),
52  hasOperatorName("<="), hasOperatorName("<")),
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
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:227
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result, const char *BindingStr)