[clang-tidy] Recognize [[clang::reinitializes]] attribute in bugprone-use-after-move
Summary: This allows member functions to be marked as reinitializing the object. After a moved-from object has been reinitialized, the check will no longer consider it to be in an indeterminate state. The patch that adds the attribute itself is at https://reviews.llvm.org/D49911 Reviewers: ilya-biryukov, aaron.ballman, alexfh, hokein, rsmith Reviewed By: aaron.ballman Subscribers: dblaikie, xazax.hun, cfe-commits Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D49910 llvm-svn: 339571
This commit is contained in:
parent
dc3e4c6d95
commit
e47a631d1c
|
@ -308,6 +308,10 @@ void UseAfterMoveFinder::getReinits(
|
|||
cxxMemberCallExpr(
|
||||
on(allOf(DeclRefMatcher, StandardSmartPointerTypeMatcher)),
|
||||
callee(cxxMethodDecl(hasName("reset")))),
|
||||
// Methods that have the [[clang::reinitializes]] attribute.
|
||||
cxxMemberCallExpr(
|
||||
on(DeclRefMatcher),
|
||||
callee(cxxMethodDecl(hasAttr(clang::attr::Reinitializes)))),
|
||||
// Passing variable to a function as a non-const pointer.
|
||||
callExpr(forEachArgumentWithParam(
|
||||
unaryOperator(hasOperatorName("&"),
|
||||
|
|
|
@ -178,6 +178,9 @@ The check considers a variable to be reinitialized in the following cases:
|
|||
- ``reset()`` is called on the variable and the variable is of type
|
||||
``std::unique_ptr``, ``std::shared_ptr`` or ``std::weak_ptr``.
|
||||
|
||||
- A member function marked with the ``[[clang::reinitializes]]`` attribute is
|
||||
called on the variable.
|
||||
|
||||
If the variable in question is a struct and an individual member variable of
|
||||
that struct is written to, the check does not consider this to be a
|
||||
reinitialization -- even if, eventually, all member variables of the struct are
|
||||
|
|
|
@ -107,6 +107,15 @@ public:
|
|||
int i;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class AnnotatedContainer {
|
||||
public:
|
||||
AnnotatedContainer();
|
||||
|
||||
void foo() const;
|
||||
[[clang::reinitializes]] void clear();
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// General tests.
|
||||
|
||||
|
@ -898,6 +907,32 @@ void standardSmartPointerResetIsReinit() {
|
|||
}
|
||||
}
|
||||
|
||||
void reinitAnnotation() {
|
||||
{
|
||||
AnnotatedContainer<int> obj;
|
||||
std::move(obj);
|
||||
obj.foo();
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'obj' used after it was
|
||||
// CHECK-MESSAGES: [[@LINE-3]]:5: note: move occurred here
|
||||
}
|
||||
{
|
||||
AnnotatedContainer<int> obj;
|
||||
std::move(obj);
|
||||
obj.clear();
|
||||
obj.foo();
|
||||
}
|
||||
{
|
||||
// Calling clear() on a different object to the one that was moved is not
|
||||
// considered a reinitialization.
|
||||
AnnotatedContainer<int> obj1, obj2;
|
||||
std::move(obj1);
|
||||
obj2.clear();
|
||||
obj1.foo();
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:5: warning: 'obj1' used after it was
|
||||
// CHECK-MESSAGES: [[@LINE-4]]:5: note: move occurred here
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Tests related to order of evaluation within expressions
|
||||
|
||||
|
|
Loading…
Reference in New Issue