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