hintonda updated this revision to Diff 59794.
hintonda added a comment.
Update matcher to use functionProtoType instead of functionType.
http://reviews.llvm.org/D20693
Files:
clang-tidy/modernize/CMakeLists.txt
clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tidy/modernize/UseNoexceptCheck.cpp
clang-tidy/modernize/UseNoexceptCheck.h
docs/ReleaseNotes.rst
docs/clang-tidy/checks/modernize-use-noexcept.rst
test/clang-tidy/modernize-use-noexcept-macro.cpp
test/clang-tidy/modernize-use-noexcept.cpp
Index: test/clang-tidy/modernize-use-noexcept.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-noexcept.cpp
@@ -0,0 +1,56 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN: -- -std=c++11
+
+class A {};
+class B {};
+
+void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: found dynamic exception specification 'throw()' [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+void bar() throw(...);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: found dynamic exception specification 'throw(...)' [modernize-use-noexcept]
+// CHECK-FIXES: void bar() noexcept(false);
+
+void k() throw(int(int));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found dynamic exception specification 'throw(int(int))' [modernize-use-noexcept]
+// CHECK-FIXES: void k() noexcept(false);
+
+void foobar() throw(A, B)
+{}
+// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: found dynamic exception specification 'throw(A, B)' [modernize-use-noexcept]
+// CHECK-FIXES: void foobar() noexcept(false)
+
+void baz(int = (throw A(), 0)) throw(A, B) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: found dynamic exception specification 'throw(A, B)' [modernize-use-noexcept]
+// CHECK-FIXES: void baz(int = (throw A(), 0)) noexcept(false) {}
+
+void g(void (*fp)(void) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: found dynamic exception specification 'throw()' [modernize-use-noexcept]
+// CHECK-FIXES: void g(void (*fp)(void) noexcept);
+
+void f(void (*fp)(void) throw()) throw(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: found dynamic exception specification 'throw()' [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:34: warning: found dynamic exception specification 'throw(char)' [modernize-use-noexcept]
+// CHECK-FIXES: void f(void (*fp)(void) noexcept) noexcept(false);
+
+void j() throw(int(int) throw(void(void) throw(int)));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: found dynamic exception specification 'throw(int(int) throw(void(void) throw(int)))' [modernize-use-noexcept]
+// CHECK-FIXES: void j() noexcept(false);
+
+class Y {
+ Y() throw() = default;
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: found dynamic exception specification 'throw()' [modernize-use-noexcept]
+// CHECK-FIXES: Y() noexcept = default;
+
+// Should not trigger a replacement.
+void titi() noexcept {}
+void toto() noexcept(true) {}
+
+// Should not trigger a replacement.
+void bad()
+#if !__has_feature(cxx_noexcept)
+ throw()
+#endif
+ ;
Index: test/clang-tidy/modernize-use-noexcept-macro.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-noexcept-macro.cpp
@@ -0,0 +1,24 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-noexcept.ReplacementString, value: 'NOEXCEPT'}]}" \
+// RUN: -- -std=c++11
+
+// Example definition of NOEXCEPT -- simplified test to see if noexcept is supported.
+#if (__has_feature(cxx_noexcept))
+#define NOEXCEPT noexcept
+#else
+#define NOEXCEPT throw()
+#endif
+
+void bar() throw() {}
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: found dynamic exception specification 'throw()' [modernize-use-noexcept]
+// CHECK-FIXES: void bar() NOEXCEPT {}
+
+// Should not trigger a FixItHint, since macros only support noexcept, and this
+// case throws.
+class A {};
+class B {};
+void foobar() throw(A, B);
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: found dynamic exception specification 'throw(A, B)' [modernize-use-noexcept]
+
+// Should not trigger a replacement.
+void foo() noexcept(true);
Index: docs/clang-tidy/checks/modernize-use-noexcept.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/modernize-use-noexcept.rst
@@ -0,0 +1,55 @@
+.. title:: clang-tidy - modernize-use-noexcept
+
+modernize-use-noexcept
+======================
+
+The check converts dynamic exception specifications, e.g., ``throw()``,
+``throw(<exception>[,...])``, or ``throw(...)`` to ``noexcept``, ``noexcept(false)``,
+or a user defined macro.
+
+Example
+-------
+
+.. code-block:: c++
+
+ void foo() throw();
+ void bar() throw(int) {}
+
+transforms to:
+
+.. code-block:: c++
+
+ void foo() noexcept;
+ void bar() noexcept(false) {}
+
+
+User defined macros
+-------------------
+
+By default this check will only replace ``throw()`` with ``noexcept``,
+and ``throw(<exception>[,...])`` or ``throw(...)`` with
+``noexcept(false)``. Additionally, users can also use
+:option:`ReplacementString` to specify a macro to use instead of
+``noexcept``. This is useful when maintaining source code that must
+be compiled with older compilers that don't support the ``noexcept``
+keyword. Users can define the macro to be ``noexcept`` or ``throw()``
+depending on whether or not noexcept is supported.
+
+Please note that since ``throw(int)`` is equivelent to
+``noexcept(false)`` not ``noexcept``, this check will detect, but not
+provide a FixItHint in that case.
+
+Example
+^^^^^^^
+
+.. code-block:: c++
+
+ void foo() throw() {}
+
+transforms to:
+
+.. code-block:: c++
+
+ void foo() NOEXCEPT {}
+
+if the :option:`ReplacementString` option is set to `NOEXCEPT`.
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -206,6 +206,11 @@
Finds integer literals which are cast to ``bool``.
+- New `modernize-use-noexcept
+ <http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-noexcept.html>`_ check
+
+ Replaces dynamic exception specifications with ``noexcept`` or a user defined macro.
+
- New `performance-faster-string-find
<http://clang.llvm.org/extra/clang-tidy/checks/performance-faster-string-find.html>`_ check
Index: clang-tidy/modernize/UseNoexceptCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseNoexceptCheck.h
@@ -0,0 +1,50 @@
+//===--- UseNoexceptCheck.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_NOEXCEPT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+using CandidateSet = llvm::StringSet<llvm::MallocAllocator>;
+
+/// \brief Replace dynamic exception specifications, with
+/// `noexcept` (or user-defined macro) or `noexcept(false)`.
+/// \code
+/// void foo() throw();
+/// void bar() throw(int);
+/// \endcode
+/// Is converted to:
+/// \code
+/// void foo() noexcept;
+// void bar() noexcept(false);
+/// \endcode
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-noexcept.html
+class UseNoexceptCheck : public ClangTidyCheck {
+public:
+ UseNoexceptCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ const std::string DefaultReplacement;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H
Index: clang-tidy/modernize/UseNoexceptCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseNoexceptCheck.cpp
@@ -0,0 +1,102 @@
+//===--- UseNoexceptCheck.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 "UseNoexceptCheck.h"
+#include "clang/AST/ASTContext.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static StringRef
+makeDynamicExceptionString(const SourceManager &SM,
+ const CharSourceRange &FileMoveRange) {
+ std::pair<FileID, unsigned> BeginInfo =
+ SM.getDecomposedLoc(FileMoveRange.getBegin());
+ std::pair<FileID, unsigned> EndInfo =
+ SM.getDecomposedLoc(FileMoveRange.getEnd());
+
+ // Add 1 which represents the size of the trailing ')'.
+ auto Len = EndInfo.second - BeginInfo.second + 1;
+ return StringRef(SM.getCharacterData(FileMoveRange.getBegin()), Len);
+}
+
+UseNoexceptCheck::UseNoexceptCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ DefaultReplacement(Options.get("ReplacementString", "noexcept")) {}
+
+void UseNoexceptCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "ReplacementString", DefaultReplacement);
+}
+
+void UseNoexceptCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ Finder->addMatcher(
+ functionDecl(hasTypeLoc(loc(functionProtoType(hasDynamicExceptionSpec()))))
+ .bind("funcDecl"),
+ this);
+ Finder->addMatcher(
+ parmVarDecl(hasType(pointerType(pointee(parenType(
+ innerType(functionProtoType(hasDynamicExceptionSpec())))))))
+ .bind("parmVarDecl"),
+ this);
+}
+
+void UseNoexceptCheck::check(const MatchFinder::MatchResult &Result) {
+ bool IsNoThrow = false;
+ SourceRange Range;
+
+ if (const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("funcDecl")) {
+ if (auto const *FnTy = FuncDecl->getType()->getAs<FunctionProtoType>())
+ IsNoThrow = FnTy->isNothrow(*Result.Context);
+ if (const auto *Info = FuncDecl->getTypeSourceInfo())
+ Range =
+ Info->getTypeLoc().castAs<FunctionTypeLoc>().getExceptionSpecRange();
+ }
+ if (const auto *ParmDecl =
+ Result.Nodes.getNodeAs<ParmVarDecl>("parmVarDecl")) {
+ if (const auto *PtrTy = ParmDecl->getType()->getAs<PointerType>())
+ if (const auto *FnTy =
+ PtrTy->getPointeeType()->getAs<FunctionProtoType>())
+ IsNoThrow = FnTy->isNothrow(*Result.Context);
+
+ if (const TypeSourceInfo *TSI = ParmDecl->getTypeSourceInfo()) {
+ TypeLoc TL = TSI->getTypeLoc();
+ if (TL.getType()->isPointerType()) {
+ TL = TL.getNextTypeLoc().IgnoreParens();
+ if (auto FPTL = TL.getAs<FunctionProtoTypeLoc>()) {
+ Range = FPTL.getExceptionSpecRange();
+ }
+ }
+ }
+ }
+ if (!Range.isValid())
+ return;
+
+ StringRef SpecificReplacement = DefaultReplacement;
+ FixItHint FixIt;
+ if (!IsNoThrow)
+ SpecificReplacement = "noexcept(false)";
+ if (IsNoThrow || DefaultReplacement == "noexcept")
+ FixIt = FixItHint::CreateReplacement(CharSourceRange(Range, true),
+ SpecificReplacement);
+
+ diag(Range.getBegin(), "found dynamic exception specification '%0'")
+ << makeDynamicExceptionString(*Result.SourceManager,
+ CharSourceRange(Range, true))
+ << FixIt;
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===================================================================
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -23,6 +23,7 @@
#include "UseAutoCheck.h"
#include "UseBoolLiteralsCheck.h"
#include "UseDefaultCheck.h"
+#include "UseNoexceptCheck.h"
#include "UseNullptrCheck.h"
#include "UseOverrideCheck.h"
@@ -54,6 +55,7 @@
CheckFactories.registerCheck<UseBoolLiteralsCheck>(
"modernize-use-bool-literals");
CheckFactories.registerCheck<UseDefaultCheck>("modernize-use-default");
+ CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept");
CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr");
CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override");
}
Index: clang-tidy/modernize/CMakeLists.txt
===================================================================
--- clang-tidy/modernize/CMakeLists.txt
+++ clang-tidy/modernize/CMakeLists.txt
@@ -17,6 +17,7 @@
UseAutoCheck.cpp
UseBoolLiteralsCheck.cpp
UseDefaultCheck.cpp
+ UseNoexceptCheck.cpp
UseNullptrCheck.cpp
UseOverrideCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits