]> granicus.if.org Git - clang/commitdiff
Do not give a -Wredundant-move warning when removing the move will result in an
authorRichard Trieu <rtrieu@google.com>
Tue, 28 Jul 2015 19:06:16 +0000 (19:06 +0000)
committerRichard Trieu <rtrieu@google.com>
Tue, 28 Jul 2015 19:06:16 +0000 (19:06 +0000)
error.

If the object being moved has a move constructor and a deleted copy constructor,
std::move is required, otherwise Clang will give a deleted constructor error.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@243463 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaInit.cpp
test/SemaCXX/warn-redundant-move.cpp

index ed5696358481783c7d9fa28583f611aec7fe4935..fd067775aca3a38cb4f98a63f7b1bb96bc7f1c8a 100644 (file)
@@ -5983,9 +5983,19 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
     if (!VD || !VD->hasLocalStorage())
       return;
 
-    if (!VD->getType()->isRecordType())
+    QualType SourceType = VD->getType();
+    if (!SourceType->isRecordType())
       return;
 
+    if (!S.Context.hasSameUnqualifiedType(DestType, SourceType)) {
+      if (CXXRecordDecl *RD = SourceType->getAsCXXRecordDecl()) {
+        for (auto* Construct : RD->ctors()) {
+          if (Construct->isCopyConstructor() && Construct->isDeleted())
+            return;
+        }
+      }
+    }
+
     // If we're returning a function parameter, copy elision
     // is not possible.
     if (isa<ParmVarDecl>(VD))
index d5df3a6428c2556d94f1f8d708f1dee891275e99..06f9c58bae60290d5e1d42b59df2d12a46aa8765 100644 (file)
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
 
 // definitions for std::move
 namespace std {
@@ -102,3 +102,39 @@ D test5(D d) {
   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
 }
+
+// No more fix-its past here.
+// CHECK-NOT: fix-it
+
+// A deleted copy constructor will prevent moves without std::move
+struct E {
+  E(E &&e);
+  E(const E &e) = delete;
+  // expected-note@-1{{deleted here}}
+};
+
+struct F {
+  F(E);
+  // expected-note@-1{{passing argument to parameter here}}
+};
+
+F test6(E e) {
+  return e;
+  // expected-error@-1{{call to deleted constructor of 'E'}}
+  return std::move(e);
+}
+
+struct G {
+  G(G &&g);
+  // expected-note@-1{{copy constructor is implicitly deleted because 'G' has a user-declared move constructor}}
+};
+
+struct H {
+  H(G);
+  // expected-note@-1{{passing argument to parameter here}}
+};
+
+H test6(G g) {
+  return g;  // expected-error{{call to implicitly-deleted copy constructor of 'G'}}
+  return std::move(g);
+}