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 KeyValue.first->hasMacroDefinition(); 35 }; 36 const auto TryExpandAsInteger = 37 [](Preprocessor::macro_iterator It) -> Optional<unsigned> { 38 if (It == PP->macro_end()) 39 return llvm::None; 40 const MacroInfo *MI = PP->getMacroInfo(It->first); 41 const Token &T = MI->tokens().back(); 42 if (!T.isLiteral() || !T.getLiteralData()) 43 return llvm::None; 44 StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength()); 45 46 llvm::APInt IntValue; 47 constexpr unsigned AutoSenseRadix = 0; 48 if (ValueStr.getAsInteger(AutoSenseRadix, IntValue)) 49 return llvm::None; 50 return IntValue.getZExtValue(); 51 }; 52 53 const auto SigtermMacro = llvm::find_if(PP->macros(), IsSigterm); 54 55 if (!SigtermValue && !(SigtermValue = TryExpandAsInteger(SigtermMacro))) 56 return; 57 58 const auto *MatchedExpr = Result.Nodes.getNodeAs<Expr>("thread-kill"); 59 const auto *MatchedIntLiteral = 60 Result.Nodes.getNodeAs<IntegerLiteral>("integer-literal"); 61 if (MatchedIntLiteral->getValue() == *SigtermValue) { 62 diag(MatchedExpr->getBeginLoc(), 63 "thread should not be terminated by raising the 'SIGTERM' signal"); 64 } 65 } 66 67 void BadSignalToKillThreadCheck::registerPPCallbacks( 68 const SourceManager &SM, Preprocessor *Pp, Preprocessor *ModuleExpanderPP) { 69 PP = Pp; 70 } 71 72 } // namespace bugprone 73 } // namespace tidy 74 } // namespace clang 75