llvm-project

Форк
0
110 строк · 3.9 Кб
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
#include <algorithm>
16

17
using namespace clang::ast_matchers;
18
using ::clang::ast_matchers::internal::Matcher;
19

20
namespace clang::tidy::bugprone {
21

22
namespace {
23
AST_MATCHER(CXXCatchStmt, isInMacro) {
24
  return Node.getBeginLoc().isMacroID() || Node.getEndLoc().isMacroID() ||
25
         Node.getCatchLoc().isMacroID();
26
}
27

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);
33
}
34

35
AST_MATCHER_P(CXXCatchStmt, hasCaughtType, Matcher<QualType>, InnerMatcher) {
36
  return InnerMatcher.matches(Node.getCaughtType(), Finder, Builder);
37
}
38

39
AST_MATCHER_P(CompoundStmt, hasAnyTextFromList, std::vector<llvm::StringRef>,
40
              List) {
41
  if (List.empty())
42
    return false;
43

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 llvm::any_of(List, [&](const StringRef &Str) {
50
    return Text.contains_insensitive(Str);
51
  });
52
}
53

54
} // namespace
55

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", ""))) {}
62

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));
69
}
70

71
bool EmptyCatchCheck::isLanguageVersionSupported(
72
    const LangOptions &LangOpts) const {
73
  return LangOpts.CPlusPlus;
74
}
75

76
std::optional<TraversalKind> EmptyCatchCheck::getCheckTraversalKind() const {
77
  return TK_IgnoreUnlessSpelledInSource;
78
}
79

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)));
90

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);
99
}
100

101
void EmptyCatchCheck::check(const MatchFinder::MatchResult &Result) {
102
  const auto *MatchedCatchStmt = Result.Nodes.getNodeAs<CXXCatchStmt>("catch");
103

104
  diag(
105
      MatchedCatchStmt->getCatchLoc(),
106
      "empty catch statements hide issues; to handle exceptions appropriately, "
107
      "consider re-throwing, handling, or avoiding catch altogether");
108
}
109

110
} // namespace clang::tidy::bugprone
111

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.