summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Bohme <mboehme@google.com>2017-03-08 12:34:51 +0000
committerMartin Bohme <mboehme@google.com>2017-03-08 12:34:51 +0000
commit96d29e5761fa84a253b788cde01a165eb664546f (patch)
tree7c6728b053b5acf09ac40ec3579622e4fe249c25
parent34120d67430a107a5ff79c3bac61f690dfee5509 (diff)
downloadbcm5719-llvm-96d29e5761fa84a253b788cde01a165eb664546f.tar.gz
bcm5719-llvm-96d29e5761fa84a253b788cde01a165eb664546f.zip
[clang-tidy] misc-use-after-move: Fix failing assertion
Summary: I've added a test case that (without the fix) triggers the assertion, which happens when a move happens in an implicitly called conversion operator. This patch also fixes nondeterministic behavior in the source code location reported for the move when the move is constained in an init list; this was causing buildbot failures in the previous attempt to submit this patch (see D30569 and rL297004). Reviewers: alexfh Reviewed By: alexfh Subscribers: Eugene.Zelenko, JDevlieghere, cfe-commits Differential Revision: https://reviews.llvm.org/D30650 llvm-svn: 297272
-rw-r--r--clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp9
-rw-r--r--clang-tools-extra/test/clang-tidy/misc-use-after-move.cpp17
2 files changed, 24 insertions, 2 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp
index 471b7506375..842aa5b3f72 100644
--- a/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp
@@ -384,6 +384,13 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
// the direct ancestor of the std::move() that isn't one of the node
// types ignored by ignoringParenImpCasts().
stmt(forEach(expr(ignoringParenImpCasts(CallMoveMatcher))),
+ // Don't allow an InitListExpr to be the moving call. An InitListExpr
+ // has both a syntactic and a semantic form, and the parent-child
+ // relationships are different between the two. This could cause an
+ // InitListExpr to be analyzed as the moving call in addition to the
+ // Expr that we actually want, resulting in two diagnostics with
+ // different code locations for the same move.
+ unless(initListExpr()),
unless(expr(ignoringParenImpCasts(equalsBoundNode("call-move")))))
.bind("moving-call"),
this);
@@ -398,7 +405,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
const auto *MovingCall = Result.Nodes.getNodeAs<Expr>("moving-call");
const auto *Arg = Result.Nodes.getNodeAs<DeclRefExpr>("arg");
- if (!MovingCall)
+ if (!MovingCall || !MovingCall->getExprLoc().isValid())
MovingCall = CallMove;
Stmt *FunctionBody = nullptr;
diff --git a/clang-tools-extra/test/clang-tidy/misc-use-after-move.cpp b/clang-tools-extra/test/clang-tidy/misc-use-after-move.cpp
index 92eb1239496..aac901c7690 100644
--- a/clang-tools-extra/test/clang-tidy/misc-use-after-move.cpp
+++ b/clang-tools-extra/test/clang-tidy/misc-use-after-move.cpp
@@ -282,7 +282,7 @@ void moveInInitList() {
S s{std::move(a)};
a.foo();
// CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'a' used after it was moved
- // CHECK-MESSAGES: [[@LINE-3]]:6: note: move occurred here
+ // CHECK-MESSAGES: [[@LINE-3]]:7: note: move occurred here
}
void lambdas() {
@@ -397,6 +397,21 @@ void movedTypeIsDependentType() {
}
template void movedTypeIsDependentType<A>();
+// We handle the case correctly where the move consists of an implicit call
+// to a conversion operator.
+void implicitConversionOperator() {
+ struct Convertible {
+ operator A() && { return A(); }
+ };
+ void takeA(A a);
+
+ Convertible convertible;
+ takeA(std::move(convertible));
+ convertible;
+ // CHECK-MESSAGES: [[@LINE-1]]:3: warning: 'convertible' used after it was moved
+ // CHECK-MESSAGES: [[@LINE-3]]:9: note: move occurred here
+}
+
// Using decltype on an expression is not a use.
void decltypeIsNotUse() {
A a;
OpenPOWER on IntegriCloud