Disable -Wpessimizing-move and -Wredundant-move in template instantiations.
authorRichard Trieu <rtrieu@google.com>
Wed, 29 Jul 2015 17:03:34 +0000 (17:03 +0000)
committerRichard Trieu <rtrieu@google.com>
Wed, 29 Jul 2015 17:03:34 +0000 (17:03 +0000)
Dependent types can throw off the analysis for these warnings, possibly giving
conflicting warnings and fix-its.  Disabling the warning in template
instantiations will prevent this problem, and will still catch the
non-dependent cases in templates.

llvm-svn: 243538

clang/lib/Sema/SemaInit.cpp
clang/test/SemaCXX/warn-pessmizing-move.cpp
clang/test/SemaCXX/warn-redundant-move.cpp

index fd06777..f66bc7f 100644 (file)
@@ -5926,6 +5926,9 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
   if (!InitExpr)
     return;
 
+  if (!S.ActiveTemplateInstantiations.empty())
+    return;
+
   QualType DestType = InitExpr->getType();
   if (!DestType->isRecordType())
     return;
index f5a4b90..5645564 100644 (file)
@@ -196,3 +196,40 @@ A test10() {
   // expected-warning@-1{{prevents copy elision}}
   // CHECK-NOT: fix-it
 }
+
+namespace templates {
+  struct A {};
+  struct B { B(A); };
+  struct C { C(); C(C&&); };
+  struct D { D(C); };
+
+  // Warn once here since the type is not dependent.
+  template <typename T>
+  A test1() {
+    A a;
+    return std::move(a);
+    // expected-warning@-1{{prevents copy elision}}
+    // expected-note@-2{{remove std::move call}}
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
+  }
+  void run_test1() {
+    test1<A>();
+    test1<B>();
+    test1<C>();
+    test1<D>();
+  }
+
+  // Either a pessimizing move, a redundant move, or no warning could be
+  // emitted, given the right types.  So just drop the warning.
+  template <typename T1, typename T2>
+  T1 test2() {
+    T2 t;
+    return std::move(t);
+  }
+  void run_test2() {
+    test2<A, A>();
+    test2<B, A>();
+    test2<D, C>();
+  }
+}
index 06f9c58..d160695 100644 (file)
@@ -103,6 +103,43 @@ D test5(D d) {
   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
 }
 
+namespace templates {
+  struct A {};
+  struct B { B(A); };
+  struct C { C(); C(C&&); };
+  struct D { D(C); };
+
+  // Warn once here since the type is not dependent.
+  template <typename T>
+  B test1() {
+    A a;
+    return std::move(a);
+    // expected-warning@-1{{redundant move in return statement}}
+    // expected-note@-2{{remove std::move call here}}
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
+  }
+  void run_test1() {
+    test1<A>();
+    test1<B>();
+    test1<C>();
+    test1<D>();
+  }
+
+  // Either a pessimizing move, a redundant move, or no warning could be
+  // emitted, given the right types.  So just drop the warning.
+  template <typename T1, typename T2>
+  T1 test2() {
+    T2 t;
+    return std::move(t);
+  }
+  void run_test2() {
+    test2<A, A>();
+    test2<B, A>();
+    test2<D, C>();
+  }
+}
+
 // No more fix-its past here.
 // CHECK-NOT: fix-it