[clang-tidy][#51939] Exempt placement-new expressions from 'bugprone-throw-keyword-missing'

The purpose of this checker is to flag a missing throw keyword, and does so by checking for the construction of an exception class that is then unused.
This works great except that placement new expressions are also flagged as those lead to the construction of an object as well, even though they are not temporary (as that is dependent on the storage).
This patch fixes the issue by exempting the match if it is within a placement-new.

Fixes https://github.com/llvm/llvm-project/issues/51939

Differential Revision: https://reviews.llvm.org/D115576
This commit is contained in:
Markus Böck 2021-12-15 16:59:04 +01:00
parent e0669931af
commit b7d55771ce
3 changed files with 22 additions and 5 deletions

View File

@ -24,11 +24,13 @@ void ThrowKeywordMissingCheck::registerMatchers(MatchFinder *Finder) {
cxxConstructExpr(
hasType(cxxRecordDecl(
isSameOrDerivedFrom(matchesName("[Ee]xception|EXCEPTION")))),
unless(anyOf(hasAncestor(stmt(
anyOf(cxxThrowExpr(), callExpr(), returnStmt()))),
hasAncestor(decl(anyOf(varDecl(), fieldDecl()))),
allOf(hasAncestor(CtorInitializerList),
unless(hasAncestor(cxxCatchStmt()))))))
unless(anyOf(
hasAncestor(
stmt(anyOf(cxxThrowExpr(), callExpr(), returnStmt()))),
hasAncestor(decl(anyOf(varDecl(), fieldDecl()))),
hasAncestor(expr(cxxNewExpr(hasAnyPlacementArg(anything())))),
allOf(hasAncestor(CtorInitializerList),
unless(hasAncestor(cxxCatchStmt()))))))
.bind("temporary-exception-not-thrown"),
this);
}

View File

@ -148,6 +148,10 @@ Changes in existing checks
- Fixed a false positive in :doc:`fuchsia-trailing-return
<clang-tidy/checks/fuchsia-trailing-return>` for C++17 deduction guides.
- Fixed a false positive in :doc:`bugprone-throw-keyword-missing
<clang-tidy/checks/bugprone-throw-keyword-missing>` when creating an exception object
using placement new
Removed checks
^^^^^^^^^^^^^^

View File

@ -175,3 +175,14 @@ struct ExceptionRAII {
void exceptionRAIITest() {
ExceptionRAII E;
}
namespace std {
typedef decltype(sizeof(void*)) size_t;
}
void* operator new(std::size_t, void*);
void placeMentNewTest() {
alignas(RegularException) unsigned char expr[sizeof(RegularException)];
new (expr) RegularException{};
}