forked from OSchip/llvm-project
102 lines
3.4 KiB
C++
102 lines
3.4 KiB
C++
//===--- 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"
|
|
|
|
using namespace clang::ast_matchers;
|
|
|
|
namespace clang {
|
|
namespace tidy {
|
|
namespace 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 CallExpr *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 modernize
|
|
} // namespace tidy
|
|
} // namespace clang
|