[clang-tidy] Replace the usage of std::uncaught_exception with std::uncaught_exceptions

Patch by: Daniel Kolozsvari!

Differential Revision: https://reviews.llvm.org/D40787

llvm-svn: 325572
This commit is contained in:
Gabor Horvath 2018-02-20 10:48:38 +00:00
parent b8f369d636
commit 76e5023dd3
8 changed files with 294 additions and 0 deletions

View File

@ -27,6 +27,7 @@ add_clang_library(clangTidyModernizeModule
UseNullptrCheck.cpp
UseOverrideCheck.cpp
UseTransparentFunctorsCheck.cpp
UseUncaughtExceptionsCheck.cpp
UseUsingCheck.cpp
LINK_LIBS

View File

@ -33,6 +33,7 @@
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
#include "UseTransparentFunctorsCheck.h"
#include "UseUncaughtExceptionsCheck.h"
#include "UseUsingCheck.h"
using namespace clang::ast_matchers;
@ -78,6 +79,8 @@ public:
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
CheckFactories.registerCheck<UseTransparentFunctorsCheck>(
"modernize-use-transparent-functors");
CheckFactories.registerCheck<UseUncaughtExceptionsCheck>(
"modernize-use-uncaught-exceptions");
CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
}

View File

@ -0,0 +1,104 @@
//===--- UseUncaughtExceptionsCheck.cpp - clang-tidy--------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#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) {
if (!getLangOpts().CPlusPlus17)
return;
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(allOf(to(functionDecl(hasName(MatchText))),
unless(callExpr())))
.bind("decl_ref_expr"),
this);
// CallExpr: warning, fix-it.
Finder->addMatcher(
callExpr(allOf(hasDeclaration(functionDecl(hasName(MatchText))),
unless(hasAncestor(initListExpr()))))
.bind("call_expr"),
this);
// CallExpr in initialisation list: warning, fix-it with avoiding narrowing
// conversions.
Finder->addMatcher(
callExpr(allOf(hasAncestor(initListExpr()),
hasDeclaration(functionDecl(hasName(MatchText)))))
.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->getLocStart();
EndLoc = C->getLocEnd();
} else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) {
BeginLoc = E->getLocStart();
EndLoc = E->getLocEnd();
} else if (const auto *D =
Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) {
BeginLoc = D->getLocStart();
EndLoc = D->getLocEnd();
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

View File

@ -0,0 +1,37 @@
//===--- UseUncaughtExceptionsCheck.h - clang-tidy------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H
#include "../ClangTidy.h"
namespace clang {
namespace tidy {
namespace modernize {
/// This check will warn on calls to std::uncaught_exception and replace them with calls to
/// std::uncaught_exceptions, since std::uncaught_exception was deprecated in C++17. In case of
/// macro ID there will be only a warning without fixits.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-uncaught-exceptions.html
class UseUncaughtExceptionsCheck : public ClangTidyCheck {
public:
UseUncaughtExceptionsCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
};
} // namespace modernize
} // namespace tidy
} // namespace clang
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_UNCAUGHT_EXCEPTIONS_H

View File

@ -105,6 +105,11 @@ Improvements to clang-tidy
Diagnoses when a temporary object that appears to be an exception is constructed but not thrown.
- New `modernize-use-uncaught-exceptions
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-uncaught-exceptions.html>`_ check
Finds and replaces deprecated uses of std::uncaught_exception to std::uncaught_exceptions()
Improvements to include-fixer
-----------------------------

View File

@ -177,6 +177,7 @@ Clang-Tidy Checks
modernize-use-nullptr
modernize-use-override
modernize-use-transparent-functors
modernize-use-uncaught-exceptions
modernize-use-using
mpi-buffer-deref
mpi-type-mismatch

View File

@ -0,0 +1,64 @@
.. title:: clang-tidy - modernize-use-uncaught-exceptions
modernize-use-uncaught-exceptions
====================================
This check will warn on calls to ``std::uncaught_exception`` and replace them with
calls to ``std::uncaught_exceptions``, since ``std::uncaught_exception`` was deprecated
in C++17.
Below are a few examples of what kind of occurrences will be found and what
they will be replaced with.
.. code-block:: c++
#define MACRO1 std::uncaught_exception
#define MACRO2 std::uncaught_exception
int uncaught_exception() {
return 0;
}
int main() {
int res;
res = uncaught_exception();
// No warning, since it is not the deprecated function from namespace std
res = MACRO2();
// Warning, but will not be replaced
res = std::uncaught_exception();
// Warning and replaced
using std::uncaught_exception;
// Warning and replaced
res = uncaught_exception();
// Warning and replaced
}
After applying the fixes the code will look like the following:
.. code-block:: c++
#define MACRO1 std::uncaught_exception
#define MACRO2 std::uncaught_exception
int uncaught_exception() {
return 0;
}
int main() {
int res;
res = uncaught_exception();
res = MACRO2();
res = std::uncaught_exceptions();
using std::uncaught_exceptions;
res = uncaught_exceptions();
}

View File

@ -0,0 +1,79 @@
// RUN: %check_clang_tidy %s modernize-use-uncaught-exceptions %t -- -- -std=c++1z
#define MACRO std::uncaught_exception
// CHECK-FIXES: #define MACRO std::uncaught_exception
bool uncaught_exception() {
return 0;
}
namespace std {
bool uncaught_exception() {
return false;
}
int uncaught_exceptions() {
return 0;
}
}
template <typename T>
bool doSomething(T t) {
return t();
// CHECK-FIXES: return t();
}
template <bool (*T)()>
bool doSomething2() {
return T();
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: return T();
}
void no_warn() {
uncaught_exception();
// CHECK-FIXES: uncaught_exception();
doSomething(uncaught_exception);
// CHECK-FIXES: doSomething(uncaught_exception);
}
void warn() {
std::uncaught_exception();
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: std::uncaught_exceptions();
using std::uncaught_exception;
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: using std::uncaught_exceptions;
uncaught_exception();
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: uncaught_exceptions();
bool b{uncaught_exception()};
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: bool b{std::uncaught_exceptions() > 0};
MACRO();
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: MACRO();
doSomething(std::uncaught_exception);
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: doSomething(std::uncaught_exception);
doSomething(uncaught_exception);
// CHECK-MESSAGES: [[@LINE-1]]:15: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: doSomething(uncaught_exception);
bool (*foo)();
foo = &uncaught_exception;
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: foo = &uncaught_exception;
doSomething2<uncaught_exception>();
// CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead
// CHECK-FIXES: doSomething2<uncaught_exception>();
}