sbarzowski removed rL LLVM as the repository for this revision.
sbarzowski updated this revision to Diff 84577.
sbarzowski added a comment.
Herald added subscribers: JDevlieghere, mgorny.
I took advantage of new getExceptionSpecSourceRange (it wasn't available
before) instead of getting exception specification manually with the lexer.
https://reviews.llvm.org/D19201
Files:
clang-tidy/misc/CMakeLists.txt
clang-tidy/misc/MiscTidyModule.cpp
clang-tidy/misc/ThrowWithNoexceptCheck.cpp
clang-tidy/misc/ThrowWithNoexceptCheck.h
docs/ReleaseNotes.rst
docs/clang-tidy/checks/list.rst
docs/clang-tidy/checks/misc-throw-with-noexcept.rst
test/clang-tidy/misc-throw-with-noexcept.cpp
Index: test/clang-tidy/misc-throw-with-noexcept.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-throw-with-noexcept.cpp
@@ -0,0 +1,88 @@
+// RUN: %check_clang_tidy %s misc-throw-with-noexcept %t
+
+void f_throw_with_ne() noexcept(true) {
+ {
+ throw 5;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:24: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void f_throw_with_ne() {
+
+void f_noexcept_false() noexcept(false) {
+ throw 5;
+}
+
+void f_decl_only() noexcept;
+
+// Controversial example
+void throw_and_catch() noexcept(true) {
+ try {
+ throw 5;
+ } catch (...) {
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-6]]:24: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-5]]:5: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void throw_and_catch() {
+
+void with_parens() noexcept((true)) {
+ throw 42;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:20: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-3]]:2: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void with_parens() {
+
+
+void with_parens_and_spaces() noexcept ( (true) ) {
+ throw 42;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:31: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-3]]:2: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void with_parens_and_spaces() {
+
+class Class {
+ void InClass() const noexcept(true) {
+ throw 42;
+ }
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:24: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void InClass() const {
+
+
+void forward_declared() noexcept;
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-FIXES: void forward_declared() ;
+
+void forward_declared() noexcept {
+ throw 42;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:25: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-3]]:2: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void forward_declared() {
+
+void getFunction() noexcept {
+ struct X {
+ static void inner()
+ {
+ throw 42;
+ }
+ };
+}
+
+void dynamic_exception_spec() throw() {
+ throw 42;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:31: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void dynamic_exception_spec() {
+
+#define NOEXCEPT noexcept
+
+void with_macro() NOEXCEPT {
+ throw 42;
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:19: warning: In function declared no-throw here: [misc-throw-with-noexcept]
+// CHECK-MESSAGES: :[[@LINE-3]]:3: warning: 'throw' expression in a function declared with a non-throwing exception specification [misc-throw-with-noexcept]
+// CHECK-FIXES: void with_macro() {
Index: docs/clang-tidy/checks/misc-throw-with-noexcept.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-throw-with-noexcept.rst
@@ -0,0 +1,22 @@
+.. title:: clang-tidy - misc-throw-with-noexcept
+
+mist-throw-with-noexcept
+========================
+
+This check finds cases of using ``throw`` in a function declared as noexcept.
+Please note that the warning is issued even if the exception is caught within
+the same function, as that would be probably a bad style anyway.
+
+It removes the noexcept specifier as a fix.
+
+
+ .. code-block:: c++
+
+ void f() noexcept {
+ throw 42;
+ }
+
+ // Will be changed to
+ void f() {
+ throw 42;
+ }
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -91,6 +91,7 @@
misc-suspicious-string-compare
misc-swapped-arguments
misc-throw-by-value-catch-by-reference
+ misc-throw-with-noexcept
misc-unconventional-assign-operator
misc-undelegated-constructor
misc-uniqueptr-reset-release
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -57,7 +57,10 @@
Improvements to clang-tidy
--------------------------
-The improvements are...
+- New `misc-throw-with-noexcept
+ <http://clang.llvm.org/extra/clang-tidy/checks/misc-throw-with-noexcept.html>`_ check
+
+ Flags ``throw`` statements in functions marked as no-throw.
Improvements to include-fixer
-----------------------------
Index: clang-tidy/misc/ThrowWithNoexceptCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/ThrowWithNoexceptCheck.h
@@ -0,0 +1,33 @@
+//===--- ThrowWithNoexceptCheck.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_MISC_THROW_WITH_NOEXCEPT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_THROW_WITH_NOEXCEPT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+///\brief Warns about using throw in function declared as noexcept.
+/// It complains about every throw, even if it is caught later.
+class ThrowWithNoexceptCheck : public ClangTidyCheck {
+public:
+ ThrowWithNoexceptCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_THROW_WITH_NOEXCEPT_H
Index: clang-tidy/misc/ThrowWithNoexceptCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/ThrowWithNoexceptCheck.cpp
@@ -0,0 +1,60 @@
+//===--- ThrowWithNoexceptCheck.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 "ThrowWithNoexceptCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void ThrowWithNoexceptCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+ Finder->addMatcher(
+ cxxThrowExpr(stmt(forFunction(functionDecl(isNoThrow()).bind("func"))))
+ .bind("throw"),
+ this);
+}
+
+void ThrowWithNoexceptCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Function = Result.Nodes.getNodeAs<FunctionDecl>("func");
+ const auto *Throw = Result.Nodes.getNodeAs<Stmt>("throw");
+ diag(Throw->getLocStart(), "'throw' expression in a function declared with a "
+ "non-throwing exception specification");
+
+ llvm::SmallVector<SourceRange, 5> NoExceptRanges;
+ for (const auto *Redecl : Function->redecls()) {
+ SourceRange NoExceptRange =
+ Redecl->getExceptionSpecSourceRange();
+
+ if (NoExceptRange.isValid()) {
+ NoExceptRanges.push_back(NoExceptRange);
+ } else {
+ /* If a single one is not valid, we cannot apply the fix as we need to
+ * remove noexcept in all declarations for the fix to be effective. */
+ NoExceptRanges.clear();
+ break;
+ }
+ }
+
+ for (const auto &NoExceptRange : NoExceptRanges) {
+ // FIXME use DiagnosticIDs::Level::Note
+ diag(NoExceptRange.getBegin(), "In function declared no-throw here:")
+ << FixItHint::CreateRemoval(NoExceptRange);
+ }
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -46,6 +46,7 @@
#include "SwappedArgumentsCheck.h"
#include "ThrowByValueCatchByReferenceCheck.h"
#include "UnconventionalAssignOperatorCheck.h"
+#include "ThrowWithNoexceptCheck.h"
#include "UndelegatedConstructor.h"
#include "UniqueptrResetReleaseCheck.h"
#include "UnusedAliasDeclsCheck.h"
@@ -126,6 +127,8 @@
"misc-swapped-arguments");
CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>(
"misc-throw-by-value-catch-by-reference");
+ CheckFactories.registerCheck<ThrowWithNoexceptCheck>(
+ "misc-throw-with-noexcept");
CheckFactories.registerCheck<UndelegatedConstructorCheck>(
"misc-undelegated-constructor");
CheckFactories.registerCheck<UniqueptrResetReleaseCheck>(
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -38,6 +38,7 @@
SuspiciousStringCompareCheck.cpp
SwappedArgumentsCheck.cpp
ThrowByValueCatchByReferenceCheck.cpp
+ ThrowWithNoexceptCheck.cpp
UndelegatedConstructor.cpp
UniqueptrResetReleaseCheck.cpp
UnusedAliasDeclsCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits