1 //===--- SetLongJmpCheck.cpp - clang-tidy----------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "SetLongJmpCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Lex/PPCallbacks.h"
14 #include "clang/Lex/Preprocessor.h"
16 using namespace clang::ast_matchers
;
18 namespace clang::tidy::cert
{
21 const char DiagWording
[] =
22 "do not call %0; consider using exception handling instead";
24 class SetJmpMacroCallbacks
: public PPCallbacks
{
25 SetLongJmpCheck
&Check
;
28 explicit SetJmpMacroCallbacks(SetLongJmpCheck
&Check
) : Check(Check
) {}
30 void MacroExpands(const Token
&MacroNameTok
, const MacroDefinition
&MD
,
31 SourceRange Range
, const MacroArgs
*Args
) override
{
32 const auto *II
= MacroNameTok
.getIdentifierInfo();
36 if (II
->getName() == "setjmp")
37 Check
.diag(Range
.getBegin(), DiagWording
) << II
;
42 void SetLongJmpCheck::registerPPCallbacks(const SourceManager
&SM
,
44 Preprocessor
*ModuleExpanderPP
) {
45 // Per [headers]p5, setjmp must be exposed as a macro instead of a function,
46 // despite the allowance in C for setjmp to also be an extern function.
47 PP
->addPPCallbacks(std::make_unique
<SetJmpMacroCallbacks
>(*this));
50 void SetLongJmpCheck::registerMatchers(MatchFinder
*Finder
) {
51 // In case there is an implementation that happens to define setjmp as a
52 // function instead of a macro, this will also catch use of it. However, we
53 // are primarily searching for uses of longjmp.
55 callExpr(callee(functionDecl(hasAnyName("setjmp", "longjmp"))))
60 void SetLongJmpCheck::check(const MatchFinder::MatchResult
&Result
) {
61 const auto *E
= Result
.Nodes
.getNodeAs
<CallExpr
>("expr");
62 diag(E
->getExprLoc(), DiagWording
) << cast
<NamedDecl
>(E
->getCalleeDecl());
65 } // namespace clang::tidy::cert