Home | History | Annotate | Download | only in SemaCXX
      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
      6 namespace std {
      7 inline namespace foo {
      8 template <class T> struct remove_reference { typedef T type; };
      9 template <class T> struct remove_reference<T&> { typedef T type; };
     10 template <class T> struct remove_reference<T&&> { typedef T type; };
     11 
     12 template <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.
     17 struct A {};
     18 struct B : public A {};
     19 
     20 A test1(B b1) {
     21   B b2;
     22   return b1;
     23   return b2;
     24   return std::move(b1);
     25   return std::move(b2);
     26 }
     27 
     28 struct C {
     29   C() {}
     30   C(A) {}
     31 };
     32 
     33 C 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.
     49 A 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 
     57 C 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
     73 struct D {};
     74 D 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 
     89 namespace 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