150
|
1 //===--- UseUncaughtExceptionsCheck.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 "UseUncaughtExceptionsCheck.h"
|
|
10 #include "clang/AST/ASTContext.h"
|
|
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
12
|
|
13 using namespace clang::ast_matchers;
|
|
14
|
|
15 namespace clang {
|
|
16 namespace tidy {
|
|
17 namespace modernize {
|
|
18
|
|
19 void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder *Finder) {
|
|
20 if (!getLangOpts().CPlusPlus17)
|
|
21 return;
|
|
22
|
|
23 std::string MatchText = "::std::uncaught_exception";
|
|
24
|
|
25 // Using declaration: warning and fix-it.
|
|
26 Finder->addMatcher(
|
|
27 usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
|
|
28 .bind("using_decl"),
|
|
29 this);
|
|
30
|
|
31 // DeclRefExpr: warning, no fix-it.
|
|
32 Finder->addMatcher(
|
|
33 declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr()))
|
|
34 .bind("decl_ref_expr"),
|
|
35 this);
|
|
36
|
|
37 auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts(
|
|
38 declRefExpr(hasDeclaration(functionDecl(hasName(MatchText)))))));
|
|
39
|
|
40 // CallExpr: warning, fix-it.
|
|
41 Finder->addMatcher(callExpr(DirectCallToUncaughtException,
|
|
42 unless(hasAncestor(initListExpr())))
|
|
43 .bind("call_expr"),
|
|
44 this);
|
|
45 // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
|
|
46 // conversions.
|
|
47 Finder->addMatcher(callExpr(DirectCallToUncaughtException,
|
|
48 hasAncestor(initListExpr()))
|
|
49 .bind("init_call_expr"),
|
|
50 this);
|
|
51 }
|
|
52
|
|
53 void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult &Result) {
|
|
54 SourceLocation BeginLoc;
|
|
55 SourceLocation EndLoc;
|
|
56 const CallExpr *C = Result.Nodes.getNodeAs<CallExpr>("init_call_expr");
|
|
57 bool WarnOnly = false;
|
|
58
|
|
59 if (C) {
|
|
60 BeginLoc = C->getBeginLoc();
|
|
61 EndLoc = C->getEndLoc();
|
|
62 } else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) {
|
|
63 BeginLoc = E->getBeginLoc();
|
|
64 EndLoc = E->getEndLoc();
|
|
65 } else if (const auto *D =
|
|
66 Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) {
|
|
67 BeginLoc = D->getBeginLoc();
|
|
68 EndLoc = D->getEndLoc();
|
|
69 WarnOnly = true;
|
|
70 } else {
|
|
71 const auto *U = Result.Nodes.getNodeAs<UsingDecl>("using_decl");
|
|
72 assert(U && "Null pointer, no node provided");
|
|
73 BeginLoc = U->getNameInfo().getBeginLoc();
|
|
74 EndLoc = U->getNameInfo().getEndLoc();
|
|
75 }
|
|
76
|
|
77 auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use "
|
|
78 "'std::uncaught_exceptions' instead");
|
|
79
|
|
80 if (!BeginLoc.isMacroID()) {
|
|
81 StringRef Text =
|
|
82 Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
|
|
83 *Result.SourceManager, getLangOpts());
|
|
84
|
|
85 Text.consume_back("()");
|
|
86 int TextLength = Text.size();
|
|
87
|
|
88 if (WarnOnly) {
|
|
89 return;
|
|
90 }
|
|
91
|
|
92 if (!C) {
|
|
93 Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength),
|
|
94 "s");
|
|
95 } else {
|
|
96 Diag << FixItHint::CreateReplacement(C->getSourceRange(),
|
|
97 "std::uncaught_exceptions() > 0");
|
|
98 }
|
|
99 }
|
|
100 }
|
|
101
|
|
102 } // namespace modernize
|
|
103 } // namespace tidy
|
|
104 } // namespace clang
|