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//===----------------------------------------------------------------------===//
8
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
16using namespace clang::ast_matchers;
17using ::clang::ast_matchers::internal::Matcher;
18
19namespace clang::tidy::bugprone {
20
21namespace {
22AST_MATCHER(CXXCatchStmt, isInMacro) {
23 return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID() ||
24 Node.getCatchLoc().isMacroID();
25}
26
27AST_MATCHER_P(CXXCatchStmt, hasHandler, Matcher<Stmt>, InnerMatcher) {
28 Stmt *Handler = Node.getHandlerBlock();
29 if (!Handler)
30 return false;
31 return InnerMatcher.matches(Node: *Handler, Finder, Builder);
32}
33
34AST_MATCHER_P(CXXCatchStmt, hasCaughtType, Matcher<QualType>, InnerMatcher) {
35 return InnerMatcher.matches(Node: Node.getCaughtType(), Finder, Builder);
36}
37
38AST_MATCHER_P(CompoundStmt, hasAnyTextFromList, std::vector<llvm::StringRef>,
39 List) {
40 if (List.empty())
41 return false;
42
43 ASTContext &Context = Finder->getASTContext();
44 SourceManager &SM = Context.getSourceManager();
45 StringRef Text = Lexer::getSourceText(
46 Range: CharSourceRange::getTokenRange(Node.getSourceRange()), SM,
47 LangOpts: Context.getLangOpts());
48 return llvm::any_of(Range: List, P: [&](const StringRef &Str) {
49 return Text.contains_insensitive(Str);
50 });
51}
52
53} // namespace
54
55EmptyCatchCheck::EmptyCatchCheck(StringRef Name, ClangTidyContext *Context)
56 : ClangTidyCheck(Name, Context),
57 IgnoreCatchWithKeywords(utils::options::parseStringList(
58 Option: Options.get(LocalName: "IgnoreCatchWithKeywords", Default: "@TODO;@FIXME"))),
59 AllowEmptyCatchForExceptions(utils::options::parseStringList(
60 Option: Options.get(LocalName: "AllowEmptyCatchForExceptions", Default: ""))) {}
61
62void EmptyCatchCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
63 Options.store(Options&: Opts, LocalName: "IgnoreCatchWithKeywords",
64 Value: utils::options::serializeStringList(Strings: IgnoreCatchWithKeywords));
65 Options.store(
66 Options&: Opts, LocalName: "AllowEmptyCatchForExceptions",
67 Value: utils::options::serializeStringList(Strings: AllowEmptyCatchForExceptions));
68}
69
70bool EmptyCatchCheck::isLanguageVersionSupported(
71 const LangOptions &LangOpts) const {
72 return LangOpts.CPlusPlus;
73}
74
75std::optional<TraversalKind> EmptyCatchCheck::getCheckTraversalKind() const {
76 return TK_IgnoreUnlessSpelledInSource;
77}
78
79void EmptyCatchCheck::registerMatchers(MatchFinder *Finder) {
80 auto AllowedNamedExceptionDecl =
81 namedDecl(matchers::matchesAnyListedName(NameList: AllowEmptyCatchForExceptions));
82 auto AllowedNamedExceptionTypes =
83 qualType(anyOf(hasDeclaration(InnerMatcher: AllowedNamedExceptionDecl),
84 references(InnerMatcher: AllowedNamedExceptionDecl),
85 pointsTo(InnerMatcher: AllowedNamedExceptionDecl)));
86 auto IgnoredExceptionType =
87 qualType(anyOf(AllowedNamedExceptionTypes,
88 hasCanonicalType(InnerMatcher: AllowedNamedExceptionTypes)));
89
90 Finder->addMatcher(
91 NodeMatch: cxxCatchStmt(unless(isExpansionInSystemHeader()), unless(isInMacro()),
92 unless(hasCaughtType(InnerMatcher: IgnoredExceptionType)),
93 hasHandler(InnerMatcher: compoundStmt(
94 statementCountIs(N: 0),
95 unless(hasAnyTextFromList(List: IgnoreCatchWithKeywords)))))
96 .bind(ID: "catch"),
97 Action: this);
98}
99
100void EmptyCatchCheck::check(const MatchFinder::MatchResult &Result) {
101 const auto *MatchedCatchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>(ID: "catch");
102
103 diag(
104 Loc: MatchedCatchStmt->getCatchLoc(),
105 Description: "empty catch statements hide issues; to handle exceptions appropriately, "
106 "consider re-throwing, handling, or avoiding catch altogether");
107}
108
109} // namespace clang::tidy::bugprone
110

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang-tools-extra/clang-tidy/bugprone/EmptyCatchCheck.cpp