Index: clang-tidy/bugprone/UseAfterMoveCheck.cpp =================================================================== --- clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -308,6 +308,10 @@ 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("&"), Index: docs/clang-tidy/checks/bugprone-use-after-move.rst =================================================================== --- docs/clang-tidy/checks/bugprone-use-after-move.rst +++ docs/clang-tidy/checks/bugprone-use-after-move.rst @@ -178,6 +178,9 @@ - ``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 Index: test/clang-tidy/bugprone-use-after-move.cpp =================================================================== --- test/clang-tidy/bugprone-use-after-move.cpp +++ test/clang-tidy/bugprone-use-after-move.cpp @@ -107,6 +107,15 @@ int i; }; +template +class AnnotatedContainer { +public: + AnnotatedContainer(); + + void foo() const; + [[clang::reinitializes]] void clear(); +}; + //////////////////////////////////////////////////////////////////////////////// // General tests. @@ -898,6 +907,32 @@ } } +void reinitAnnotation() { + { + AnnotatedContainer 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 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 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