https://github.com/higher-performance updated https://github.com/llvm/llvm-project/pull/114255
>From ae601ed439b3a538f7976a52c47c386f2d9ef56f Mon Sep 17 00:00:00 2001 From: higher-performance <higher.performance.git...@gmail.com> Date: Wed, 30 Oct 2024 12:01:00 -0400 Subject: [PATCH] Extend bugprone-use-after-move check to handle std::optional::reset() and std::any::reset() similarly to smart pointers --- .../clang-tidy/bugprone/UseAfterMoveCheck.cpp | 9 +++--- clang-tools-extra/docs/ReleaseNotes.rst | 5 ++++ .../checks/bugprone/use-after-move.rst | 10 +++---- .../checkers/bugprone/use-after-move.cpp | 29 +++++++++++++++++-- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index 8f4b5e8092ddaa..960133159dbbf5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -315,9 +315,10 @@ void UseAfterMoveFinder::getReinits( "::std::unordered_map", "::std::unordered_multiset", "::std::unordered_multimap")))))); - auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType( - recordType(hasDeclaration(cxxRecordDecl(hasAnyName( - "::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr")))))); + auto StandardResettableOwnerTypeMatcher = hasType( + hasUnqualifiedDesugaredType(recordType(hasDeclaration(cxxRecordDecl( + hasAnyName("::std::unique_ptr", "::std::shared_ptr", + "::std::weak_ptr", "::std::optional", "::std::any")))))); // Matches different types of reinitialization. auto ReinitMatcher = @@ -340,7 +341,7 @@ void UseAfterMoveFinder::getReinits( callee(cxxMethodDecl(hasAnyName("clear", "assign")))), // reset() on standard smart pointers. cxxMemberCallExpr( - on(expr(DeclRefMatcher, StandardSmartPointerTypeMatcher)), + on(expr(DeclRefMatcher, StandardResettableOwnerTypeMatcher)), callee(cxxMethodDecl(hasName("reset")))), // Methods that have the [[clang::reinitializes]] attribute. cxxMemberCallExpr( diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index abcdcc25705bf5..943f87db0e2f96 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -186,6 +186,11 @@ Changes in existing checks <clang-tidy/checks/bugprone/unsafe-functions>` check to allow specifying additional functions to match. +- Improved :doc:`bugprone-use-after-move + <clang-tidy/checks/bugprone/use-after-move>` to avoid triggering on + ``reset()`` calls on moved-from ``std::optional`` and ``std::any`` objects, + similarly to smart pointers. + - Improved :doc:`cert-flp30-c <clang-tidy/checks/cert/flp30-c>` check to fix false positive that floating point variable is only used in increment expression. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst index 08bb5374bab1f4..6b70727c61d6de 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/use-after-move.rst @@ -196,10 +196,9 @@ Any occurrence of the moved variable that is not a reinitialization (see below) is considered to be a use. An exception to this are objects of type ``std::unique_ptr``, -``std::shared_ptr`` and ``std::weak_ptr``, which have defined move behavior -(objects of these classes are guaranteed to be empty after they have been moved -from). Therefore, an object of these classes will only be considered to be used -if it is dereferenced, i.e. if ``operator*``, ``operator->`` or ``operator[]`` +``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``. +An object of these classes will only be considered to be used if it is +dereferenced, i.e. if ``operator*``, ``operator->`` or ``operator[]`` (in the case of ``std::unique_ptr<T []>``) is called on it. If multiple uses occur after a move, only the first of these is flagged. @@ -222,7 +221,8 @@ The check considers a variable to be reinitialized in the following cases: ``unordered_multimap``. - ``reset()`` is called on the variable and the variable is of type - ``std::unique_ptr``, ``std::shared_ptr`` or ``std::weak_ptr``. + ``std::unique_ptr``, ``std::shared_ptr``, ``std::weak_ptr``, + ``std::optional``, or ``std::any``. - A member function marked with the ``[[clang::reinitializes]]`` attribute is called on the variable. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp index 6a4e3990e36dc5..49306e1e2107c1 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/use-after-move.cpp @@ -33,6 +33,17 @@ struct weak_ptr { bool expired() const; }; +template <typename T> +struct optional { + optional(); + void reset(); +}; + +struct any { + any(); + void reset(); +}; + template <typename T1, typename T2> struct pair {}; @@ -994,10 +1005,10 @@ void standardContainerAssignIsReinit() { } } -// Resetting the standard smart pointer types using reset() is treated as a +// Resetting the standard smart owning types using reset() is treated as a // re-initialization. (We don't test std::weak_ptr<> because it can't be // dereferenced directly.) -void standardSmartPointerResetIsReinit() { +void resetIsReinit() { { std::unique_ptr<A> ptr; std::move(ptr); @@ -1010,6 +1021,20 @@ void standardSmartPointerResetIsReinit() { ptr.reset(new A); *ptr; } + { + std::optional<A> opt; + std::move(opt); + opt.reset(); + std::optional<A> opt2 = opt; + (void)opt2; + } + { + std::any a; + std::move(a); + a.reset(); + std::any a2 = a; + (void)a2; + } } void reinitAnnotation() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits