clang-tools 19.0.0git
UseUncaughtExceptionsCheck.cpp
Go to the documentation of this file.
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
10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/Lex/Lexer.h"
13
14using namespace clang::ast_matchers;
15
16namespace clang::tidy::modernize {
17
19 std::string MatchText = "::std::uncaught_exception";
20
21 // Using declaration: warning and fix-it.
22 Finder->addMatcher(
23 usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
24 .bind("using_decl"),
25 this);
26
27 // DeclRefExpr: warning, no fix-it.
28 Finder->addMatcher(
29 declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr()))
30 .bind("decl_ref_expr"),
31 this);
32
33 auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts(
34 declRefExpr(hasDeclaration(functionDecl(hasName(MatchText)))))));
35
36 // CallExpr: warning, fix-it.
37 Finder->addMatcher(callExpr(DirectCallToUncaughtException,
38 unless(hasAncestor(initListExpr())))
39 .bind("call_expr"),
40 this);
41 // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
42 // conversions.
43 Finder->addMatcher(callExpr(DirectCallToUncaughtException,
44 hasAncestor(initListExpr()))
45 .bind("init_call_expr"),
46 this);
47}
48
49void 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;
54
55 if (C) {
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();
65 WarnOnly = true;
66 } else {
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();
71 }
72
73 auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use "
74 "'std::uncaught_exceptions' instead");
75
76 if (!BeginLoc.isMacroID()) {
77 StringRef Text =
78 Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
79 *Result.SourceManager, getLangOpts());
80
81 Text.consume_back("()");
82 int TextLength = Text.size();
83
84 if (WarnOnly) {
85 return;
86 }
87
88 if (!C) {
89 Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength),
90 "s");
91 } else {
92 Diag << FixItHint::CreateReplacement(C->getSourceRange(),
93 "std::uncaught_exceptions() > 0");
94 }
95 }
96}
97
98} // namespace clang::tidy::modernize
const Expr * E
const Criteria C
std::string Text
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
const LangOptions & getLangOpts() const
Returns the language options from the context.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.