]> granicus.if.org Git - clang/commitdiff
Add increment/decrement operators and compound assignment operators to the
authorRichard Trieu <rtrieu@google.com>
Thu, 25 Sep 2014 01:15:40 +0000 (01:15 +0000)
committerRichard Trieu <rtrieu@google.com>
Thu, 25 Sep 2014 01:15:40 +0000 (01:15 +0000)
uninitialized checkers that did not have them before.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218435 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/SemaCXX/decl-init-ref.cpp
test/SemaCXX/uninitialized.cpp

index 277816be4291ab19fc9448a37ff3addd4a69a831..1bac28753fee4c5b6983dae272777d46f244c1b9 100644 (file)
@@ -8452,6 +8452,12 @@ namespace {
           HandleValue(E->getSubExpr());
         return;
       }
+
+      if (E->isIncrementDecrementOp()) {
+        HandleValue(E->getSubExpr());
+        return;
+      }
+
       Inherited::VisitUnaryOperator(E);
     }
 
@@ -8480,6 +8486,16 @@ namespace {
       Inherited::VisitCallExpr(E);
     }
 
+    void VisitBinaryOperator(BinaryOperator *E) {
+      if (E->isCompoundAssignmentOp()) {
+        HandleValue(E->getLHS());
+        Visit(E->getRHS());
+        return;
+      }
+
+      Inherited::VisitBinaryOperator(E);
+    }
+
     // A custom visitor for BinaryConditionalOperator is needed because the
     // regular visitor would check the condition and true expression separately
     // but both point to the same place giving duplicate diagnostics.
index 006a3c49d7ca7a0c38f17b54e76f625159aef878..bf53ae38ddb564697c5e31bb70f3e34f7f9512ed 100644 (file)
@@ -2382,8 +2382,19 @@ namespace {
             if (!FD->getType()->isReferenceType())
               DeclsToRemove.push_back(FD);
 
+      if (E->isCompoundAssignmentOp()) {
+        HandleValue(E->getLHS());
+      }
+
       Inherited::VisitBinaryOperator(E);
     }
+
+    void VisitUnaryOperator(UnaryOperator *E) {
+      if (E->isIncrementDecrementOp())
+        HandleValue(E->getSubExpr());
+
+      Inherited::VisitUnaryOperator(E);
+    }
   };
 
   // Diagnose value-uses of fields to initialize themselves, e.g.
index 2d0c9cb4ffbec2a5df8c04ee7c73e641c7b0c781..42b9286852c7521fcb83b82c3236df193dc57c0d 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -Wno-uninitialized
 
 struct A {};
 
index a43b616ebf4c5062f5d64fee0345dbf06e42ff1b..d6331965ab4ef9689ec00e34dd7d1049746b3d23 100644 (file)
@@ -16,6 +16,7 @@ int bar(int* x);
 int boo(int& x);
 int far(const int& x);
 int moved(int&& x);
+int &ref(int x);
 
 // Test self-references within initializers which are guaranteed to be
 // uninitialized.
@@ -44,6 +45,11 @@ int s = r ?: s; // expected-warning {{variable 's' is uninitialized when used wi
 int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
 int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
 int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+int z = ++ref(z); // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
 
 void test_stuff () {
   int a = a; // no-warning: used to signal intended lack of initialization.
@@ -72,6 +78,11 @@ void test_stuff () {
   int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
   int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
   int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+  int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+  int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+  int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+  int z = ++ref(z);                              // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+  int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
 
   for (;;) {
     int a = a; // no-warning: used to signal intended lack of initialization.
@@ -100,6 +111,11 @@ void test_stuff () {
     int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
     int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
     int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+    int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+    int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+    int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+    int z = ++ref(z);                              // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+    int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
   }
 }
 
@@ -176,7 +192,7 @@ void setupA(bool x) {
   A a35 = std::move(x ? a34 : (37, a35));  // expected-warning {{variable 'a35' is uninitialized when used within its own initialization}}
 }
 
-bool x;
+bool cond;
 
 A a1;
 A a2(a1.get());
@@ -196,8 +212,8 @@ A a14 = A(a14);  // expected-warning {{variable 'a14' is uninitialized when used
 A a15 = getA(a15.num);  // expected-warning {{variable 'a15' is uninitialized when used within its own initialization}}
 A a16(&a16.num);  // expected-warning {{variable 'a16' is uninitialized when used within its own initialization}}
 A a17(a17.get2());  // expected-warning {{variable 'a17' is uninitialized when used within its own initialization}}
-A a18 = x ? a18 : a17;  // expected-warning {{variable 'a18' is uninitialized when used within its own initialization}}
-A a19 = getA(x ? a19 : a17);  // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}}
+A a18 = cond ? a18 : a17;  // expected-warning {{variable 'a18' is uninitialized when used within its own initialization}}
+A a19 = getA(cond ? a19 : a17);  // expected-warning {{variable 'a19' is uninitialized when used within its own initialization}}
 A a20{a20};  // expected-warning {{variable 'a20' is uninitialized when used within its own initialization}}
 A a21 = {a21};  // expected-warning {{variable 'a21' is uninitialized when used within its own initialization}}
 
@@ -328,6 +344,11 @@ struct S {
 
   S(char (*)[7]) : x(0), y((foo(y), x)) {} // expected-warning {{field 'y' is uninitialized when used here}}
   S(char (*)[8]) : x(0), y(x += y) {} // expected-warning {{field 'y' is uninitialized when used here}}
+  S(char (*)[9]) : x(x += 10) {} // expected-warning {{field 'x' is uninitialized when used here}}
+  S(char (*)[10]) : x(x++) {} // expected-warning {{field 'x' is uninitialized when used here}}
+  S(char (*)[11]) : x(0), y(((x ? (y, x) : (77, y))++, sizeof(y))) {} // expected-warning {{field 'y' is uninitialized when used here}}
+  S(char (*)[12]) : x(++ref(x)) {} // expected-warning {{field 'x' is uninitialized when used here}}
+  S(char (*)[13]) : x(ref(x) += 10) {} // expected-warning {{field 'x' is uninitialized when used here}}
 };
 
 struct C { char a[100], *e; } car = { .e = car.a };
@@ -496,6 +517,11 @@ namespace statics {
   static int t = t ?: s; // expected-warning {{variable 't' is uninitialized when used within its own initialization}}
   static int u = (foo(u), s); // expected-warning {{variable 'u' is uninitialized when used within its own initialization}}
   static int v = (u += v); // expected-warning {{variable 'v' is uninitialized when used within its own initialization}}
+  static int w = (w += 10); // expected-warning {{variable 'w' is uninitialized when used within its own initialization}}
+  static int x = x++; // expected-warning {{variable 'x' is uninitialized when used within its own initialization}}
+  static int y = ((s ? (y, v) : (77, y))++, sizeof(y)); // expected-warning {{variable 'y' is uninitialized when used within its own initialization}}
+  static int z = ++ref(z); // expected-warning {{variable 'z' is uninitialized when used within its own initialization}}
+  static int aa = (ref(aa) += 10); // expected-warning {{variable 'aa' is uninitialized when used within its own initialization}}
 
   void test() {
     static int a = a; // no-warning: used to signal intended lack of initialization.
@@ -524,6 +550,11 @@ namespace statics {
     static int t = t ?: s;  // expected-warning {{static variable 't' is suspiciously used within its own initialization}}
     static int u = (foo(u), s);  // expected-warning {{static variable 'u' is suspiciously used within its own initialization}}
     static int v = (u += v);  // expected-warning {{static variable 'v' is suspiciously used within its own initialization}}
+    static int w = (w += 10);  // expected-warning {{static variable 'w' is suspiciously used within its own initialization}}
+    static int x = x++;  // expected-warning {{static variable 'x' is suspiciously used within its own initialization}}
+    static int y = ((s ? (y, v) : (77, y))++, sizeof(y));  // expected-warning {{static variable 'y' is suspiciously used within its own initialization}}
+    static int z = ++ref(z); // expected-warning {{static variable 'z' is suspiciously used within its own initialization}}
+    static int aa = (ref(aa) += 10); // expected-warning {{static variable 'aa' is suspiciously used within its own initialization}}
    for (;;) {
       static int a = a; // no-warning: used to signal intended lack of initialization.
       static int b = b + 1; // expected-warning {{static variable 'b' is suspiciously used within its own initialization}}
@@ -551,6 +582,11 @@ namespace statics {
       static int t = t ?: s;  // expected-warning {{static variable 't' is suspiciously used within its own initialization}}
       static int u = (foo(u), s);  // expected-warning {{static variable 'u' is suspiciously used within its own initialization}}
       static int v = (u += v);  // expected-warning {{static variable 'v' is suspiciously used within its own initialization}}
+      static int w = (w += 10);  // expected-warning {{static variable 'w' is suspiciously used within its own initialization}}
+      static int x = x++;  // expected-warning {{static variable 'x' is suspiciously used within its own initialization}}
+      static int y = ((s ? (y, v) : (77, y))++, sizeof(y));  // expected-warning {{static variable 'y' is suspiciously used within its own initialization}}
+      static int z = ++ref(z); // expected-warning {{static variable 'z' is suspiciously used within its own initialization}}
+      static int aa = (ref(aa) += 10); // expected-warning {{static variable 'aa' is suspiciously used within its own initialization}}
     }
   }
 }