1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s 2*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s 3*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -ast-dump | FileCheck %s --check-prefix=CHECK-AST 4*67e74705SXin Li 5*67e74705SXin Li // definitions for std::move 6*67e74705SXin Li namespace std { 7*67e74705SXin Li inline namespace foo { 8*67e74705SXin Li template <class T> struct remove_reference { typedef T type; }; 9*67e74705SXin Li template <class T> struct remove_reference<T&> { typedef T type; }; 10*67e74705SXin Li template <class T> struct remove_reference<T&&> { typedef T type; }; 11*67e74705SXin Li 12*67e74705SXin Li template <class T> typename remove_reference<T>::type &&move(T &&t); 13*67e74705SXin Li } 14*67e74705SXin Li } 15*67e74705SXin Li 16*67e74705SXin Li // test1 and test2 should not warn until after implementation of DR1579. 17*67e74705SXin Li struct A {}; 18*67e74705SXin Li struct B : public A {}; 19*67e74705SXin Li test1(B b1)20*67e74705SXin LiA test1(B b1) { 21*67e74705SXin Li B b2; 22*67e74705SXin Li return b1; 23*67e74705SXin Li return b2; 24*67e74705SXin Li return std::move(b1); 25*67e74705SXin Li return std::move(b2); 26*67e74705SXin Li } 27*67e74705SXin Li 28*67e74705SXin Li struct C { CC29*67e74705SXin Li C() {} CC30*67e74705SXin Li C(A) {} 31*67e74705SXin Li }; 32*67e74705SXin Li test2(A a1,B b1)33*67e74705SXin LiC test2(A a1, B b1) { 34*67e74705SXin Li A a2; 35*67e74705SXin Li B b2; 36*67e74705SXin Li 37*67e74705SXin Li return a1; 38*67e74705SXin Li return a2; 39*67e74705SXin Li return b1; 40*67e74705SXin Li return b2; 41*67e74705SXin Li 42*67e74705SXin Li return std::move(a1); 43*67e74705SXin Li return std::move(a2); 44*67e74705SXin Li return std::move(b1); 45*67e74705SXin Li return std::move(b2); 46*67e74705SXin Li } 47*67e74705SXin Li 48*67e74705SXin Li // Copy of tests above with types changed to reference types. test3(B & b1)49*67e74705SXin LiA test3(B& b1) { 50*67e74705SXin Li B& b2 = b1; 51*67e74705SXin Li return b1; 52*67e74705SXin Li return b2; 53*67e74705SXin Li return std::move(b1); 54*67e74705SXin Li return std::move(b2); 55*67e74705SXin Li } 56*67e74705SXin Li test4(A & a1,B & b1)57*67e74705SXin LiC test4(A& a1, B& b1) { 58*67e74705SXin Li A& a2 = a1; 59*67e74705SXin Li B& b2 = b1; 60*67e74705SXin Li 61*67e74705SXin Li return a1; 62*67e74705SXin Li return a2; 63*67e74705SXin Li return b1; 64*67e74705SXin Li return b2; 65*67e74705SXin Li 66*67e74705SXin Li return std::move(a1); 67*67e74705SXin Li return std::move(a2); 68*67e74705SXin Li return std::move(b1); 69*67e74705SXin Li return std::move(b2); 70*67e74705SXin Li } 71*67e74705SXin Li 72*67e74705SXin Li // PR23819, case 2 73*67e74705SXin Li struct D {}; test5(D d)74*67e74705SXin LiD test5(D d) { 75*67e74705SXin Li return d; 76*67e74705SXin Li // Verify the implicit move from the AST dump 77*67e74705SXin Li // CHECK-AST: ReturnStmt{{.*}}line:[[@LINE-2]] 78*67e74705SXin Li // CHECK-AST-NEXT: CXXConstructExpr{{.*}}struct D{{.*}}void (struct D &&) 79*67e74705SXin Li // CHECK-AST-NEXT: ImplicitCastExpr 80*67e74705SXin Li // CHECK-AST-NEXT: DeclRefExpr{{.*}}ParmVar{{.*}}'d' 81*67e74705SXin Li 82*67e74705SXin Li return std::move(d); 83*67e74705SXin Li // expected-warning@-1{{redundant move in return statement}} 84*67e74705SXin Li // expected-note@-2{{remove std::move call here}} 85*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" 86*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:"" 87*67e74705SXin Li } 88*67e74705SXin Li 89*67e74705SXin Li namespace templates { 90*67e74705SXin Li struct A {}; 91*67e74705SXin Li struct B { B(A); }; 92*67e74705SXin Li 93*67e74705SXin Li // Warn once here since the type is not dependent. 94*67e74705SXin Li template <typename T> test1(A a)95*67e74705SXin Li A test1(A a) { 96*67e74705SXin Li return std::move(a); 97*67e74705SXin Li // expected-warning@-1{{redundant move in return statement}} 98*67e74705SXin Li // expected-note@-2{{remove std::move call here}} 99*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:"" 100*67e74705SXin Li // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:"" 101*67e74705SXin Li } run_test1()102*67e74705SXin Li void run_test1() { 103*67e74705SXin Li test1<A>(A()); 104*67e74705SXin Li test1<B>(A()); 105*67e74705SXin Li } 106*67e74705SXin Li 107*67e74705SXin Li // T1 and T2 may not be the same, the warning may not always apply. 108*67e74705SXin Li template <typename T1, typename T2> test2(T2 t)109*67e74705SXin Li T1 test2(T2 t) { 110*67e74705SXin Li return std::move(t); 111*67e74705SXin Li } run_test2()112*67e74705SXin Li void run_test2() { 113*67e74705SXin Li test2<A, A>(A()); 114*67e74705SXin Li test2<B, A>(A()); 115*67e74705SXin Li } 116*67e74705SXin Li } 117