Skip to content

Commit

Permalink
[clang-tidy] Replace the usage of std::uncaught_exception with std::u…
Browse files Browse the repository at this point in the history
…ncaught_exceptions

Patch by: Daniel Kolozsvari!

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

llvm-svn: 325572
  • Loading branch information
Xazax-hun committed Feb 20, 2018
1 parent b8f369d commit 76e5023
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 0 deletions.
1 change: 1 addition & 0 deletions clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
Expand Up @@ -27,6 +27,7 @@ add_clang_library(clangTidyModernizeModule
UseNullptrCheck.cpp
UseOverrideCheck.cpp
UseTransparentFunctorsCheck.cpp
UseUncaughtExceptionsCheck.cpp
UseUsingCheck.cpp

LINK_LIBS
Expand Down
Expand Up @@ -33,6 +33,7 @@
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
#include "UseTransparentFunctorsCheck.h"
#include "UseUncaughtExceptionsCheck.h"
#include "UseUsingCheck.h"

using namespace clang::ast_matchers;
Expand Down Expand Up @@ -78,6 +79,8 @@ class ModernizeModule : public ClangTidyModule {
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");
}

Expand Down
104 changes: 104 additions & 0 deletions clang-tools-extra/clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
@@ -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
@@ -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
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Expand Up @@ -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
-----------------------------

Expand Down
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Expand Up @@ -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
Expand Down
@@ -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();
}
@@ -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>();
}

0 comments on commit 76e5023

Please sign in to comment.