1//===--- UseNoexceptCheck.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 "UseNoexceptCheck.h"
10#include "clang/AST/ASTContext.h"
11#include "clang/Lex/Lexer.h"
12
13using namespace clang::ast_matchers;
14
15namespace clang::tidy::modernize {
16
17namespace {
18AST_MATCHER(NamedDecl, isValid) { return !Node.isInvalidDecl(); }
19} // namespace
20
21UseNoexceptCheck::UseNoexceptCheck(StringRef Name, ClangTidyContext *Context)
22 : ClangTidyCheck(Name, Context),
23 NoexceptMacro(Options.get(LocalName: "ReplacementString", Default: "")),
24 UseNoexceptFalse(Options.get(LocalName: "UseNoexceptFalse", Default: true)) {}
25
26void UseNoexceptCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
27 Options.store(Options&: Opts, LocalName: "ReplacementString", Value: NoexceptMacro);
28 Options.store(Options&: Opts, LocalName: "UseNoexceptFalse", Value: UseNoexceptFalse);
29}
30
31void UseNoexceptCheck::registerMatchers(MatchFinder *Finder) {
32 Finder->addMatcher(
33 NodeMatch: functionDecl(
34 isValid(),
35 hasTypeLoc(Inner: loc(InnerMatcher: functionProtoType(hasDynamicExceptionSpec()))),
36 optionally(cxxMethodDecl(anyOf(hasAnyOverloadedOperatorName(
37 "delete[]", "delete"),
38 cxxDestructorDecl()))
39 .bind(ID: "del-dtor")))
40 .bind(ID: "funcDecl"),
41 Action: this);
42
43 Finder->addMatcher(
44 NodeMatch: parmVarDecl(anyOf(hasType(InnerMatcher: pointerType(pointee(parenType(innerType(
45 functionProtoType(hasDynamicExceptionSpec())))))),
46 hasType(InnerMatcher: memberPointerType(pointee(parenType(innerType(
47 functionProtoType(hasDynamicExceptionSpec()))))))))
48 .bind(ID: "parmVarDecl"),
49 Action: this);
50}
51
52void UseNoexceptCheck::check(const MatchFinder::MatchResult &Result) {
53 const FunctionProtoType *FnTy = nullptr;
54 bool DtorOrOperatorDel = false;
55 SourceRange Range;
56
57 if (const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>(ID: "funcDecl")) {
58 DtorOrOperatorDel = Result.Nodes.getNodeAs<FunctionDecl>(ID: "del-dtor");
59 FnTy = FuncDecl->getType()->getAs<FunctionProtoType>();
60 if (const auto *TSI = FuncDecl->getTypeSourceInfo())
61 Range =
62 TSI->getTypeLoc().castAs<FunctionTypeLoc>().getExceptionSpecRange();
63 } else if (const auto *ParmDecl =
64 Result.Nodes.getNodeAs<ParmVarDecl>(ID: "parmVarDecl")) {
65 FnTy = ParmDecl->getType()
66 ->castAs<Type>()
67 ->getPointeeType()
68 ->getAs<FunctionProtoType>();
69
70 if (const auto *TSI = ParmDecl->getTypeSourceInfo())
71 Range = TSI->getTypeLoc()
72 .getNextTypeLoc()
73 .IgnoreParens()
74 .castAs<FunctionProtoTypeLoc>()
75 .getExceptionSpecRange();
76 }
77
78 assert(FnTy && "FunctionProtoType is null.");
79 if (isUnresolvedExceptionSpec(ESpecType: FnTy->getExceptionSpecType()))
80 return;
81
82 assert(Range.isValid() && "Exception Source Range is invalid.");
83
84 CharSourceRange CRange = Lexer::makeFileCharRange(
85 Range: CharSourceRange::getTokenRange(R: Range), SM: *Result.SourceManager,
86 LangOpts: Result.Context->getLangOpts());
87
88 bool IsNoThrow = FnTy->isNothrow();
89 StringRef ReplacementStr =
90 IsNoThrow ? NoexceptMacro.empty() ? "noexcept" : NoexceptMacro
91 : NoexceptMacro.empty()
92 ? (DtorOrOperatorDel || UseNoexceptFalse) ? "noexcept(false)" : ""
93 : "";
94
95 FixItHint FixIt;
96 if ((IsNoThrow || NoexceptMacro.empty()) && CRange.isValid())
97 FixIt = FixItHint::CreateReplacement(RemoveRange: CRange, Code: ReplacementStr);
98
99 diag(Loc: Range.getBegin(), Description: "dynamic exception specification '%0' is deprecated; "
100 "consider %select{using '%2'|removing it}1 instead")
101 << Lexer::getSourceText(Range: CRange, SM: *Result.SourceManager,
102 LangOpts: Result.Context->getLangOpts())
103 << ReplacementStr.empty() << ReplacementStr << FixIt;
104}
105
106} // namespace clang::tidy::modernize
107

source code of clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp