r216438 - Passing a variable to std::move now counts as a use for -Wuninitialized

Richard Trieu rtrieu at google.com
Mon Aug 25 21:30:56 PDT 2014


Author: rtrieu
Date: Mon Aug 25 23:30:55 2014
New Revision: 216438

URL: http://llvm.org/viewvc/llvm-project?rev=216438&view=rev
Log:
Passing a variable to std::move now counts as a use for -Wuninitialized

Modified:
    cfe/trunk/lib/Analysis/UninitializedValues.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/uninitialized.cpp

Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=216438&r1=216437&r2=216438&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Mon Aug 25 23:30:55 2014
@@ -341,6 +341,16 @@ void ClassifyRefs::VisitUnaryOperator(Un
 }
 
 void ClassifyRefs::VisitCallExpr(CallExpr *CE) {
+  // Classify arguments to std::move as used.
+  if (CE->getNumArgs() == 1) {
+    if (FunctionDecl *FD = CE->getDirectCallee()) {
+      if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) {
+        classify(CE->getArg(0), Use);
+        return;
+      }
+    }
+  }
+
   // If a value is passed by const reference to a function, we should not assume
   // that it is initialized by the call, and we conservatively do not assume
   // that it is used.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=216438&r1=216437&r2=216438&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Aug 25 23:30:55 2014
@@ -8288,6 +8288,21 @@ namespace {
       Inherited::VisitCXXConstructExpr(E);
     }
 
+    void VisitCallExpr(CallExpr *E) {
+      // Treat std::move as a use.
+      if (E->getNumArgs() == 1) {
+        if (FunctionDecl *FD = E->getDirectCallee()) {
+          if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) {
+            if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getArg(0))) {
+              HandleDeclRefExpr(DRE);
+            }
+          }
+        }
+      }
+
+      Inherited::VisitCallExpr(E);
+    }
+
     void HandleDeclRefExpr(DeclRefExpr *DRE) {
       Decl* ReferenceDecl = DRE->getDecl();
       if (OrigDecl != ReferenceDecl) return;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=216438&r1=216437&r2=216438&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Aug 25 23:30:55 2014
@@ -2337,6 +2337,21 @@ namespace {
       Inherited::VisitCXXMemberCallExpr(E);
     }
 
+    void VisitCallExpr(CallExpr *E) {
+      // Treat std::move as a use.
+      if (E->getNumArgs() == 1) {
+        if (FunctionDecl *FD = E->getDirectCallee()) {
+          if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) {
+            if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getArg(0))) {
+              HandleMemberExpr(ME, false /*CheckReferenceOnly*/);
+            }
+          }
+        }
+      }
+
+      Inherited::VisitCallExpr(E);
+    }
+
     void VisitBinaryOperator(BinaryOperator *E) {
       // If a field assignment is detected, remove the field from the
       // uninitiailized field set.

Modified: cfe/trunk/test/SemaCXX/uninitialized.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/uninitialized.cpp?rev=216438&r1=216437&r2=216438&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/uninitialized.cpp (original)
+++ cfe/trunk/test/SemaCXX/uninitialized.cpp Mon Aug 25 23:30:55 2014
@@ -1,9 +1,21 @@
 // RUN: %clang_cc1 -fsyntax-only -Wall -Wuninitialized -Wno-unused-value -std=c++11 -verify %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);
+}
+}
+
 int foo(int x);
 int bar(int* x);
 int boo(int& x);
 int far(const int& x);
+int moved(int&& x);
 
 // Test self-references within initializers which are guaranteed to be
 // uninitialized.
@@ -24,6 +36,9 @@ int k = __alignof__(k);
 int l = k ? l : l;  // expected-warning 2{{variable 'l' is uninitialized when used within its own initialization}}
 int m = 1 + (k ? m : m);  // expected-warning 2{{variable 'm' is uninitialized when used within its own initialization}}
 int n = -n;  // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+int o = std::move(o); // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+const int p = std::move(p); // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+int q = moved(std::move(q)); // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
 
 void test_stuff () {
   int a = a; // no-warning: used to signal intended lack of initialization.
@@ -44,6 +59,9 @@ void test_stuff () {
   int l = k ? l : l;  // expected-warning {{variable 'l' is uninitialized when used within its own initialization}}
   int m = 1 + (k ? m : m);  // expected-warning {{'m' is uninitialized when used within its own initialization}}
   int n = -n;  // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+  int o = std::move(o);  // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+  const int p = std::move(p);  // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+  int q = moved(std::move(q));  // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
 
   for (;;) {
     int a = a; // no-warning: used to signal intended lack of initialization.
@@ -64,6 +82,9 @@ void test_stuff () {
     int l = k ? l : l;  // expected-warning {{variable 'l' is uninitialized when used within its own initialization}}
     int m = 1 + (k ? m : m);  // expected-warning {{'m' is uninitialized when used within its own initialization}}
     int n = -n;  // expected-warning {{variable 'n' is uninitialized when used within its own initialization}}
+    int o = std::move(o);  // expected-warning {{variable 'o' is uninitialized when used within its own initialization}}
+    const int p = std::move(p);  // expected-warning {{variable 'p' is uninitialized when used within its own initialization}}
+    int q = moved(std::move(q));  // expected-warning {{variable 'q' is uninitialized when used within its own initialization}}
   }
 }
 
@@ -84,6 +105,7 @@ class A {
     A(int x) {}
     A(int *x) {}
     A(A *a) {}
+    A(A &&a) {}
     ~A();
 };
 
@@ -91,6 +113,7 @@ A getA() { return A(); }
 A getA(int x) { return A(); }
 A getA(A* a) { return A(); }
 A getA(A a) { return A(); }
+A moveA(A&& a) { return A(); }
 
 void setupA(bool x) {
   A a1;
@@ -130,6 +153,11 @@ void setupA(bool x) {
 
   const A a29(a29);  // expected-warning {{variable 'a29' is uninitialized when used within its own initialization}}
   const A a30 = a30;  // expected-warning {{variable 'a30' is uninitialized when used within its own initialization}}
+
+  A a31 = std::move(a31);  // expected-warning {{variable 'a31' is uninitialized when used within its own initialization}}
+  A a32 = moveA(std::move(a32));  // expected-warning {{variable 'a32' is uninitialized when used within its own initialization}}
+  A a33 = A(std::move(a33));   // expected-warning {{variable 'a33' is uninitialized when used within its own initialization}}
+  A a34(std::move(a34));   // expected-warning {{variable 'a34' is uninitialized when used within its own initialization}}
 }
 
 bool x;
@@ -169,6 +197,10 @@ A *a28 = new A(a28->num);  // expected-w
 const A a29(a29);  // expected-warning {{variable 'a29' is uninitialized when used within its own initialization}}
 const A a30 = a30;  // expected-warning {{variable 'a30' is uninitialized when used within its own initialization}}
 
+A a31 = std::move(a31);  // expected-warning {{variable 'a31' is uninitialized when used within its own initialization}}
+A a32 = moveA(std::move(a32));  // expected-warning {{variable 'a32' is uninitialized when used within its own initialization}}
+A a33 = A(std::move(a33));   // expected-warning {{variable 'a33' is uninitialized when used within its own initialization}}
+A a34(std::move(a34));   // expected-warning {{variable 'a34' is uninitialized when used within its own initialization}}
 struct B {
   // POD struct.
   int x;
@@ -179,6 +211,7 @@ B getB() { return B(); };
 B getB(int x) { return B(); };
 B getB(int *x) { return B(); };
 B getB(B *b) { return B(); };
+B moveB(B &&b) { return B(); };
 
 B* getPtrB() { return 0; };
 B* getPtrB(int x) { return 0; };
@@ -219,6 +252,9 @@ void setupB() {
   const B b19 = b19;  // expected-warning {{variable 'b19' is uninitialized when used within its own initialization}}
   const B b20(b20);  // expected-warning {{variable 'b20' is uninitialized when used within its own initialization}}
 
+  B b21 = std::move(b21);  // expected-warning {{variable 'b21' is uninitialized when used within its own initialization}}
+  B b22 = moveB(std::move(b22));  // expected-warning {{variable 'b22' is uninitialized when used within its own initialization}}
+  B b23 = B(std::move(b23));   // expected-warning {{variable 'b23' is uninitialized when used within its own initialization}}
 }
 
 B b1;
@@ -247,6 +283,10 @@ B b18 = { b18.x + 1, b18.y };  // expect
 const B b19 = b19;  // expected-warning {{variable 'b19' is uninitialized when used within its own initialization}}
 const B b20(b20);  // expected-warning {{variable 'b20' is uninitialized when used within its own initialization}}
 
+B b21 = std::move(b21);  // expected-warning {{variable 'b21' is uninitialized when used within its own initialization}}
+B b22 = moveB(std::move(b22));  // expected-warning {{variable 'b22' is uninitialized when used within its own initialization}}
+B b23 = B(std::move(b23));   // expected-warning {{variable 'b23' is uninitialized when used within its own initialization}}
+
 // Also test similar constructs in a field's initializer.
 struct S {
   int x;
@@ -558,6 +598,7 @@ namespace record_fields {
   A const_ref(const A&);
   A pointer(A*);
   A normal(A);
+  A rref(A&&);
 
   struct B {
     A a;
@@ -570,9 +611,12 @@ namespace record_fields {
     B(char (*)[7]) : a(const_ref(a)) {}
     B(char (*)[8]) : a(pointer(&a)) {}
     B(char (*)[9]) : a(normal(a)) {}  // expected-warning {{uninitialized}}
+    B(char (*)[10]) : a(std::move(a)) {}  // expected-warning {{uninitialized}}
+    B(char (*)[11]) : a(A(std::move(a))) {}  // expected-warning {{uninitialized}}
+    B(char (*)[12]) : a(rref(std::move(a))) {}  // expected-warning {{uninitialized}}
   };
   struct C {
-    C() {} // expected-note5{{in this constructor}}
+    C() {} // expected-note8{{in this constructor}}
     A a1 = a1;  // expected-warning {{uninitialized}}
     A a2 = a2.get();  // expected-warning {{uninitialized}}
     A a3 = a3.num();
@@ -583,8 +627,11 @@ namespace record_fields {
     A a8 = pointer(&a8);
     A a9 = normal(a9);  // expected-warning {{uninitialized}}
     const A a10 = a10;  // expected-warning {{uninitialized}}
+    A a11 = std::move(a11);  // expected-warning {{uninitialized}}
+    A a12 = A(std::move(a12));  // expected-warning {{uninitialized}}
+    A a13 = rref(std::move(a13));  // expected-warning {{uninitialized}}
   };
-  struct D {  // expected-note5{{in the implicit default constructor}}
+  struct D {  // expected-note8{{in the implicit default constructor}}
     A a1 = a1;  // expected-warning {{uninitialized}}
     A a2 = a2.get();  // expected-warning {{uninitialized}}
     A a3 = a3.num();
@@ -595,6 +642,9 @@ namespace record_fields {
     A a8 = pointer(&a8);
     A a9 = normal(a9);  // expected-warning {{uninitialized}}
     const A a10 = a10;  // expected-warning {{uninitialized}}
+    A a11 = std::move(a11);  // expected-warning {{uninitialized}}
+    A a12 = A(std::move(a12));  // expected-warning {{uninitialized}}
+    A a13 = rref(std::move(a13));  // expected-warning {{uninitialized}}
   };
   D d;
   struct E {
@@ -608,6 +658,9 @@ namespace record_fields {
     A a8 = pointer(&a8);
     A a9 = normal(a9);
     const A a10 = a10;
+    A a11 = std::move(a11);
+    A a12 = A(std::move(a12));
+    A a13 = rref(std::move(a13));
   };
 }
 





More information about the cfe-commits mailing list