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