Skip to content

Commit 49d0961

Browse files
Extend bugprone-use-after-move check to handle std::optional::reset() and std::any::reset() similarly to smart pointers
1 parent a78861f commit 49d0961

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ void UseAfterMoveFinder::getUsesAndReinits(
242242
});
243243
}
244244

245-
bool isStandardSmartPointer(const ValueDecl *VD) {
245+
bool isStandardResettableOwner(const ValueDecl *VD) {
246246
const Type *TheType = VD->getType().getNonReferenceType().getTypePtrOrNull();
247247
if (!TheType)
248248
return false;
@@ -256,7 +256,8 @@ bool isStandardSmartPointer(const ValueDecl *VD) {
256256
return false;
257257

258258
StringRef Name = ID->getName();
259-
if (Name != "unique_ptr" && Name != "shared_ptr" && Name != "weak_ptr")
259+
if (Name != "unique_ptr" && Name != "shared_ptr" && Name != "weak_ptr" &&
260+
Name != "optional" && Name != "any")
260261
return false;
261262

262263
return RecordDecl->getDeclContext()->isStdNamespace();
@@ -279,7 +280,7 @@ void UseAfterMoveFinder::getDeclRefs(
279280
if (DeclRef && BlockMap->blockContainingStmt(DeclRef) == Block) {
280281
// Ignore uses of a standard smart pointer that don't dereference the
281282
// pointer.
282-
if (Operator || !isStandardSmartPointer(DeclRef->getDecl())) {
283+
if (Operator || !isStandardResettableOwner(DeclRef->getDecl())) {
283284
DeclRefs->insert(DeclRef);
284285
}
285286
}
@@ -315,9 +316,10 @@ void UseAfterMoveFinder::getReinits(
315316
"::std::unordered_map", "::std::unordered_multiset",
316317
"::std::unordered_multimap"))))));
317318

318-
auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
319-
recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
320-
"::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr"))))));
319+
auto StandardResettableOwnerTypeMatcher = hasType(
320+
hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl(
321+
hasAnyName("::std::unique_ptr", "::std::shared_ptr",
322+
"::std::weak_ptr", "::std::optional", "::std::any"))))));
321323

322324
// Matches different types of reinitialization.
323325
auto ReinitMatcher =
@@ -340,7 +342,7 @@ void UseAfterMoveFinder::getReinits(
340342
callee(cxxMethodDecl(hasAnyName("clear", "assign")))),
341343
// reset() on standard smart pointers.
342344
cxxMemberCallExpr(
343-
on(expr(DeclRefMatcher, StandardSmartPointerTypeMatcher)),
345+
on(expr(DeclRefMatcher, StandardResettableOwnerTypeMatcher)),
344346
callee(cxxMethodDecl(hasName("reset")))),
345347
// Methods that have the [[clang::reinitializes]] attribute.
346348
cxxMemberCallExpr(

clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ struct weak_ptr {
3333
bool expired() const;
3434
};
3535

36+
template <typename T>
37+
struct optional {
38+
optional();
39+
void reset();
40+
};
41+
42+
struct any {
43+
any();
44+
void reset();
45+
};
46+
3647
template <typename T1, typename T2>
3748
struct pair {};
3849

@@ -994,10 +1005,10 @@ void standardContainerAssignIsReinit() {
9941005
}
9951006
}
9961007

997-
// Resetting the standard smart pointer types using reset() is treated as a
1008+
// Resetting the standard smart owning types using reset() is treated as a
9981009
// re-initialization. (We don't test std::weak_ptr<> because it can't be
9991010
// dereferenced directly.)
1000-
void standardSmartPointerResetIsReinit() {
1011+
void resetIsReinit() {
10011012
{
10021013
std::unique_ptr<A> ptr;
10031014
std::move(ptr);
@@ -1010,6 +1021,20 @@ void standardSmartPointerResetIsReinit() {
10101021
ptr.reset(new A);
10111022
*ptr;
10121023
}
1024+
{
1025+
std::optional<A> opt;
1026+
std::move(opt);
1027+
opt.reset();
1028+
std::optional<A> opt2 = opt;
1029+
(void)opt2;
1030+
}
1031+
{
1032+
std::any a;
1033+
std::move(a);
1034+
a.reset();
1035+
std::any a2 = a;
1036+
(void)a2;
1037+
}
10131038
}
10141039

10151040
void reinitAnnotation() {

0 commit comments

Comments
 (0)