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

- Merge branch 'master' into fix_exception


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D48714

Files:
  clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
  test/clang-tidy/hicpp-exception-baseclass.cpp

Index: test/clang-tidy/hicpp-exception-baseclass.cpp
===================================================================
--- test/clang-tidy/hicpp-exception-baseclass.cpp
+++ test/clang-tidy/hicpp-exception-baseclass.cpp
@@ -2,6 +2,7 @@
 
 namespace std {
 class exception {};
+class invalid_argument : public exception {};
 } // namespace std
 
 class derived_exception : public std::exception {};
@@ -35,6 +36,7 @@
 
   try {
     throw non_derived_exception();
+
     // CHECK-NOTES: [[@LINE-1]]:11: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
     // CHECK-NOTES: 9:1: note: type defined here
   } catch (non_derived_exception &e) {
@@ -50,24 +52,24 @@
   try {
     throw bad_inheritance();
     // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
-    // CHECK MESSAGES: 10:1: note: type defined here
+    // CHECK MESSAGES: 11:1: note: type defined here
     throw no_good_inheritance();
     // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
-    // CHECK MESSAGES: 11:1: note: type defined here
+    // CHECK MESSAGES: 12:1: note: type defined here
     throw really_creative();
     // CHECK MESSAGES: [[@LINE-1]]:11: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
-    // CHECK MESSAGES: 12:1: note: type defined here
+    // CHECK MESSAGES: 13:1: note: type defined here
   } catch (...) {
   }
   throw bad_inheritance();
   // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'bad_inheritance' is not derived from 'std::exception'
-  // CHECK MESSAGES: 10:1: note: type defined here
+  // CHECK MESSAGES: 11:1: note: type defined here
   throw no_good_inheritance();
   // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'no_good_inheritance' is not derived from 'std::exception'
-  // CHECK MESSAGES: 11:1: note: type defined here
+  // CHECK MESSAGES: 12:1: note: type defined here
   throw really_creative();
   // CHECK MESSAGES: [[@LINE-1]]:9: warning: throwing an exception whose type 'really_creative' is not derived from 'std::exception'
-  // CHECK MESSAGES: 12:1: note: type defined here
+  // CHECK MESSAGES: 13:1: note: type defined here
 #endif
 }
 
@@ -91,7 +93,7 @@
   throw deep_hierarchy(); // Ok
 
   try {
-    throw terrible_idea();     // Ok, but multiple inheritance isn't clean
+    throw terrible_idea();      // Ok, but multiple inheritance isn't clean
   } catch (std::exception &e) { // Can be caught as std::exception, even with multiple inheritance
   }
   throw terrible_idea(); // Ok, but multiple inheritance
@@ -128,7 +130,7 @@
   // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
   THROW_EXCEPTION(non_derived_exception);
   // CHECK MESSAGES: [[@LINE-1]]:3: warning: throwing an exception whose type 'non_derived_exception' is not derived from 'std::exception'
-  // CHECK MESSAGES: 9:1: note: type defined here
+  // CHECK MESSAGES: 10:1: note: type defined here
   THROW_EXCEPTION(std::exception);    // Ok
   THROW_EXCEPTION(derived_exception); // Ok
   THROW_EXCEPTION(deep_hierarchy);    // Ok
@@ -180,3 +182,21 @@
   // CHECK-NOTES: 169:1: note: type defined here
   throw UsingGood(); // Ok
 }
+
+// Fix PR37913
+struct invalid_argument_maker {
+  ::std::invalid_argument operator()() const;
+};
+struct int_maker {
+  int operator()() const;
+};
+template <typename T>
+void templated_thrower() { throw T{}(); }
+// CHECK-MESSAGES: [[@LINE-1]]:34: warning: throwing an exception whose type 'int' is not derived from 'std::exception'
+
+void exception_created_with_function() {
+  templated_thrower<invalid_argument_maker>();
+  templated_thrower<int_maker>();
+
+  throw invalid_argument_maker{}();
+}
Index: clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
===================================================================
--- clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
+++ clang-tidy/hicpp/ExceptionBaseclassCheck.cpp
@@ -22,24 +22,39 @@
     return;
 
   Finder->addMatcher(
-      cxxThrowExpr(allOf(has(expr(unless(hasType(qualType(hasCanonicalType(
-                             hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom(
-                                 hasName("std::exception")))))))))),
-                         has(expr(unless(cxxUnresolvedConstructExpr()))),
-                         eachOf(has(expr(hasType(namedDecl().bind("decl")))),
-                                anything())))
+      cxxThrowExpr(
+          allOf(
+              has(expr(unless(hasType(
+                  qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
+                      isSameOrDerivedFrom(hasName("std::exception")))))))))),
+              anyOf(has(expr(hasType(
+                        substTemplateTypeParmType().bind("templ_type")))),
+                    anything()),
+              has(expr(allOf(
+                  unless(cxxUnresolvedConstructExpr()),
+                  unless(callExpr(callee(cxxUnresolvedConstructExpr())))))),
+              eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything())))
           .bind("bad_throw"),
       this);
 }
 
 void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) {
   const auto *BadThrow = Result.Nodes.getNodeAs<CXXThrowExpr>("bad_throw");
+  assert(BadThrow && "Did not match the throw expression");
 
   diag(BadThrow->getSubExpr()->getBeginLoc(), "throwing an exception whose "
                                               "type %0 is not derived from "
                                               "'std::exception'")
       << BadThrow->getSubExpr()->getType() << BadThrow->getSourceRange();
 
+  const auto *Template =
+      Result.Nodes.getNodeAs<SubstTemplateTypeParmType>("templ_type");
+  if (Template) {
+    diag(BadThrow->getSubExpr()->getLocStart(),
+         "type %0 is a template instantiation of %1", DiagnosticIDs::Note)
+        << BadThrow->getSubExpr()->getType()
+        << Template->getReplacedParameter()->getDecl();
+  }
   const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl");
   if (TypeDecl != nullptr)
     diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to