From: Richard Trieu Date: Tue, 28 Jul 2015 19:06:16 +0000 (+0000) Subject: Do not give a -Wredundant-move warning when removing the move will result in an X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ea88b600f597e6dbbaa1d6d5db9ab5e122cac5a;p=clang Do not give a -Wredundant-move warning when removing the move will result in an 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 --- diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index ed56963584..fd067775ac 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -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(VD)) diff --git a/test/SemaCXX/warn-redundant-move.cpp b/test/SemaCXX/warn-redundant-move.cpp index d5df3a6428..06f9c58bae 100644 --- a/test/SemaCXX/warn-redundant-move.cpp +++ b/test/SemaCXX/warn-redundant-move.cpp @@ -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); +}