1 //===--- UseUncaughtExceptionsCheck.cpp - clang-tidy--------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "UseUncaughtExceptionsCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers
;
16 namespace clang::tidy::modernize
{
18 void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder
*Finder
) {
19 std::string MatchText
= "::std::uncaught_exception";
21 // Using declaration: warning and fix-it.
23 usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText
))))
27 // DeclRefExpr: warning, no fix-it.
29 declRefExpr(to(functionDecl(hasName(MatchText
))), unless(callExpr()))
30 .bind("decl_ref_expr"),
33 auto DirectCallToUncaughtException
= callee(expr(ignoringImpCasts(
34 declRefExpr(hasDeclaration(functionDecl(hasName(MatchText
)))))));
36 // CallExpr: warning, fix-it.
37 Finder
->addMatcher(callExpr(DirectCallToUncaughtException
,
38 unless(hasAncestor(initListExpr())))
41 // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
43 Finder
->addMatcher(callExpr(DirectCallToUncaughtException
,
44 hasAncestor(initListExpr()))
45 .bind("init_call_expr"),
49 void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult
&Result
) {
50 SourceLocation BeginLoc
;
51 SourceLocation EndLoc
;
52 const auto *C
= Result
.Nodes
.getNodeAs
<CallExpr
>("init_call_expr");
53 bool WarnOnly
= false;
56 BeginLoc
= C
->getBeginLoc();
57 EndLoc
= C
->getEndLoc();
58 } else if (const auto *E
= Result
.Nodes
.getNodeAs
<CallExpr
>("call_expr")) {
59 BeginLoc
= E
->getBeginLoc();
60 EndLoc
= E
->getEndLoc();
61 } else if (const auto *D
=
62 Result
.Nodes
.getNodeAs
<DeclRefExpr
>("decl_ref_expr")) {
63 BeginLoc
= D
->getBeginLoc();
64 EndLoc
= D
->getEndLoc();
67 const auto *U
= Result
.Nodes
.getNodeAs
<UsingDecl
>("using_decl");
68 assert(U
&& "Null pointer, no node provided");
69 BeginLoc
= U
->getNameInfo().getBeginLoc();
70 EndLoc
= U
->getNameInfo().getEndLoc();
73 auto Diag
= diag(BeginLoc
, "'std::uncaught_exception' is deprecated, use "
74 "'std::uncaught_exceptions' instead");
76 if (!BeginLoc
.isMacroID()) {
78 Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc
, EndLoc
),
79 *Result
.SourceManager
, getLangOpts());
81 Text
.consume_back("()");
82 int TextLength
= Text
.size();
89 Diag
<< FixItHint::CreateInsertion(BeginLoc
.getLocWithOffset(TextLength
),
92 Diag
<< FixItHint::CreateReplacement(C
->getSourceRange(),
93 "std::uncaught_exceptions() > 0");
98 } // namespace clang::tidy::modernize