UseNullptrCheck.cpp
UseOverrideCheck.cpp
UseTransparentFunctorsCheck.cpp
+ UseUncaughtExceptionsCheck.cpp
UseUsingCheck.cpp
LINK_LIBS
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
#include "UseTransparentFunctorsCheck.h"
+#include "UseUncaughtExceptionsCheck.h"
#include "UseUsingCheck.h"
using namespace clang::ast_matchers;
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");
}
--- /dev/null
+//===--- 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
--- /dev/null
+//===--- 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
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
-----------------------------
modernize-use-nullptr
modernize-use-override
modernize-use-transparent-functors
+ modernize-use-uncaught-exceptions
modernize-use-using
mpi-buffer-deref
mpi-type-mismatch
--- /dev/null
+.. 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();
+ }
--- /dev/null
+// 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>();
+}