<div dir="ltr">Why are these DefaultIgnore?</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Apr 28, 2015 at 6:52 PM, Richard Trieu <span dir="ltr"><<a href="mailto:rtrieu@google.com" target="_blank">rtrieu@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rtrieu<br>
Date: Tue Apr 28 20:52:17 2015<br>
New Revision: 236075<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=236075&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=236075&view=rev</a><br>
Log:<br>
Add -Wpessimizing-move and -Wredundant-move warnings.<br>
<br>
-Wpessimizing-move warns when a call to std::move would prevent copy elision<br>
if the argument was not wrapped in a call.  This happens when moving a local<br>
variable in a return statement when the variable is the same type as the<br>
return type or using a move to create a new object from a temporary object.<br>
<br>
-Wredundant-move warns when an implicit move would already be made, so the<br>
std::move call is not needed, such as when moving a local variable in a return<br>
that is different from the return type.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D7633" target="_blank">http://reviews.llvm.org/D7633</a><br>
<br>
Added:<br>
    cfe/trunk/test/SemaCXX/warn-pessmizing-move.cpp<br>
    cfe/trunk/test/SemaCXX/warn-redundant-move.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/Sema/SemaInit.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=236075&r1=236074&r2=236075&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=236075&r1=236074&r2=236075&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Apr 28 20:52:17 2015<br>
@@ -286,6 +286,7 @@ def DeprecatedObjCIsaUsage : DiagGroup<"<br>
 def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;<br>
 def Packed : DiagGroup<"packed">;<br>
 def Padded : DiagGroup<"padded">;<br>
+def PessimizingMove : DiagGroup<"pessimizing-move">;<br>
 def PointerArith : DiagGroup<"pointer-arith">;<br>
 def PoundWarning : DiagGroup<"#warnings">;<br>
 def PoundPragmaMessage : DiagGroup<"#pragma-messages">,<br>
@@ -294,6 +295,7 @@ def : DiagGroup<"pointer-to-int-cast">;<br>
 def : DiagGroup<"redundant-decls">;<br>
 def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;<br>
 def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;<br>
+def RedundantMove : DiagGroup<"redundant-move">;<br>
 def ReturnStackAddress : DiagGroup<"return-stack-address">;<br>
 def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;<br>
 def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=236075&r1=236074&r2=236075&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=236075&r1=236074&r2=236075&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 28 20:52:17 2015<br>
@@ -4777,6 +4777,17 @@ def warn_self_move : Warning<<br>
   "explicitly moving variable of type %0 to itself">,<br>
   InGroup<SelfMove>, DefaultIgnore;<br>
<br>
+def warn_redundant_move_on_return : Warning<<br>
+  "redundant move in return statement">,<br>
+  InGroup<RedundantMove>, DefaultIgnore;<br>
+def warn_pessimizing_move_on_return : Warning<<br>
+  "moving a local object in a return statement prevents copy elision">,<br>
+  InGroup<PessimizingMove>, DefaultIgnore;<br>
+def warn_pessimizing_move_on_initialization : Warning<<br>
+  "moving a temporary object prevents copy elision">,<br>
+  InGroup<PessimizingMove>, DefaultIgnore;<br>
+def note_remove_move : Note<"remove std::move call here">;<br>
+<br>
 def warn_string_plus_int : Warning<<br>
   "adding %0 to a string does not append to the string">,<br>
   InGroup<StringPlusInt>;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=236075&r1=236074&r2=236075&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=236075&r1=236074&r2=236075&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Apr 28 20:52:17 2015<br>
@@ -5768,6 +5768,112 @@ static void DiagnoseNarrowingInInitList(<br>
                                         QualType EntityType,<br>
                                         const Expr *PostInit);<br>
<br>
+/// Provide warnings when std::move is used on construction.<br>
+static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,<br>
+                                    bool IsReturnStmt) {<br>
+  if (!InitExpr)<br>
+    return;<br>
+<br>
+  QualType DestType = InitExpr->getType();<br>
+  if (!DestType->isRecordType())<br>
+    return;<br>
+<br>
+  unsigned DiagID = 0;<br>
+  if (IsReturnStmt) {<br>
+    const CXXConstructExpr *CCE =<br>
+        dyn_cast<CXXConstructExpr>(InitExpr->IgnoreParens());<br>
+    if (!CCE || CCE->getNumArgs() != 1)<br>
+      return;<br>
+<br>
+    if (!CCE->getConstructor()->isCopyOrMoveConstructor())<br>
+      return;<br>
+<br>
+    InitExpr = CCE->getArg(0)->IgnoreImpCasts();<br>
+<br>
+    // Remove implicit temporary and constructor nodes.<br>
+    if (const MaterializeTemporaryExpr *MTE =<br>
+            dyn_cast<MaterializeTemporaryExpr>(InitExpr)) {<br>
+      InitExpr = MTE->GetTemporaryExpr()->IgnoreImpCasts();<br>
+      while (const CXXConstructExpr *CCE =<br>
+                 dyn_cast<CXXConstructExpr>(InitExpr)) {<br>
+        if (isa<CXXTemporaryObjectExpr>(CCE))<br>
+          return;<br>
+        if (CCE->getNumArgs() == 0)<br>
+          return;<br>
+        if (CCE->getNumArgs() > 1 && !isa<CXXDefaultArgExpr>(CCE->getArg(1)))<br>
+          return;<br>
+        InitExpr = CCE->getArg(0);<br>
+      }<br>
+      InitExpr = InitExpr->IgnoreImpCasts();<br>
+      DiagID = diag::warn_redundant_move_on_return;<br>
+    }<br>
+  }<br>
+<br>
+  // Find the std::move call and get the argument.<br>
+  const CallExpr *CE = dyn_cast<CallExpr>(InitExpr->IgnoreParens());<br>
+  if (!CE || CE->getNumArgs() != 1)<br>
+    return;<br>
+<br>
+  const FunctionDecl *MoveFunction = CE->getDirectCallee();<br>
+  if (!MoveFunction || !MoveFunction->isInStdNamespace() ||<br>
+      !MoveFunction->getIdentifier() ||<br>
+      !MoveFunction->getIdentifier()->isStr("move"))<br>
+    return;<br>
+<br>
+  const Expr *Arg = CE->getArg(0)->IgnoreImplicit();<br>
+<br>
+  if (IsReturnStmt) {<br>
+    const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arg->IgnoreParenImpCasts());<br>
+    if (!DRE || DRE->refersToEnclosingVariableOrCapture())<br>
+      return;<br>
+<br>
+    const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());<br>
+    if (!VD || !VD->hasLocalStorage())<br>
+      return;<br>
+<br>
+    if (DiagID == 0) {<br>
+      DiagID = S.Context.hasSameUnqualifiedType(DestType, VD->getType())<br>
+                   ? diag::warn_pessimizing_move_on_return<br>
+                   : diag::warn_redundant_move_on_return;<br>
+    }<br>
+  } else {<br>
+    DiagID = diag::warn_pessimizing_move_on_initialization;<br>
+    const Expr *ArgStripped = Arg->IgnoreImplicit()->IgnoreParens();<br>
+    if (!ArgStripped->isRValue() || !ArgStripped->getType()->isRecordType())<br>
+      return;<br>
+  }<br>
+<br>
+  S.Diag(CE->getLocStart(), DiagID);<br>
+<br>
+  // Get all the locations for a fix-it.  Don't emit the fix-it if any location<br>
+  // is within a macro.<br>
+  SourceLocation CallBegin = CE->getCallee()->getLocStart();<br>
+  if (CallBegin.isMacroID())<br>
+    return;<br>
+  SourceLocation RParen = CE->getRParenLoc();<br>
+  if (RParen.isMacroID())<br>
+    return;<br>
+  SourceLocation LParen;<br>
+  SourceLocation ArgLoc = Arg->getLocStart();<br>
+<br>
+  // Special testing for the argument location.  Since the fix-it needs the<br>
+  // location right before the argument, the argument location can be in a<br>
+  // macro only if it is at the beginning of the macro.<br>
+  while (ArgLoc.isMacroID() &&<br>
+         S.getSourceManager().isAtStartOfImmediateMacroExpansion(ArgLoc)) {<br>
+    ArgLoc = S.getSourceManager().getImmediateExpansionRange(ArgLoc).first;<br>
+  }<br>
+<br>
+  if (LParen.isMacroID())<br>
+    return;<br>
+<br>
+  LParen = ArgLoc.getLocWithOffset(-1);<br>
+<br>
+  S.Diag(CE->getLocStart(), diag::note_remove_move)<br>
+      << FixItHint::CreateRemoval(SourceRange(CallBegin, LParen))<br>
+      << FixItHint::CreateRemoval(SourceRange(RParen, RParen));<br>
+}<br>
+<br>
 ExprResult<br>
 InitializationSequence::Perform(Sema &S,<br>
                                 const InitializedEntity &Entity,<br>
@@ -6497,6 +6603,12 @@ InitializationSequence::Perform(Sema &S,<br>
                                   cast<FieldDecl>(Entity.getDecl()),<br>
                                   CurInit.get());<br>
<br>
+  // Check for std::move on construction.<br>
+  if (const Expr *E = CurInit.get()) {<br>
+    CheckMoveOnConstruction(S, E,<br>
+                            Entity.getKind() == InitializedEntity::EK_Result);<br>
+  }<br>
+<br>
   return CurInit;<br>
 }<br>
<br>
<br>
Added: cfe/trunk/test/SemaCXX/warn-pessmizing-move.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-pessmizing-move.cpp?rev=236075&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-pessmizing-move.cpp?rev=236075&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/warn-pessmizing-move.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/warn-pessmizing-move.cpp Tue Apr 28 20:52:17 2015<br>
@@ -0,0 +1,203 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s<br>
+// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s<br>
+<br>
+// definitions for std::move<br>
+namespace std {<br>
+inline namespace foo {<br>
+template <class T> struct remove_reference { typedef T type; };<br>
+template <class T> struct remove_reference<T&> { typedef T type; };<br>
+template <class T> struct remove_reference<T&&> { typedef T type; };<br>
+<br>
+template <class T> typename remove_reference<T>::type &&move(T &&t);<br>
+}<br>
+}<br>
+<br>
+struct A {};<br>
+struct B {<br>
+  B() {}<br>
+  B(A) {}<br>
+};<br>
+<br>
+A test1(A a1) {<br>
+  A a2;<br>
+  return a1;<br>
+  return a2;<br>
+  return std::move(a1);<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move(a2);<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+}<br>
+<br>
+B test2(A a1, B b1) {<br>
+  // Object is different than return type so don't warn.<br>
+  A a2;<br>
+  return a1;<br>
+  return a2;<br>
+  return std::move(a1);<br>
+  return std::move(a2);<br>
+<br>
+  B b2;<br>
+  return b1;<br>
+  return b2;<br>
+  return std::move(b1);<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move(b2);<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+}<br>
+<br>
+A global_a;<br>
+A test3() {<br>
+  // Don't warn when object is not local.<br>
+  return global_a;<br>
+  return std::move(global_a);<br>
+  static A static_a;<br>
+  return static_a;<br>
+  return std::move(static_a);<br>
+<br>
+}<br>
+<br>
+A test4() {<br>
+  return A();<br>
+  return test3();<br>
+<br>
+  return std::move(A());<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""<br>
+  return std::move(test3());<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""<br>
+}<br>
+<br>
+void test5(A) {<br>
+  test5(A());<br>
+  test5(test4());<br>
+<br>
+  test5(std::move(A()));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  test5(std::move(test4()));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""<br>
+}<br>
+<br>
+void test6() {<br>
+  A a1 = A();<br>
+  A a2 = test3();<br>
+<br>
+  A a3 = std::move(A());<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""<br>
+  A a4 = std::move(test3());<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""<br>
+}<br>
+<br>
+A test7() {<br>
+  A a1 = std::move(A());<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""<br>
+  A a2 = std::move((A()));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""<br>
+  A a3 = (std::move(A()));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""<br>
+  A a4 = (std::move((A())));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""<br>
+<br>
+  return std::move(a1);<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move((a1));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""<br>
+  return (std::move(a1));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""<br>
+  return (std::move((a1)));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""<br>
+}<br>
+<br>
+#define wrap1(x) x<br>
+#define wrap2(x) x<br>
+<br>
+// Macro test.  Since the std::move call is outside the macro, it is<br>
+// safe to suggest a fix-it.<br>
+A test8(A a) {<br>
+  return std::move(a);<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""<br>
+  return std::move(wrap1(a));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:28-[[@LINE-4]]:29}:""<br>
+  return std::move(wrap1(wrap2(a)));<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:35-[[@LINE-4]]:36}:""<br>
+}<br>
+<br>
+#define test9            \<br>
+  A test9(A a) {         \<br>
+    return std::move(a); \<br>
+  }<br>
+<br>
+// Macro test.  The std::call is inside the macro, so no fix-it is suggested.<br>
+test9<br>
+// expected-warning@-1{{prevents copy elision}}<br>
+// CHECK-NOT: fix-it<br>
+<br>
+#define return_a return std::move(a)<br>
+<br>
+// Macro test.  The std::call is inside the macro, so no fix-it is suggested.<br>
+A test10(A a) {<br>
+  return_a;<br>
+  // expected-warning@-1{{prevents copy elision}}<br>
+  // CHECK-NOT: fix-it<br>
+}<br>
<br>
Added: cfe/trunk/test/SemaCXX/warn-redundant-move.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-redundant-move.cpp?rev=236075&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-redundant-move.cpp?rev=236075&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/warn-redundant-move.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/warn-redundant-move.cpp Tue Apr 28 20:52:17 2015<br>
@@ -0,0 +1,68 @@<br>
+// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s<br>
+// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s<br>
+<br>
+// definitions for std::move<br>
+namespace std {<br>
+inline namespace foo {<br>
+template <class T> struct remove_reference { typedef T type; };<br>
+template <class T> struct remove_reference<T&> { typedef T type; };<br>
+template <class T> struct remove_reference<T&&> { typedef T type; };<br>
+<br>
+template <class T> typename remove_reference<T>::type &&move(T &&t);<br>
+}<br>
+}<br>
+<br>
+struct A {};<br>
+struct B : public A {};<br>
+<br>
+A test1(B b1) {<br>
+  B b2;<br>
+  //return b1;<br>
+  //return b2;<br>
+  return std::move(b1);<br>
+  // expected-warning@-1{{redundant move}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move(b2);<br>
+  // expected-warning@-1{{redundant move}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+}<br>
+<br>
+struct C {<br>
+  C() {}<br>
+  C(A) {}<br>
+};<br>
+<br>
+C test2(A a1, B b1) {<br>
+  A a2;<br>
+  B b2;<br>
+<br>
+  return a1;<br>
+  return a2;<br>
+  return b1;<br>
+  return b2;<br>
+<br>
+  return std::move(a1);<br>
+  // expected-warning@-1{{redundant move}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move(a2);<br>
+  // expected-warning@-1{{redundant move}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move(b1);<br>
+  // expected-warning@-1{{redundant move}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+  return std::move(b2);<br>
+  // expected-warning@-1{{redundant move}}<br>
+  // expected-note@-2{{remove std::move call}}<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""<br>
+  // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>