[ObjC++] Don't warn about pessimizing move for __block variables
authorAlex Lorenz <arphaman@gmail.com>
Tue, 7 Nov 2017 21:40:11 +0000 (21:40 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 7 Nov 2017 21:40:11 +0000 (21:40 +0000)
rdar://33316951

llvm-svn: 317620

clang/lib/Sema/SemaInit.cpp
clang/test/SemaObjCXX/block-variable-move.mm [new file with mode: 0644]

index dc7fe1d..5ece958 100644 (file)
@@ -6422,6 +6422,10 @@ static void CheckMoveOnConstruction(Sema &S, const Expr *InitExpr,
     if (!VD || !VD->hasLocalStorage())
       return;
 
+    // __block variables are not moved implicitly.
+    if (VD->hasAttr<BlocksAttr>())
+      return;
+
     QualType SourceType = VD->getType();
     if (!SourceType->isRecordType())
       return;
diff --git a/clang/test/SemaObjCXX/block-variable-move.mm b/clang/test/SemaObjCXX/block-variable-move.mm
new file mode 100644 (file)
index 0000000..e26dffc
--- /dev/null
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -fobjc-arc -verify -fblocks -Wpessimizing-move -Wredundant-move %s
+
+// definitions for std::move
+namespace std {
+inline namespace foo {
+template <class T> struct remove_reference { typedef T type; };
+template <class T> struct remove_reference<T&> { typedef T type; };
+template <class T> struct remove_reference<T&&> { typedef T type; };
+
+template <class T> typename remove_reference<T>::type &&move(T &&t);
+}
+}
+
+class MoveOnly {
+public:
+  MoveOnly() { }
+  MoveOnly(MoveOnly &&) = default; // expected-note 2 {{copy constructor is implicitly deleted}}
+  MoveOnly &operator=(MoveOnly &&) = default;
+  ~MoveOnly();
+};
+
+void copyInit() {
+  __block MoveOnly temp;
+  MoveOnly temp2 = temp; // expected-error {{call to implicitly-deleted copy constructor of 'MoveOnly'}}
+  MoveOnly temp3 = std::move(temp); // ok
+}
+
+MoveOnly errorOnCopy() {
+  __block MoveOnly temp;
+  return temp; // expected-error {{call to implicitly-deleted copy constructor of 'MoveOnly'}}
+}
+
+MoveOnly dontWarnOnMove() {
+  __block MoveOnly temp;
+  return std::move(temp); // ok
+}
+
+class MoveOnlySub : public MoveOnly {};
+
+MoveOnly dontWarnOnMoveSubclass() {
+  __block MoveOnlySub temp;
+  return std::move(temp); // ok
+}