-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[clang-tidy] Add bugprone-move-shared-pointer-contents check. #67467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed a problem with your matcher, so I reviewed the rest of it while I was at it.
The problem is that you do not consider a type-dependent std::shared_ptr<T>
and the following test case fails:
template <typename T>
void dependentType() {
std::shared_ptr<T> p;
T y = std::move(*p);
// CHECK-FIXES: *std::move(p)
}
// CHECK-MESSAGES: :[[@LINE-3]]:11: warning: don't move the contents out of a shared pointer, as other accessors expect them to remain in a determinate state [bugprone-move-shared-pointer-contents]
In this case, your callee
is no longer a functionDecl
but an unresolvedLookupExpr
and the *
operator is a UnaryOperator
instead of a cxxOperatorCallExpr
.
Otherwise, looks like a good check to have.
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.h
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/move-shared-pointer-contents.rst
Outdated
Show resolved
Hide resolved
✅ With the latest revision this PR passed the C/C++ code formatter. |
I'm really struggling with this, and also with getting the git history right after three months oops. The UnaryOperator is matchable without much difficulty, but there appears to be no way to introspect the UnresolvedLookupExpr to ensure I'm matching calls to |
Try searching for llvm-project/clang-tools-extra/clang-tidy/cppcoreguidelines/RvalueReferenceParamNotMovedCheck.cpp Lines 46 to 47 in 2b7191c
And there is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few fixes needed, but looks you are on good road.
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/test/clang-tidy/checkers/bugprone/move-shared-pointer-contents.cpp
Outdated
Show resolved
Hide resolved
Try searching for
Thanks, this was super helpful and exactly what I was looking for! I think the missing insight was that I could go from the lookup -> decls. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few issues with unaryOperator
left, after that will be fixed, it would look fine.
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
Not sure how to squash properly; I tried rebasing but all the commits on the main branch snuck in to the history and I'm quite new to git. If it would be preferred I can store this off as a patch and open up a new PR. Sorry for all the hassle with the merges! |
You need to do interactive rebase:
|
97323d0
to
ab88688
Compare
A coworker was able to help me get this working by rebasing against upstream, so I think we're good to go at this point. Thanks for all the feedback! |
clang-tools-extra/docs/clang-tidy/checks/bugprone/move-shared-pointer-contents.rst
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.h
Outdated
Show resolved
Hide resolved
clang-tools-extra/docs/clang-tidy/checks/bugprone/move-shared-pointer-contents.rst
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
I'm not experienced enough in clang-tidy internals, but I believe it will not be a serious challenge to check for having I suppose everybody agree that this snippet
..is better than that one:
|
@pizzud, you wish to continue work on this PR? 21th release of LLVM would be in late July, we have time to prepare and merge this check before the release. Also, It's okay to not cover all cases in the first iteration, some improvements can be added in later patches. Windows build is failing most likely to absent of "-fno-delayed-template-parsing" flag in test command, look for it in other tests for reference. |
@denzor2000 I agree it's better and technically possible within clang-tidy, but I am not sure it's simple to do. I'd like to get this in as-is. @vbvictor |
I agree that modelling |
clang-tools-extra/docs/clang-tidy/checks/bugprone/move-shared-pointer-contents.rst
Show resolved
Hide resolved
Please ping me when you're done working and want to test CI build |
…pointer-contents.rst Co-authored-by: EugeneZelenko <eugene.zelenko@gmail.com>
…s and provides limited additional coverage
Give it a go? |
} | ||
} | ||
|
||
if (Call == nullptr && !Call->getBeginLoc().isValid()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be Call != nullptr
or simply Call &&
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither. It should be ||
instead of &&
. The somewhat scary (but unsurprising part since I'm not sure how you would actually get here) is that all the unit tests passed either way.
|
||
if (Call == nullptr && !Call->getBeginLoc().isValid()) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using braces for single if-stmt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -148,6 +148,12 @@ New checks | |||
Finds potentially erroneous calls to ``reset`` method on smart pointers when | |||
the pointee type also has a ``reset`` method. | |||
|
|||
- New :doc:`bugprone-move-shared-pointer-contents |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please place in alphabetical order by check name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please run clang-tidy over your file and fix the errors, clangd can detect them, too.
A semicolon-separated list of class names that should be treated as | ||
shared pointers. Classes are resolved through aliases, so any alias | ||
to the defined classes will be considered. Default is | ||
`::std::shared_ptr;::boost::shared_pointer`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Boost has ::boost::shared_ptr
, not ::boost::shared_pointer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, done. Fixed in the actual checker as well.
#include "../ClangTidyCheck.h" | ||
#include "../utils/Matchers.h" | ||
#include "../utils/OptionsUtils.h" | ||
#include "clang/AST/ASTContext.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused include?
#include "clang/AST/ASTContext.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I played with matchers a bit, one diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
index 4d5c25bf9f27..ab5e13fbb9cc 100644
--- a/clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
@@ -70,12 +70,11 @@ void MoveSharedPointerContentsCheck::registerMatchers(MatchFinder *Finder) {
hasArgument(
0, unaryOperator(
hasOperatorName("*"),
- hasUnaryOperand(allOf(
- hasDescendant(declRefExpr(hasType(qualType(
- isSharedPointer(matchers::matchesAnyListedName(
- SharedPointerClasses)))))),
- cxxMemberCallExpr(
- callee(cxxMethodDecl(hasName("get")))))))))
+ hasUnaryOperand(cxxMemberCallExpr(
+ callee(cxxMethodDecl(hasName("get"))),
+ on(hasType(qualType(isSharedPointer(
+ matchers::matchesAnyListedName(
+ SharedPointerClasses))))))))))
.bind("get_call"))); All the tests seem to pass on ubuntu, couldn't test on windows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I got the clang-tidy issues sorted out.
A semicolon-separated list of class names that should be treated as | ||
shared pointers. Classes are resolved through aliases, so any alias | ||
to the defined classes will be considered. Default is | ||
`::std::shared_ptr;::boost::shared_pointer`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, done. Fixed in the actual checker as well.
#include "../ClangTidyCheck.h" | ||
#include "../utils/Matchers.h" | ||
#include "../utils/OptionsUtils.h" | ||
#include "clang/AST/ASTContext.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also try to eliminate second hasDescendant(declRefExpr())
in similar way if possible. I'd try to look at it this week too.
I suppose it's the only issue to be resolved before merge.
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
clang-tools-extra/clang-tidy/bugprone/MoveSharedPointerContentsCheck.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll give the matcher simplification a shot and see how it goes; I have a very short working week this week so I'm unlikely to make much progress.
This check detects moves of the contents of a shared pointer rather than the pointer itself. Other code with a reference to the shared pointer is probably not expecting the move.
The set of shared pointer classes is configurable via options to allow individual projects to cover additional types.