1 //===--- BadSignalToKillThreadCheck.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 "BadSignalToKillThreadCheck.h" 10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 12 13 using namespace clang::ast_matchers; 14 15 namespace clang { 16 namespace tidy { 17 namespace bugprone { 18 19 void BadSignalToKillThreadCheck::registerMatchers(MatchFinder *Finder) { 20 Finder->addMatcher( 21 callExpr(allOf(callee(functionDecl(hasName("::pthread_kill"))), 22 argumentCountIs(2)), 23 hasArgument(1, integerLiteral().bind("integer-literal"))) 24 .bind("thread-kill"), 25 this); 26 } 27 28 static Preprocessor *PP; 29 30 void BadSignalToKillThreadCheck::check(const MatchFinder::MatchResult &Result) { 31 const auto IsSigterm = [](const auto &KeyValue) -> bool { 32 return KeyValue.first->getName() == "SIGTERM"; 33 }; 34 const auto TryExpandAsInteger = 35 [](Preprocessor::macro_iterator It) -> Optional<unsigned> { 36 if (It == PP->macro_end()) 37 return llvm::None; 38 const MacroInfo *MI = PP->getMacroInfo(It->first); 39 const Token &T = MI->tokens().back(); 40 StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength()); 41 42 llvm::APInt IntValue; 43 constexpr unsigned AutoSenseRadix = 0; 44 if (ValueStr.getAsInteger(AutoSenseRadix, IntValue)) 45 return llvm::None; 46 return IntValue.getZExtValue(); 47 }; 48 49 const auto SigtermMacro = llvm::find_if(PP->macros(), IsSigterm); 50 51 if (!SigtermValue && !(SigtermValue = TryExpandAsInteger(SigtermMacro))) 52 return; 53 54 const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("thread-kill"); 55 const auto *MatchedIntLiteral = 56 Result.Nodes.getNodeAs<IntegerLiteral>("integer-literal"); 57 if (MatchedIntLiteral->getValue() == *SigtermValue) { 58 diag(MatchedExpr->getBeginLoc(), 59 "thread should not be terminated by raising the 'SIGTERM' signal"); 60 } 61 } 62 63 void BadSignalToKillThreadCheck::registerPPCallbacks( 64 const SourceManager &SM, Preprocessor *pp, Preprocessor *ModuleExpanderPP) { 65 PP = pp; 66 } 67 68 } // namespace bugprone 69 } // namespace tidy 70 } // namespace clang 71