1 //===--- UseUncaughtExceptionsCheck.cpp - clang-tidy--------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "UseUncaughtExceptionsCheck.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.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 if (!getLangOpts().CPlusPlus17) 22 return; 23 24 std::string MatchText = "::std::uncaught_exception"; 25 26 // Using declaration: warning and fix-it. 27 Finder->addMatcher( 28 usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText)))) 29 .bind("using_decl"), 30 this); 31 32 // DeclRefExpr: warning, no fix-it. 33 Finder->addMatcher( 34 declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr())) 35 .bind("decl_ref_expr"), 36 this); 37 38 // CallExpr: warning, fix-it. 39 Finder->addMatcher(callExpr(hasDeclaration(functionDecl(hasName(MatchText))), 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(hasAncestor(initListExpr()), 46 hasDeclaration(functionDecl(hasName(MatchText)))) 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 103