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