1//===--- ExceptionEscapeCheck.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 "ExceptionEscapeCheck.h"
10
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "llvm/ADT/StringSet.h"
13
14using namespace clang::ast_matchers;
15
16namespace clang::tidy::bugprone {
17namespace {
18
19AST_MATCHER_P(FunctionDecl, isEnabled, llvm::StringSet<>,
20 FunctionsThatShouldNotThrow) {
21 return FunctionsThatShouldNotThrow.contains(key: Node.getNameAsString());
22}
23
24AST_MATCHER(FunctionDecl, isExplicitThrow) {
25 return isExplicitThrowExceptionSpec(ESpecType: Node.getExceptionSpecType()) &&
26 Node.getExceptionSpecSourceRange().isValid();
27}
28
29AST_MATCHER(FunctionDecl, hasAtLeastOneParameter) {
30 return Node.getNumParams() > 0;
31}
32
33} // namespace
34
35ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
36 ClangTidyContext *Context)
37 : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get(
38 LocalName: "FunctionsThatShouldNotThrow", Default: "")),
39 RawIgnoredExceptions(Options.get(LocalName: "IgnoredExceptions", Default: "")) {
40 llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec,
41 IgnoredExceptionsVec;
42 StringRef(RawFunctionsThatShouldNotThrow)
43 .split(A&: FunctionsThatShouldNotThrowVec, Separator: ",", MaxSplit: -1, KeepEmpty: false);
44 FunctionsThatShouldNotThrow.insert_range(R&: FunctionsThatShouldNotThrowVec);
45
46 llvm::StringSet<> IgnoredExceptions;
47 StringRef(RawIgnoredExceptions).split(A&: IgnoredExceptionsVec, Separator: ",", MaxSplit: -1, KeepEmpty: false);
48 IgnoredExceptions.insert_range(R&: IgnoredExceptionsVec);
49 Tracer.ignoreExceptions(ExceptionNames: std::move(IgnoredExceptions));
50 Tracer.ignoreBadAlloc(ShallIgnore: true);
51}
52
53void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
54 Options.store(Options&: Opts, LocalName: "FunctionsThatShouldNotThrow",
55 Value: RawFunctionsThatShouldNotThrow);
56 Options.store(Options&: Opts, LocalName: "IgnoredExceptions", Value: RawIgnoredExceptions);
57}
58
59void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
60 Finder->addMatcher(
61 NodeMatch: functionDecl(
62 isDefinition(),
63 anyOf(isNoThrow(),
64 allOf(anyOf(cxxDestructorDecl(),
65 cxxConstructorDecl(isMoveConstructor()),
66 cxxMethodDecl(isMoveAssignmentOperator()), isMain(),
67 allOf(hasAnyName("swap", "iter_swap", "iter_move"),
68 hasAtLeastOneParameter())),
69 unless(isExplicitThrow())),
70 isEnabled(FunctionsThatShouldNotThrow)))
71 .bind(ID: "thrower"),
72 Action: this);
73}
74
75void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
76 const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>(ID: "thrower");
77
78 if (!MatchedDecl)
79 return;
80
81 if (Tracer.analyze(Func: MatchedDecl).getBehaviour() ==
82 utils::ExceptionAnalyzer::State::Throwing)
83 // FIXME: We should provide more information about the exact location where
84 // the exception is thrown, maybe the full path the exception escapes
85 diag(MatchedDecl->getLocation(), "an exception may be thrown in function "
86 "%0 which should not throw exceptions")
87 << MatchedDecl;
88}
89
90} // namespace clang::tidy::bugprone
91

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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