1 //===--- CloexecSocketCheck.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 "CloexecSocketCheck.h" 11 #include "../utils/ASTUtils.h" 12 #include "clang/AST/ASTContext.h" 13 #include "clang/ASTMatchers/ASTMatchFinder.h" 14 15 using namespace clang::ast_matchers; 16 17 namespace clang { 18 namespace tidy { 19 namespace android { 20 21 static constexpr const char *SOCK_CLOEXEC = "SOCK_CLOEXEC"; 22 23 void CloexecSocketCheck::registerMatchers(MatchFinder *Finder) { 24 Finder->addMatcher( 25 callExpr(callee(functionDecl(isExternC(), returns(isInteger()), 26 hasName("socket"), 27 hasParameter(0, hasType(isInteger())), 28 hasParameter(1, hasType(isInteger())), 29 hasParameter(2, hasType(isInteger()))) 30 .bind("funcDecl"))) 31 .bind("socketFn"), 32 this); 33 } 34 35 void CloexecSocketCheck::check(const MatchFinder::MatchResult &Result) { 36 const auto *MatchedCall = Result.Nodes.getNodeAs<CallExpr>("socketFn"); 37 const auto *FD = Result.Nodes.getNodeAs<FunctionDecl>("funcDecl"); 38 const Expr *FlagArg = MatchedCall->getArg(1); 39 SourceManager &SM = *Result.SourceManager; 40 41 if (utils::exprHasBitFlagWithSpelling(FlagArg->IgnoreParenCasts(), SM, 42 Result.Context->getLangOpts(), SOCK_CLOEXEC)) 43 return; 44 45 SourceLocation EndLoc = 46 Lexer::getLocForEndOfToken(SM.getFileLoc(FlagArg->getLocEnd()), 0, SM, 47 Result.Context->getLangOpts()); 48 49 diag(EndLoc, "%0 should use %1 where possible") 50 << FD << SOCK_CLOEXEC 51 << FixItHint::CreateInsertion(EndLoc, 52 (Twine(" | ") + SOCK_CLOEXEC).str()); 53 } 54 55 } // namespace android 56 } // namespace tidy 57 } // namespace clang 58