clang-tools  9.0.0
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(binaryOperator(hasOperatorName("<"),
32  hasLHS(callExpr(callee(functionDecl(
33  matchesName("^::posix_"),
34  unless(hasName("::posix_openpt")))))),
35  hasRHS(integerLiteral(equals(0))))
36  .bind("ltzop"),
37  this);
38  Finder->addMatcher(binaryOperator(hasOperatorName(">="),
39  hasLHS(callExpr(callee(functionDecl(
40  matchesName("^::posix_"),
41  unless(hasName("::posix_openpt")))))),
42  hasRHS(integerLiteral(equals(0))))
43  .bind("atop"),
44  this);
45  Finder->addMatcher(
46  binaryOperator(
47  anyOf(hasOperatorName("=="), hasOperatorName("!="),
48  hasOperatorName("<="), hasOperatorName("<")),
49  hasLHS(callExpr(callee(functionDecl(
50  matchesName("^::posix_"), unless(hasName("::posix_openpt")))))),
51  hasRHS(unaryOperator(hasOperatorName("-"),
52  hasUnaryOperand(integerLiteral()))))
53  .bind("binop"),
54  this);
55 }
56 
57 void PosixReturnCheck::check(const MatchFinder::MatchResult &Result) {
58  if (const auto *LessThanZeroOp =
59  Result.Nodes.getNodeAs<BinaryOperator>("ltzop")) {
60  SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc();
61  diag(OperatorLoc, "the comparison always evaluates to false because %0 "
62  "always returns non-negative values")
63  << getFunctionSpelling(Result, "ltzop")
64  << FixItHint::CreateReplacement(OperatorLoc, Twine(">").str());
65  return;
66  }
67  if (const auto *AlwaysTrueOp =
68  Result.Nodes.getNodeAs<BinaryOperator>("atop")) {
69  diag(AlwaysTrueOp->getOperatorLoc(),
70  "the comparison always evaluates to true because %0 always returns "
71  "non-negative values")
72  << getFunctionSpelling(Result, "atop");
73  return;
74  }
75  const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binop");
76  diag(BinOp->getOperatorLoc(), "%0 only returns non-negative values")
77  << getFunctionSpelling(Result, "binop");
78 }
79 
80 } // namespace bugprone
81 } // namespace tidy
82 } // namespace clang
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:203
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: Rename.cpp:36
static StringRef getFunctionSpelling(const MatchFinder::MatchResult &Result, const char *BindingStr)