koldaniel updated this revision to Diff 132595.

https://reviews.llvm.org/D40787

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
  clang-tidy/modernize/UseUncaughtExceptionsCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-use-uncaught-exceptions.rst
  test/clang-tidy/modernize-use-uncaught-exceptions.cpp

Index: test/clang-tidy/modernize-use-uncaught-exceptions.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-uncaught-exceptions.cpp
@@ -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>();
+}
Index: docs/clang-tidy/checks/modernize-use-uncaught-exceptions.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/modernize-use-uncaught-exceptions.rst
@@ -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();
+    }
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -173,6 +173,7 @@
    modernize-use-nullptr
    modernize-use-override
    modernize-use-transparent-functors
+   modernize-use-uncaught-exceptions
    modernize-use-using
    mpi-buffer-deref
    mpi-type-mismatch
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -64,6 +64,11 @@
   object is statically initialized with a ``constexpr`` constructor or has no 
   explicit constructor.
 
+- 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
 -----------------------------
 
Index: clang-tidy/modernize/UseUncaughtExceptionsCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseUncaughtExceptionsCheck.h
@@ -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
Index: clang-tidy/modernize/UseUncaughtExceptionsCheck.cpp
===================================================================
--- /dev/null
+++ 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
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===================================================================
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -33,6 +33,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseTransparentFunctorsCheck.h"
+#include "UseUncaughtExceptionsCheck.h"
 #include "UseUsingCheck.h"
 
 using namespace clang::ast_matchers;
@@ -76,6 +77,8 @@
     CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept");
     CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
     CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
+    CheckFactories.registerCheck<UseUncaughtExceptionsCheck>(
+        "modernize-use-uncaught-exceptions");
     CheckFactories.registerCheck<UseTransparentFunctorsCheck>(
         "modernize-use-transparent-functors");
     CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
Index: clang-tidy/modernize/CMakeLists.txt
===================================================================
--- clang-tidy/modernize/CMakeLists.txt
+++ clang-tidy/modernize/CMakeLists.txt
@@ -27,6 +27,7 @@
   UseNullptrCheck.cpp
   UseOverrideCheck.cpp
   UseTransparentFunctorsCheck.cpp
+  UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
 
   LINK_LIBS
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to