Index: clang-tidy/modernize/CMakeLists.txt =================================================================== --- clang-tidy/modernize/CMakeLists.txt +++ clang-tidy/modernize/CMakeLists.txt @@ -15,6 +15,7 @@ ReplaceAutoPtrCheck.cpp ReplaceRandomShuffleCheck.cpp ReturnBracedInitListCheck.cpp + ReplaceUncaughtExceptionCheck.cpp ShrinkToFitCheck.cpp UnaryStaticAssertCheck.cpp UseAutoCheck.cpp Index: clang-tidy/modernize/ModernizeTidyModule.cpp =================================================================== --- clang-tidy/modernize/ModernizeTidyModule.cpp +++ clang-tidy/modernize/ModernizeTidyModule.cpp @@ -21,6 +21,7 @@ #include "ReplaceAutoPtrCheck.h" #include "ReplaceRandomShuffleCheck.h" #include "ReturnBracedInitListCheck.h" +#include "ReplaceUncaughtExceptionCheck.h" #include "ShrinkToFitCheck.h" #include "UnaryStaticAssertCheck.h" #include "UseAutoCheck.h" @@ -61,6 +62,8 @@ "modernize-replace-random-shuffle"); CheckFactories.registerCheck( "modernize-return-braced-init-list"); + CheckFactories.registerCheck( + "modernize-replace-uncaught-exception"); CheckFactories.registerCheck("modernize-shrink-to-fit"); CheckFactories.registerCheck( "modernize-unary-static-assert"); Index: clang-tidy/modernize/ReplaceUncaughtExceptionCheck.h =================================================================== --- /dev/null +++ clang-tidy/modernize/ReplaceUncaughtExceptionCheck.h @@ -0,0 +1,37 @@ +//===--- ReplaceUncaughtExceptionCheck.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_REPLACE_UNCAUGHT_EXCEPTION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_REPLACE_UNCAUGHT_EXCEPTION_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace modernize { + +/// This check will warn for the occurrences of std::uncaught_exception and replace it with +/// std::uncaught_exceptions. Since C++17 std::uncaught_exception is deprecated. 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-replace-uncaught-exception.html +class ReplaceUncaughtExceptionCheck : public ClangTidyCheck { +public: + ReplaceUncaughtExceptionCheck(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_REPLACE_UNCAUGHT_EXCEPTION_H Index: clang-tidy/modernize/ReplaceUncaughtExceptionCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/modernize/ReplaceUncaughtExceptionCheck.cpp @@ -0,0 +1,66 @@ +//===--- ReplaceUncaughtExceptionCheck.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 "ReplaceUncaughtExceptionCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace modernize { + +static const char *MatchText = "::std::uncaught_exception"; + +void ReplaceUncaughtExceptionCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus1z) + return; + + Finder->addMatcher( + usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText)))) + .bind("using_decl"), + this); + + Finder->addMatcher( + declRefExpr(to(functionDecl(hasName(MatchText)))).bind("call_expr"), + this); +} + +void ReplaceUncaughtExceptionCheck::check( + const MatchFinder::MatchResult &Result) { + SourceLocation BeginLoc; + SourceLocation EndLoc; + + if (const auto *D = Result.Nodes.getNodeAs("call_expr")) { + BeginLoc = D->getLocStart(); + EndLoc = D->getLocEnd(); + } else { + const auto *U = Result.Nodes.getNodeAs("using_decl"); + BeginLoc = U->getNameInfo().getBeginLoc(); + EndLoc = U->getNameInfo().getEndLoc(); + } + + unsigned int TextLength = + Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc), + *Result.SourceManager, getLangOpts()) + .size(); + + auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use " + "'std::uncaught_exceptions' instead"); + + if (!BeginLoc.isMacroID()) { + Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength), + "s"); + } +} + +} // namespace modernize +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -146,6 +146,7 @@ modernize-replace-auto-ptr modernize-replace-random-shuffle modernize-return-braced-init-list + modernize-replace-uncaught-exception modernize-shrink-to-fit modernize-unary-static-assert modernize-use-auto Index: docs/clang-tidy/checks/modernize-replace-uncaught-exception.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/modernize-replace-uncaught-exception.rst @@ -0,0 +1,64 @@ +.. title:: clang-tidy - modernize-replace-uncaught-exception + +modernize-replace-uncaught-exception +==================================== + +This check will warn for the occurrences of ``std::uncaught_exception`` and +replace it with ``std::uncaught_exceptions``. Since C++17 +``std::uncaught_exception`` is deprecated. + +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(); + } \ No newline at end of file Index: test/clang-tidy/modernize-replace-uncaught-exception.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-replace-uncaught-exception.cpp @@ -0,0 +1,54 @@ +// RUN: %check_clang_tidy %s modernize-replace-uncaught-exception %t -- -- -std=c++1z +#define MACRO std::uncaught_exception +// CHECK-FIXES: #define MACRO std::uncaught_exception + +int uncaught_exception() { + return 0; +} + +namespace std { + int uncaught_exception() { + return 0; + } +} + +template +int doSomething(T t) { + return t(); +} + +int main() { + int res; + + res = uncaught_exception(); + // CHECK-FIXES: res = uncaught_exception(); + + res = doSomething(uncaught_exception); + // CHECK-FIXES: res = doSomething(uncaught_exception); + + res = MACRO(); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead + // CHECK-FIXES: res = MACRO(); + + res = std::uncaught_exception(); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead + // CHECK-FIXES: res = 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; + + res = uncaught_exception(); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead + // CHECK-FIXES: res = uncaught_exceptions(); + + res = doSomething(std::uncaught_exception); + // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead + // CHECK-FIXES: res = doSomething(std::uncaught_exceptions); + + res = doSomething(uncaught_exception); + // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'std::uncaught_exception' is deprecated, use 'std::uncaught_exceptions' instead + // CHECK-FIXES: res = doSomething(uncaught_exceptions); + + return res; +}