|  | //===--- UseUncaughtExceptionsCheck.cpp - clang-tidy--------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "UseUncaughtExceptionsCheck.h" | 
|  | #include "clang/AST/ASTContext.h" | 
|  | #include "clang/ASTMatchers/ASTMatchFinder.h" | 
|  | #include "clang/Lex/Lexer.h" | 
|  |  | 
|  | using namespace clang::ast_matchers; | 
|  |  | 
|  | namespace clang::tidy::modernize { | 
|  |  | 
|  | void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder *Finder) { | 
|  | std::string MatchText = "::std::uncaught_exception"; | 
|  |  | 
|  | // Using declaration: warning and fix-it. | 
|  | Finder->addMatcher( | 
|  | usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText)))) | 
|  | .bind("using_decl"), | 
|  | this); | 
|  |  | 
|  | // DeclRefExpr: warning, no fix-it. | 
|  | Finder->addMatcher( | 
|  | declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr())) | 
|  | .bind("decl_ref_expr"), | 
|  | this); | 
|  |  | 
|  | auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts( | 
|  | declRefExpr(hasDeclaration(functionDecl(hasName(MatchText))))))); | 
|  |  | 
|  | // CallExpr: warning, fix-it. | 
|  | Finder->addMatcher(callExpr(DirectCallToUncaughtException, | 
|  | unless(hasAncestor(initListExpr()))) | 
|  | .bind("call_expr"), | 
|  | this); | 
|  | // CallExpr in initialisation list: warning, fix-it with avoiding narrowing | 
|  | // conversions. | 
|  | Finder->addMatcher(callExpr(DirectCallToUncaughtException, | 
|  | hasAncestor(initListExpr())) | 
|  | .bind("init_call_expr"), | 
|  | this); | 
|  | } | 
|  |  | 
|  | void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult &Result) { | 
|  | SourceLocation BeginLoc; | 
|  | SourceLocation EndLoc; | 
|  | const auto *C = Result.Nodes.getNodeAs<CallExpr>("init_call_expr"); | 
|  | bool WarnOnly = false; | 
|  |  | 
|  | if (C) { | 
|  | BeginLoc = C->getBeginLoc(); | 
|  | EndLoc = C->getEndLoc(); | 
|  | } else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) { | 
|  | BeginLoc = E->getBeginLoc(); | 
|  | EndLoc = E->getEndLoc(); | 
|  | } else if (const auto *D = | 
|  | Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) { | 
|  | BeginLoc = D->getBeginLoc(); | 
|  | EndLoc = D->getEndLoc(); | 
|  | WarnOnly = true; | 
|  | } else { | 
|  | const auto *U = Result.Nodes.getNodeAs<UsingDecl>("using_decl"); | 
|  | assert(U && "Null pointer, no node provided"); | 
|  | BeginLoc = U->getNameInfo().getBeginLoc(); | 
|  | EndLoc = U->getNameInfo().getEndLoc(); | 
|  | } | 
|  |  | 
|  | auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use " | 
|  | "'std::uncaught_exceptions' instead"); | 
|  |  | 
|  | if (!BeginLoc.isMacroID()) { | 
|  | StringRef Text = | 
|  | Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc), | 
|  | *Result.SourceManager, getLangOpts()); | 
|  |  | 
|  | Text.consume_back("()"); | 
|  | int TextLength = Text.size(); | 
|  |  | 
|  | if (WarnOnly) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!C) { | 
|  | Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength), | 
|  | "s"); | 
|  | } else { | 
|  | Diag << FixItHint::CreateReplacement(C->getSourceRange(), | 
|  | "std::uncaught_exceptions() > 0"); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | } // namespace clang::tidy::modernize |