blob: 9b6ccf29a2aeb5463272be3a1a47c6178a63ab49 [file] [log] [blame]
Yan Wang0b974142017-06-29 17:40:57 +00001//===--- CloexecCreatCheck.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 "CloexecCreatCheck.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/Lex/Lexer.h"
14
15using namespace clang::ast_matchers;
16
17namespace clang {
18namespace tidy {
19namespace android {
20
21void CloexecCreatCheck::registerMatchers(MatchFinder *Finder) {
22 auto CharPointerType = hasType(pointerType(pointee(isAnyCharacter())));
23 auto MODETType = hasType(namedDecl(hasName("mode_t")));
24
25 Finder->addMatcher(
26 callExpr(callee(functionDecl(isExternC(), returns(isInteger()),
27 hasName("creat"),
28 hasParameter(0, CharPointerType),
29 hasParameter(1, MODETType))
30 .bind("funcDecl")))
31 .bind("creatFn"),
32 this);
33}
34
35void CloexecCreatCheck::check(const MatchFinder::MatchResult &Result) {
36 const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>("creatFn");
37 const SourceManager &SM = *Result.SourceManager;
38
39 const std::string &ReplacementText =
40 (Twine("open (") +
41 Lexer::getSourceText(CharSourceRange::getTokenRange(
42 MatchedCall->getArg(0)->getSourceRange()),
43 SM, Result.Context->getLangOpts()) +
44 ", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, " +
45 Lexer::getSourceText(CharSourceRange::getTokenRange(
46 MatchedCall->getArg(1)->getSourceRange()),
47 SM, Result.Context->getLangOpts()) +
48 ")")
49 .str();
50
51 diag(MatchedCall->getLocStart(),
52 "prefer open() to creat() because open() allows O_CLOEXEC")
53 << FixItHint::CreateReplacement(MatchedCall->getSourceRange(),
54 ReplacementText);
55}
56
57} // namespace android
58} // namespace tidy
59} // namespace clang