[Workflow] Try to fix code-formatter failing to find changes in some cases.
[llvm-project.git] / clang-tools-extra / clang-tidy / bugprone / EmptyCatchCheck.cpp
blob865c88391b0b4b4c9a37ab74d3e9b29d13cb8531
1 //===--- EmptyCatchCheck.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 //===----------------------------------------------------------------------===//
9 #include "EmptyCatchCheck.h"
10 #include "../utils/Matchers.h"
11 #include "../utils/OptionsUtils.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/Lex/Lexer.h"
15 #include <algorithm>
17 using namespace clang::ast_matchers;
18 using ::clang::ast_matchers::internal::Matcher;
20 namespace clang::tidy::bugprone {
22 namespace {
23 AST_MATCHER(CXXCatchStmt, isInMacro) {
24 return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID() ||
25 Node.getCatchLoc().isMacroID();
28 AST_MATCHER_P(CXXCatchStmt, hasHandler, Matcher<Stmt>, InnerMatcher) {
29 Stmt *Handler = Node.getHandlerBlock();
30 if (!Handler)
31 return false;
32 return InnerMatcher.matches(*Handler, Finder, Builder);
35 AST_MATCHER_P(CXXCatchStmt, hasCaughtType, Matcher<QualType>, InnerMatcher) {
36 return InnerMatcher.matches(Node.getCaughtType(), Finder, Builder);
39 AST_MATCHER_P(CompoundStmt, hasAnyTextFromList, std::vector<llvm::StringRef>,
40 List) {
41 if (List.empty())
42 return false;
44 ASTContext &Context = Finder->getASTContext();
45 SourceManager &SM = Context.getSourceManager();
46 StringRef Text = Lexer::getSourceText(
47 CharSourceRange::getTokenRange(Node.getSourceRange()), SM,
48 Context.getLangOpts());
49 return std::any_of(List.begin(), List.end(), [&](const StringRef &Str) {
50 return Text.contains_insensitive(Str);
51 });
54 } // namespace
56 EmptyCatchCheck::EmptyCatchCheck(StringRef Name, ClangTidyContext *Context)
57 : ClangTidyCheck(Name, Context),
58 IgnoreCatchWithKeywords(utils::options::parseStringList(
59 Options.get("IgnoreCatchWithKeywords", "@TODO;@FIXME"))),
60 AllowEmptyCatchForExceptions(utils::options::parseStringList(
61 Options.get("AllowEmptyCatchForExceptions", ""))) {}
63 void EmptyCatchCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
64 Options.store(Opts, "IgnoreCatchWithKeywords",
65 utils::options::serializeStringList(IgnoreCatchWithKeywords));
66 Options.store(
67 Opts, "AllowEmptyCatchForExceptions",
68 utils::options::serializeStringList(AllowEmptyCatchForExceptions));
71 bool EmptyCatchCheck::isLanguageVersionSupported(
72 const LangOptions &LangOpts) const {
73 return LangOpts.CPlusPlus;
76 std::optional<TraversalKind> EmptyCatchCheck::getCheckTraversalKind() const {
77 return TK_IgnoreUnlessSpelledInSource;
80 void EmptyCatchCheck::registerMatchers(MatchFinder *Finder) {
81 auto AllowedNamedExceptionDecl =
82 namedDecl(matchers::matchesAnyListedName(AllowEmptyCatchForExceptions));
83 auto AllowedNamedExceptionTypes =
84 qualType(anyOf(hasDeclaration(AllowedNamedExceptionDecl),
85 references(AllowedNamedExceptionDecl),
86 pointsTo(AllowedNamedExceptionDecl)));
87 auto IgnoredExceptionType =
88 qualType(anyOf(AllowedNamedExceptionTypes,
89 hasCanonicalType(AllowedNamedExceptionTypes)));
91 Finder->addMatcher(
92 cxxCatchStmt(unless(isExpansionInSystemHeader()), unless(isInMacro()),
93 unless(hasCaughtType(IgnoredExceptionType)),
94 hasHandler(compoundStmt(
95 statementCountIs(0),
96 unless(hasAnyTextFromList(IgnoreCatchWithKeywords)))))
97 .bind("catch"),
98 this);
101 void EmptyCatchCheck::check(const MatchFinder::MatchResult &Result) {
102 const auto *MatchedCatchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>("catch");
104 diag(
105 MatchedCatchStmt->getCatchLoc(),
106 "empty catch statements hide issues; to handle exceptions appropriately, "
107 "consider re-throwing, handling, or avoiding catch altogether");
110 } // namespace clang::tidy::bugprone