Szelethus created this revision.
Szelethus added reviewers: cfe-commits, xazax.hun.
Szelethus added a project: clang-tools-extra.
Herald added subscribers: hintonda, rnkovacs, mgorny.
New checker called misc-throw-keyword-missing warns about cases where a 
temporary object's type is (likely) an exception but is not thrown. This is 
done by checking whether the type's name (or one of its baseclass' name) 
contains the substring "EXCEPTION", "Exception" or "exception".

  void f(int i){
      if(i = 0)
          // Exception is created but not thrown.
          std::runtime_error("Wrong argument");
  }


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43120

Files:
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  clang-tidy/misc/ThrowKeywordMissingCheck.cpp
  clang-tidy/misc/ThrowKeywordMissingCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-throw-keyword-missing.rst
  test/clang-tidy/misc-throw-keyword-missing.cpp

Index: test/clang-tidy/misc-throw-keyword-missing.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-throw-keyword-missing.cpp
@@ -0,0 +1,152 @@
+// RUN: %check_clang_tidy %s misc-throw-keyword-missing %t
+
+namespace std {
+
+// std::string declaration (taken from test/clang-tidy/readability-redundant-string-cstr-msvc.cpp)
+template <typename T>
+class allocator {};
+template <typename T>
+class char_traits {};
+template <typename C, typename T = std::char_traits<C>, typename A = std::allocator<C>>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string&);
+  // MSVC headers define two constructors instead of using optional arguments.
+  basic_string(const C *);
+  basic_string(const C *, const A &);
+  ~basic_string();
+};
+typedef basic_string<char> string;
+typedef basic_string<wchar_t> wstring;
+
+// std::exception and std::runtime_error declaration
+struct exception{
+  exception();
+  exception( const exception& other);
+  virtual ~exception();
+};
+
+struct runtime_error : public exception{
+  explicit runtime_error( const std::string& what_arg );
+};
+
+} //namespace std
+
+// The usage of this class should never emit a warning
+struct RegularClass {};
+
+// Classname contains the substring "exception", in certain cases using this class should emit a warning
+struct RegularException {
+  RegularException() {}
+
+  // Constructors with a single argument are treated differently (cxxFunctionalCastExpr) 
+  RegularException(int) {}
+};
+
+// --------------
+
+void stdExceptionNotTrown(int i) {
+  if (i < 0)
+    //CHECK-MESSAGES: :[[@LINE+1]]:5: warning: exception created but is not thrown [misc-throw-keyword-missing]
+    std::exception();
+
+  if (i > 0)
+    //CHECK-MESSAGES: :[[@LINE+1]]:5: warning: exception created but is not thrown [misc-throw-keyword-missing]
+    std::runtime_error("Unexpected argument");
+
+}
+
+void stdExceptionThrown(int i) {
+  if (i < 0)
+    throw std::exception();
+
+  if (i > 0)
+    throw std::runtime_error("Unexpected argument");
+}
+
+void regularClassNotThrown(int i) {
+  if (i < 0)
+    RegularClass();
+}
+
+void regularClassThrown(int i) {
+  if (i < 0)
+    throw RegularClass();
+}
+
+void nameContainsExceptionNotThrown(int i) {
+  if (i < 0)
+    //CHECK-MESSAGES: :[[@LINE+1]]:5: warning: exception created but is not thrown [misc-throw-keyword-missing]
+    RegularException();
+
+  if (i > 0)
+    //CHECK-MESSAGES: :[[@LINE+1]]:5: warning: exception created but is not thrown [misc-throw-keyword-missing]
+    RegularException(5);
+}
+
+void nameContainsExceptionThrown(int i) {
+  if (i < 0)
+    throw RegularException();
+
+  if (i > 0)
+    throw RegularException(5);
+}
+
+
+template <class Exception>
+void f(int i, Exception excToBeThrown){}
+
+void funcCallWithTempExcTest(){
+  f(5, RegularException());
+}
+
+// Global variable initilization test
+RegularException exc = RegularException();
+RegularException* excptr = new RegularException();
+
+void localVariableInitTest(){
+  RegularException exc = RegularException();
+  RegularException* excptr = new RegularException();
+}
+
+class CtorInitializerListTest{
+  RegularException exc;
+
+  CtorInitializerListTest() : exc(RegularException()) {}
+
+  CtorInitializerListTest(int) 
+    try : exc(RegularException()) {
+      //Constructor
+    }
+    catch(...){
+      //CHECK-MESSAGES: :[[@LINE+1]]:7: warning: exception created but is not thrown [misc-throw-keyword-missing]
+      RegularException();
+    }
+
+  CtorInitializerListTest(float);
+};
+
+CtorInitializerListTest::CtorInitializerListTest(float) 
+  try : exc(RegularException()) {
+    //Constructor
+  }
+  catch(...){
+    //CHECK-MESSAGES: :[[@LINE+1]]:5: warning: exception created but is not thrown [misc-throw-keyword-missing]
+    RegularException();
+  }
+
+RegularException funcReturningExceptioniTest(int i){
+  return RegularException();
+}
+
+struct ClassBracedInitListTest{
+  ClassBracedInitListTest(RegularException exc) {}
+};
+
+void functionBracedInitListTest(RegularException, ClassBracedInitListTest) {}
+
+void bracedInitListTest(){
+  RegularException exc{};
+  ClassBracedInitListTest test = {RegularException()};
+  functionBracedInitListTest({}, {RegularException()});
+}
Index: docs/clang-tidy/checks/misc-throw-keyword-missing.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-throw-keyword-missing.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - misc-throw-keyword-missing
+
+misc-throw-keyword-missing
+==========================
+
+This check warns about the potentially missing `throw` keyword. If a temporary object is created,
+but the object's type derives from (or the same as) a class that has 'EXCEPTION', 'Exception' or
+'exception' in its name, we can assume that the programmer's intention was to throw that object.
+
+Example:
+
+.. code-block:: c++
+  void f(int i) {
+    if(i < 0) {
+      // Exception is created but is not thrown
+      std::runtime_error("Unexpected argument");
+    }
+  }
+
+
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -143,6 +143,7 @@
    misc-suspicious-string-compare
    misc-swapped-arguments
    misc-throw-by-value-catch-by-reference
+   misc-throw-keyword-missing
    misc-unconventional-assign-operator
    misc-undelegated-constructor
    misc-uniqueptr-reset-release
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 `misc-throw-keyword-missing
+  <http://clang.llvm.org/extra/clang-tidy/checks/misc-throw-keyword-missing.html>`_ check
+
+  Warns if a ``throw`` keyword is potentialy missing before a temporary exception object.
+
 Improvements to include-fixer
 -----------------------------
 
Index: clang-tidy/misc/ThrowKeywordMissingCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/ThrowKeywordMissingCheck.h
@@ -0,0 +1,36 @@
+//===--- ThrowKeywordMissingCheck.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_THROWKEYWORDMISSINGCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_THROWKEYWORDMISSINGCHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Emits a warning about temporary objects whose type is (or is derived from) a
+/// class that has 'EXCEPTION', 'Exception' or 'exception' in its name.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-throw-keyword-missing.html
+class ThrowKeywordMissingCheck : public ClangTidyCheck {
+public:
+  ThrowKeywordMissingCheck(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_THROWKEYWORDMISSINGCHECK_H
Index: clang-tidy/misc/ThrowKeywordMissingCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/ThrowKeywordMissingCheck.cpp
@@ -0,0 +1,51 @@
+//===--- ThrowKeywordMissingCheck.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 "ThrowKeywordMissingCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void ThrowKeywordMissingCheck::registerMatchers(MatchFinder *Finder) {
+  // This is a C++ only checker.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  auto CtorInitializerList =
+      cxxConstructorDecl(hasAnyConstructorInitializer(anything()));
+
+  Finder->addMatcher(
+      expr(anyOf(cxxFunctionalCastExpr(), cxxBindTemporaryExpr(),
+                 cxxTemporaryObjectExpr()),
+           hasType(cxxRecordDecl(
+               isSameOrDerivedFrom(matchesName("[Ee]xception|EXCEPTION")))),
+           unless(anyOf(hasAncestor(stmt(
+                            anyOf(cxxThrowExpr(), callExpr(), returnStmt()))),
+                        hasAncestor(varDecl()),
+                        allOf(hasAncestor(cxxConstructorDecl(
+                                  hasAnyConstructorInitializer(anything()))),
+                              unless(hasAncestor(cxxCatchStmt()))))))
+          .bind("temporary-exception-not-thrown"),
+      this);
+}
+
+void ThrowKeywordMissingCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto TemporaryExpr =
+      Result.Nodes.getNodeAs<Expr>("temporary-exception-not-thrown");
+  diag(TemporaryExpr->getLocStart(), "exception created but is not thrown");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -33,6 +33,7 @@
 #include "SuspiciousStringCompareCheck.h"
 #include "SwappedArgumentsCheck.h"
 #include "ThrowByValueCatchByReferenceCheck.h"
+#include "ThrowKeywordMissingCheck.h"
 #include "UnconventionalAssignOperatorCheck.h"
 #include "UndelegatedConstructor.h"
 #include "UniqueptrResetReleaseCheck.h"
@@ -53,6 +54,8 @@
     CheckFactories.registerCheck<LambdaFunctionNameCheck>(
         "misc-lambda-function-name");
     CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
+    CheckFactories.registerCheck<ThrowKeywordMissingCheck>(
+        "misc-throw-keyword-missing");
     CheckFactories.registerCheck<UnconventionalAssignOperatorCheck>(
         "misc-unconventional-assign-operator");
     CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -4,6 +4,7 @@
   ForwardingReferenceOverloadCheck.cpp
   LambdaFunctionNameCheck.cpp
   MisplacedConstCheck.cpp
+  ThrowKeywordMissingCheck.cpp
   UnconventionalAssignOperatorCheck.cpp
   DefinitionsInHeadersCheck.cpp
   IncorrectRoundings.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to