JonasToth updated this revision to Diff 184477.
JonasToth added a comment.

- Merge branch 'master' into feature-introduce-noexcept


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D57108/new/

https://reviews.llvm.org/D57108

Files:
  clang-tidy/modernize/UseNoexceptCheck.cpp
  clang-tidy/modernize/UseNoexceptCheck.h
  test/clang-tidy/modernize-use-noexcept-new-noexcept.cpp
  test/clang-tidy/modernize-use-noexcept-opt.cpp
  test/clang-tidy/modernize-use-noexcept.cpp

Index: test/clang-tidy/modernize-use-noexcept.cpp
===================================================================
--- test/clang-tidy/modernize-use-noexcept.cpp
+++ test/clang-tidy/modernize-use-noexcept.cpp
@@ -10,9 +10,9 @@
 
 template <typename T>
 void foo() throw();
-void footest() { foo<int>(); foo<double>(); }
-// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
 // CHECK-FIXES: void foo() noexcept;
+void footest() { foo<int>(); foo<double>(); }
 
 void bar() throw(...);
 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw(...)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
@@ -70,21 +70,21 @@
 
 struct S {
   void f() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
 };
 void f(void (S::*)() throw());
-// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
-// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
 // CHECK-FIXES: void f() noexcept;
 // CHECK-FIXES: void f(void (S::*)() noexcept);
 
 template <typename T>
 struct ST {
   void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
 };
 template <typename T>
 void ft(void (ST<T>::*)() throw());
-// CHECK-MESSAGES: :[[@LINE-4]]:14: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
-// CHECK-MESSAGES: :[[@LINE-2]]:27: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-1]]:27: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
 // CHECK-FIXES: void foo() noexcept;
 // CHECK-FIXES: void ft(void (ST<T>::*)() noexcept);
 
Index: test/clang-tidy/modernize-use-noexcept-opt.cpp
===================================================================
--- test/clang-tidy/modernize-use-noexcept-opt.cpp
+++ test/clang-tidy/modernize-use-noexcept-opt.cpp
@@ -65,11 +65,11 @@
 
 struct S {
   void f() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f() noexcept;
 };
 void f(void (S::*)() throw());
-// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
-// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
-// CHECK-FIXES: void f() noexcept;
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
 // CHECK-FIXES: void f(void (S::*)() noexcept);
 
 typedef void (*fp)(void (*fp2)(int) throw());
Index: test/clang-tidy/modernize-use-noexcept-new-noexcept.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-noexcept-new-noexcept.cpp
@@ -0,0 +1,46 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-noexcept.AddMissingNoexcept, value: 1}]}" \
+// RUN:   -- -std=c++11 -fexceptions
+
+void undefined();
+void undefinedNoexcept() noexcept;
+
+void empty() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: this function can not throw an exception, consider adding 'noexcept'
+
+int tryCatchBody() try {
+  int Array[] = {1, 2, 3, 4};
+  throw int(42);
+  return Array[0] + Array[1] + Array[2] + Array[3];
+} catch (...) {
+  return 42;
+}
+// CHECK-MESSAGES: :[[@LINE-7]]:1: warning: this function can not throw an exception, consider adding 'noexcept'
+
+int functionCanThrow() {
+  throw int(42);
+}
+
+struct ConstructorWithNoexcept {
+  ConstructorWithNoexcept() = default;
+  int nonThrowingMember() { return 42; }
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this function can not throw an exception, consider adding 'noexcept'
+  int nonThrowingButShown() noexcept { return 42; }
+  void undefinedMethod();
+  int Member;
+};
+
+template <typename T>
+void nonThrowingTemplateUnknown();
+
+template <typename T>
+T nonThrowingTemplateKnown() {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: this function can not throw an exception, consider adding 'noexcept'
+  return T{};
+}
+void instantiate() {
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: this function can not throw an exception, consider adding 'noexcept'
+  (void)nonThrowingTemplateKnown<int>();
+  (void)nonThrowingTemplateKnown<float>();
+  (void)nonThrowingTemplateKnown<double>();
+}
Index: clang-tidy/modernize/UseNoexceptCheck.h
===================================================================
--- clang-tidy/modernize/UseNoexceptCheck.h
+++ clang-tidy/modernize/UseNoexceptCheck.h
@@ -10,6 +10,7 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H
 
 #include "../ClangTidy.h"
+#include "../utils/ExceptionAnalyzer.h"
 
 namespace clang {
 namespace tidy {
@@ -38,7 +39,9 @@
 
 private:
   const std::string NoexceptMacro;
-  bool UseNoexceptFalse;
+  const bool UseNoexceptFalse;
+  const bool AddMissingNoexcept;
+  utils::ExceptionAnalyzer Analyzer;
 };
 
 } // namespace modernize
Index: clang-tidy/modernize/UseNoexceptCheck.cpp
===================================================================
--- clang-tidy/modernize/UseNoexceptCheck.cpp
+++ clang-tidy/modernize/UseNoexceptCheck.cpp
@@ -19,11 +19,13 @@
 UseNoexceptCheck::UseNoexceptCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       NoexceptMacro(Options.get("ReplacementString", "")),
-      UseNoexceptFalse(Options.get("UseNoexceptFalse", true)) {}
+      UseNoexceptFalse(Options.get("UseNoexceptFalse", true)),
+      AddMissingNoexcept(Options.get("AddMissingNoexcept", false)) {}
 
 void UseNoexceptCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "ReplacementString", NoexceptMacro);
   Options.store(Opts, "UseNoexceptFalse", UseNoexceptFalse);
+  Options.store(Opts, "AddMissingNoexcept", AddMissingNoexcept);
 }
 
 void UseNoexceptCheck::registerMatchers(MatchFinder *Finder) {
@@ -56,6 +58,14 @@
                             functionProtoType(hasDynamicExceptionSpec()))))))))
           .bind("parmVarDecl"),
       this);
+
+  if (AddMissingNoexcept)
+    Finder->addMatcher(
+        functionDecl(allOf(hasBody(stmt()),
+                           unless(anyOf(isNoThrow(), hasDynamicExceptionSpec(),
+                                        isImplicit()))))
+            .bind("potentialNoexcept"),
+        this);
 }
 
 void UseNoexceptCheck::check(const MatchFinder::MatchResult &Result) {
@@ -82,6 +92,14 @@
                   .IgnoreParens()
                   .castAs<FunctionProtoTypeLoc>()
                   .getExceptionSpecRange();
+  } else if (const auto *PotentialNoexcept =
+                 Result.Nodes.getNodeAs<FunctionDecl>("potentialNoexcept")) {
+    if (!Analyzer.throwsException(PotentialNoexcept) &&
+        PotentialNoexcept->getBeginLoc().isValid())
+      diag(PotentialNoexcept->getBeginLoc(),
+           "this function can not throw an exception, consider adding "
+           "'noexcept'");
+    return;
   }
   CharSourceRange CRange = Lexer::makeFileCharRange(
       CharSourceRange::getTokenRange(Range), *Result.SourceManager,
@@ -92,10 +110,10 @@
   StringRef ReplacementStr =
       IsNoThrow
           ? NoexceptMacro.empty() ? "noexcept" : NoexceptMacro.c_str()
-          : NoexceptMacro.empty()
-                ? (DtorOrOperatorDel || UseNoexceptFalse) ? "noexcept(false)"
-                                                          : ""
-                : "";
+          : NoexceptMacro.empty() ? (DtorOrOperatorDel || UseNoexceptFalse)
+                                        ? "noexcept(false)"
+                                        : ""
+                                  : "";
 
   FixItHint FixIt;
   if ((IsNoThrow || NoexceptMacro.empty()) && CRange.isValid())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to