[clang-tools-extra] d3b188a - [clang-tidy] Include constructor initializers in `bugprone-exception-escape` check

Fabian Wolff via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 20 16:00:51 PST 2022


Author: Fabian Wolff
Date: 2022-01-21T00:53:57+01:00
New Revision: d3b188a2d72f9c398e4b1a36d23888c4ac783e9f

URL: https://github.com/llvm/llvm-project/commit/d3b188a2d72f9c398e4b1a36d23888c4ac783e9f
DIFF: https://github.com/llvm/llvm-project/commit/d3b188a2d72f9c398e4b1a36d23888c4ac783e9f.diff

LOG: [clang-tidy] Include constructor initializers in `bugprone-exception-escape` check

Fixes PR#52435.

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D113507

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
    clang-tools-extra/test/clang-tidy/checkers/bugprone-exception-escape.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index 97895115a7d5c..1f22c1d936561 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -119,6 +119,16 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
     CallStack.insert(Func);
     ExceptionInfo Result =
         throwsException(Body, ExceptionInfo::Throwables(), CallStack);
+
+    // For a constructor, we also have to check the initializers.
+    if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(Func)) {
+      for (const CXXCtorInitializer *Init : Ctor->inits()) {
+        ExceptionInfo Excs = throwsException(
+            Init->getInit(), ExceptionInfo::Throwables(), CallStack);
+        Result.merge(Excs);
+      }
+    }
+
     CallStack.erase(Func);
     return Result;
   }
@@ -195,6 +205,14 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
       ExceptionInfo Excs = throwsException(Func, CallStack);
       Results.merge(Excs);
     }
+  } else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
+    ExceptionInfo Excs =
+        throwsException(Construct->getConstructor(), CallStack);
+    Results.merge(Excs);
+  } else if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(St)) {
+    ExceptionInfo Excs =
+        throwsException(DefaultInit->getExpr(), Caught, CallStack);
+    Results.merge(Excs);
   } else {
     for (const Stmt *Child : St->children()) {
       ExceptionInfo Excs = throwsException(Child, Caught, CallStack);

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone-exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone-exception-escape.cpp
index ebb44f84f67cc..769064d74adc5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone-exception-escape.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone-exception-escape.cpp
@@ -288,6 +288,49 @@ int indirectly_recursive(int n) noexcept {
   return recursion_helper(n);
 }
 
+struct super_throws {
+  super_throws() noexcept(false) { throw 42; }
+};
+
+struct sub_throws : super_throws {
+  sub_throws() noexcept : super_throws() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions
+};
+
+struct super_throws_again {
+  super_throws_again() throw(int);
+};
+
+struct sub_throws_again : super_throws_again {
+  sub_throws_again() noexcept : super_throws_again() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws_again' which should not throw exceptions
+};
+
+struct init_member_throws {
+  super_throws s;
+
+  init_member_throws() noexcept : s() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions
+};
+
+struct implicit_init_member_throws {
+  super_throws s;
+
+  implicit_init_member_throws() noexcept {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions
+};
+
+struct init {
+  explicit init(int, int) noexcept(false) { throw 42; }
+};
+
+struct in_class_init_throws {
+  init i{1, 2};
+
+  in_class_init_throws() noexcept {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions
+};
+
 int main() {
   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
   throw 1;


        


More information about the cfe-commits mailing list