clang-tools  5.0.0
CloexecOpenCheck.cpp
Go to the documentation of this file.
1 //===--- CloexecOpenCheck.cpp - clang-tidy---------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CloexecOpenCheck.h"
11 #include "../utils/ASTUtils.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/Lex/Lexer.h"
15 
16 using namespace clang::ast_matchers;
17 
18 namespace clang {
19 namespace tidy {
20 namespace android {
21 
22 static constexpr const char *O_CLOEXEC = "O_CLOEXEC";
23 
24 void CloexecOpenCheck::registerMatchers(MatchFinder *Finder) {
25  auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
26 
27  Finder->addMatcher(
28  callExpr(callee(functionDecl(isExternC(), returns(isInteger()),
29  hasAnyName("open", "open64"),
30  hasParameter(0, CharPointerType),
31  hasParameter(1, hasType(isInteger())))
32  .bind("funcDecl")))
33  .bind("openFn"),
34  this);
35  Finder->addMatcher(
36  callExpr(callee(functionDecl(isExternC(), returns(isInteger()),
37  hasName("openat"),
38  hasParameter(0, hasType(isInteger())),
39  hasParameter(1, CharPointerType),
40  hasParameter(2, hasType(isInteger())))
41  .bind("funcDecl")))
42  .bind("openatFn"),
43  this);
44 }
45 
46 void CloexecOpenCheck::check(const MatchFinder::MatchResult &Result) {
47  const Expr *FlagArg = nullptr;
48  if (const auto *OpenFnCall = Result.Nodes.getNodeAs<CallExpr>("openFn"))
49  FlagArg = OpenFnCall->getArg(1);
50  else if (const auto *OpenFnCall =
51  Result.Nodes.getNodeAs<CallExpr>("openatFn"))
52  FlagArg = OpenFnCall->getArg(2);
53  assert(FlagArg);
54 
55  const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("funcDecl");
56 
57  // Check the required flag.
58  SourceManager &SM = *Result.SourceManager;
59  if (utils::exprHasBitFlagWithSpelling(FlagArg->IgnoreParenCasts(), SM,
60  Result.Context->getLangOpts(), O_CLOEXEC))
61  return;
62 
63  SourceLocation EndLoc =
64  Lexer::getLocForEndOfToken(SM.getFileLoc(FlagArg->getLocEnd()), 0, SM,
65  Result.Context->getLangOpts());
66 
67  diag(EndLoc, "%0 should use %1 where possible")
68  << FD << O_CLOEXEC
69  << FixItHint::CreateInsertion(EndLoc, (Twine(" | ") + O_CLOEXEC).str());
70 }
71 
72 } // namespace android
73 } // namespace tidy
74 } // namespace clang
static constexpr const char * O_CLOEXEC
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:275
bool exprHasBitFlagWithSpelling(const Expr *Flags, const SourceManager &SM, const LangOptions &LangOpts, StringRef FlagName)
Checks whether a macro flag is present in the given argument.
Definition: ASTUtils.cpp:43
SourceManager & SM