https://github.com/higher-performance updated https://github.com/llvm/llvm-project/pull/114255
>From 2835f0eae90061d390d1b011b6a98bf43be1a0c6 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 | 15 +++++--- .../checkers/bugprone/use-after-move.cpp | 37 ++++++++++++++++++- 4 files changed, 54 insertions(+), 12 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 442fb7180555ea..ace1c037aba0c4 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -190,6 +190,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..965fc2d3c29e24 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,11 +196,13 @@ 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[]`` -(in the case of ``std::unique_ptr<T []>``) is called on it. +``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``. +An exception to this are objects of type ``std::unique_ptr``, +``std::shared_ptr``, ``std::weak_ptr``, ``std::optional``, and ``std::any``, which +can be reinitialized via ``reset``. For smart pointers specifically, the +moved-from objects have a well-defined state of being ``nullptr``s, and only +``operator*``, ``operator->`` and ``operator[]`` are considered bad accesses as +they would be dereferencing a ``nullptr``. If multiple uses occur after a move, only the first of these is flagged. @@ -222,7 +224,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..c99bd0e4440858 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,19 @@ struct weak_ptr { bool expired() const; }; +template <typename T> +struct optional { + optional(); + T& operator*(); + const T& operator*() const; + void reset(); +}; + +struct any { + any(); + void reset(); +}; + template <typename T1, typename T2> struct pair {}; @@ -994,10 +1007,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 +1023,26 @@ void standardSmartPointerResetIsReinit() { ptr.reset(new A); *ptr; } + { + std::optional<A> opt; + std::move(opt); + opt.reset(); + std::optional<A> opt2 = opt; + (void)opt2; + } + { + std::optional<A> opt; + std::move(opt); + A val = *opt; + (void)val; + } + { + 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