Skip to content

Commit 47c2c2e

Browse files
committed
[clang-tidy] Fix bugprone-exception-escape not diagnosing throws in argument lists
1 parent a7f1910 commit 47c2c2e

File tree

3 files changed

+53
-12
lines changed

3 files changed

+53
-12
lines changed

clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -563,16 +563,6 @@ ExceptionAnalyzer::throwsException(const Stmt *St,
563563
}
564564
}
565565
Results.merge(Uncaught);
566-
} else if (const auto *Call = dyn_cast<CallExpr>(St)) {
567-
if (const FunctionDecl *Func = Call->getDirectCallee()) {
568-
ExceptionInfo Excs =
569-
throwsException(Func, Caught, CallStack, Call->getBeginLoc());
570-
Results.merge(Excs);
571-
}
572-
} else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
573-
ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught,
574-
CallStack, Construct->getBeginLoc());
575-
Results.merge(Excs);
576566
} else if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(St)) {
577567
ExceptionInfo Excs =
578568
throwsException(DefaultInit->getExpr(), Caught, CallStack);
@@ -605,6 +595,18 @@ ExceptionAnalyzer::throwsException(const Stmt *St,
605595
ExceptionInfo Excs = throwsException(Child, Caught, CallStack);
606596
Results.merge(Excs);
607597
}
598+
599+
if (const auto *Call = dyn_cast<CallExpr>(St)) {
600+
if (const FunctionDecl *Func = Call->getDirectCallee()) {
601+
ExceptionInfo Excs =
602+
throwsException(Func, Caught, CallStack, Call->getBeginLoc());
603+
Results.merge(Excs);
604+
}
605+
} else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
606+
ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught,
607+
CallStack, Construct->getBeginLoc());
608+
Results.merge(Excs);
609+
}
608610
}
609611
return Results;
610612
}

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ Changes in existing checks
260260
- Improved :doc:`bugprone-exception-escape
261261
<clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas:
262262
exceptions from captures are now diagnosed, exceptions in the bodies of
263-
lambdas that aren't actually invoked are not.
263+
lambdas that aren't actually invoked are not. Additionally, fixed an issue
264+
where the check wouldn't diagnose throws in arguments to functions or
265+
constructors.
264266

265267
- Improved :doc:`bugprone-infinite-loop
266268
<clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for

clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,11 +948,48 @@ const auto throw_in_noexcept_lambda = [] () noexcept { throw 42; };
948948
// CHECK-MESSAGES: :[[@LINE-1]]:39: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
949949
// CHECK-MESSAGES: :[[@LINE-2]]:56: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here
950950

951-
void thrower() {
951+
int thrower() {
952952
throw 42;
953953
}
954954

955955
const auto indirect_throw_in_noexcept_lambda = [] () noexcept { thrower(); };
956956
// CHECK-MESSAGES: :[[@LINE-1]]:48: warning: an exception may be thrown in function 'operator()' which should not throw exceptions
957957
// CHECK-MESSAGES: :[[@LINE-5]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here
958958
// CHECK-MESSAGES: :[[@LINE-3]]:65: note: frame #1: function 'operator()' calls function 'thrower' here
959+
960+
int f(int);
961+
void throw_in_function_arg() noexcept {
962+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_function_arg' which should not throw exceptions
963+
f(false ? 0 : throw 1);
964+
}
965+
// CHECK-MESSAGES: :[[@LINE-2]]:17: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_in_function_arg' here
966+
967+
void indirect_throw_in_function_arg() noexcept {
968+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_throw_in_function_arg' which should not throw exceptions
969+
f(thrower());
970+
}
971+
// CHECK-MESSAGES: :[[@LINE-19]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here
972+
// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #1: function 'indirect_throw_in_function_arg' calls function 'thrower' here
973+
974+
struct S {
975+
S(int) noexcept {}
976+
};
977+
978+
void throw_in_constructor_arg() noexcept {
979+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_in_constructor_arg' which should not throw exceptions
980+
S s(false ? 0 : throw 1);
981+
}
982+
// CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_in_constructor_arg' here
983+
984+
void indirect_throw_in_constructor_arg() noexcept {
985+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_throw_in_constructor_arg' which should not throw exceptions
986+
S s = thrower();
987+
}
988+
// CHECK-MESSAGES: :[[@LINE-36]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here
989+
// CHECK-MESSAGES: :[[@LINE-3]]:9: note: frame #1: function 'indirect_throw_in_constructor_arg' calls function 'thrower' here
990+
991+
void weird_throw_in_call_subexpression() noexcept {
992+
// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'weird_throw_in_call_subexpression' which should not throw exceptions
993+
(false ? []{} : throw 1)();
994+
}
995+
// CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #0: unhandled exception of type 'int' may be thrown in function 'weird_throw_in_call_subexpression' here

0 commit comments

Comments
 (0)