12#include "clang/AST/ASTContext.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/Lex/Lexer.h"
17using ::clang::ast_matchers::internal::Matcher;
23 return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID() ||
24 Node.getCatchLoc().isMacroID();
27AST_MATCHER_P(CXXCatchStmt, hasHandler, Matcher<Stmt>, InnerMatcher) {
28 Stmt *Handler = Node.getHandlerBlock();
31 return InnerMatcher.matches(*Handler, Finder, Builder);
34AST_MATCHER_P(CXXCatchStmt, hasCaughtType, Matcher<QualType>, InnerMatcher) {
35 return InnerMatcher.matches(Node.getCaughtType(), Finder, Builder);
38AST_MATCHER_P(CompoundStmt, hasAnyTextFromList, std::vector<llvm::StringRef>,
43 ASTContext &Context = Finder->getASTContext();
44 SourceManager &SM = Context.getSourceManager();
45 StringRef
Text = Lexer::getSourceText(
46 CharSourceRange::getTokenRange(Node.getSourceRange()), SM,
47 Context.getLangOpts());
48 return llvm::any_of(List, [&](
const StringRef &Str) {
49 return Text.contains_insensitive(Str);
57 IgnoreCatchWithKeywords(
utils::options::parseStringList(
58 Options.get(
"IgnoreCatchWithKeywords",
"@TODO;@FIXME"))),
59 AllowEmptyCatchForExceptions(
utils::options::parseStringList(
60 Options.get(
"AllowEmptyCatchForExceptions",
""))) {}
63 Options.store(Opts,
"IgnoreCatchWithKeywords",
66 Opts,
"AllowEmptyCatchForExceptions",
71 const LangOptions &LangOpts)
const {
72 return LangOpts.CPlusPlus;
76 return TK_IgnoreUnlessSpelledInSource;
80 auto AllowedNamedExceptionDecl =
82 auto AllowedNamedExceptionTypes =
83 qualType(anyOf(hasDeclaration(AllowedNamedExceptionDecl),
84 references(AllowedNamedExceptionDecl),
85 pointsTo(AllowedNamedExceptionDecl)));
86 auto IgnoredExceptionType =
87 qualType(anyOf(AllowedNamedExceptionTypes,
88 hasCanonicalType(AllowedNamedExceptionTypes)));
91 cxxCatchStmt(unless(isExpansionInSystemHeader()), unless(isInMacro()),
92 unless(hasCaughtType(IgnoredExceptionType)),
93 hasHandler(compoundStmt(
95 unless(hasAnyTextFromList(IgnoreCatchWithKeywords)))))
101 const auto *MatchedCatchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>(
"catch");
104 MatchedCatchStmt->getCatchLoc(),
105 "empty catch statements hide issues; to handle exceptions appropriately, "
106 "consider re-throwing, handling, or avoiding catch altogether");
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
EmptyCatchCheck(StringRef Name, ClangTidyContext *Context)
std::optional< TraversalKind > getCheckTraversalKind() const override
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
void registerMatchers(ast_matchers::MatchFinder *Finder) override
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID)
AST_MATCHER(BinaryOperator, isRelationalOperator)
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedName(llvm::ArrayRef< StringRef > NameList)
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
llvm::StringMap< ClangTidyValue > OptionMap