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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

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