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/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 102