clang-tools  9.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 
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  // CallExpr: warning, fix-it.
38  Finder->addMatcher(callExpr(hasDeclaration(functionDecl(hasName(MatchText))),
39  unless(hasAncestor(initListExpr())))
40  .bind("call_expr"),
41  this);
42  // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
43  // conversions.
44  Finder->addMatcher(callExpr(hasAncestor(initListExpr()),
45  hasDeclaration(functionDecl(hasName(MatchText))))
46  .bind("init_call_expr"),
47  this);
48 }
49 
50 void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult &Result) {
51  SourceLocation BeginLoc;
52  SourceLocation EndLoc;
53  const CallExpr *C = Result.Nodes.getNodeAs<CallExpr>("init_call_expr");
54  bool WarnOnly = false;
55 
56  if (C) {
57  BeginLoc = C->getBeginLoc();
58  EndLoc = C->getEndLoc();
59  } else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) {
60  BeginLoc = E->getBeginLoc();
61  EndLoc = E->getEndLoc();
62  } else if (const auto *D =
63  Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) {
64  BeginLoc = D->getBeginLoc();
65  EndLoc = D->getEndLoc();
66  WarnOnly = true;
67  } else {
68  const auto *U = Result.Nodes.getNodeAs<UsingDecl>("using_decl");
69  assert(U && "Null pointer, no node provided");
70  BeginLoc = U->getNameInfo().getBeginLoc();
71  EndLoc = U->getNameInfo().getEndLoc();
72  }
73 
74  auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use "
75  "'std::uncaught_exceptions' instead");
76 
77  if (!BeginLoc.isMacroID()) {
78  StringRef Text =
79  Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
80  *Result.SourceManager, getLangOpts());
81 
82  Text.consume_back("()");
83  int TextLength = Text.size();
84 
85  if (WarnOnly) {
86  return;
87  }
88 
89  if (!C) {
90  Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength),
91  "s");
92  } else {
93  Diag << FixItHint::CreateReplacement(C->getSourceRange(),
94  "std::uncaught_exceptions() > 0");
95  }
96  }
97 }
98 
99 } // namespace modernize
100 } // namespace tidy
101 } // namespace clang
std::string Text
const Decl * D
Definition: XRefs.cpp:868
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:203
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: Rename.cpp:36