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