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