]> granicus.if.org Git - clang/commitdiff
Teach -Wuninitialized about ObjC fast enumeration loops.
authorTed Kremenek <kremenek@apple.com>
Thu, 27 Jan 2011 02:01:31 +0000 (02:01 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 27 Jan 2011 02:01:31 +0000 (02:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124347 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/UninitializedValuesV2.cpp
test/SemaObjC/uninit-variables.m [new file with mode: 0644]

index 32630549599a393e08492581e138f2bdd1e6ca88..71a62f7e19f42af36127d933aafc929a8e39b65b 100644 (file)
@@ -311,6 +311,7 @@ public:
   void VisitBinaryOperator(BinaryOperator *bo);
   void VisitCastExpr(CastExpr *ce);
   void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *se);
+  void BlockStmt_VisitObjCForCollectionStmt(ObjCForCollectionStmt *fs);
 };
 }
 
@@ -319,6 +320,43 @@ void TransferFunctions::reportUninit(const DeclRefExpr *ex,
   if (handler) handler->handleUseOfUninitVariable(ex, vd);
 }
 
+static FindVarResult findBlockVarDecl(Expr* ex) {
+  if (DeclRefExpr* dr = dyn_cast<DeclRefExpr>(ex->IgnoreParenCasts()))
+    if (VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
+      if (isTrackedVar(vd))
+        return FindVarResult(vd, dr);
+  
+  return FindVarResult(0, 0);
+}
+
+void TransferFunctions::BlockStmt_VisitObjCForCollectionStmt(
+    ObjCForCollectionStmt *fs) {
+  
+  Visit(fs->getCollection());
+  
+  // This represents an initialization of the 'element' value.
+  Stmt *element = fs->getElement();
+  const VarDecl* vd = 0;
+  
+  if (DeclStmt* ds = dyn_cast<DeclStmt>(element)) {
+    vd = cast<VarDecl>(ds->getSingleDecl());
+    if (!isTrackedVar(vd))
+      vd = 0;
+  }
+  else {
+    // Initialize the value of the reference variable.
+    const FindVarResult &res = findBlockVarDecl(cast<Expr>(element));
+    vd = res.getDecl();
+    if (!vd) {
+      Visit(element);
+      return;
+    }
+  }
+  
+  if (vd)
+    vals[vd] = Initialized;
+}
+
 void TransferFunctions::VisitBlockExpr(BlockExpr *be) {
   if (!flagBlockUses || !handler)
     return;
@@ -366,15 +404,6 @@ void TransferFunctions::VisitDeclRefExpr(DeclRefExpr *dr) {
         vals[vd] = Initialized;
 }
 
-static FindVarResult findBlockVarDecl(Expr* ex) {
-  if (DeclRefExpr* dr = dyn_cast<DeclRefExpr>(ex->IgnoreParenCasts()))
-    if (VarDecl *vd = dyn_cast<VarDecl>(dr->getDecl()))
-      if (isTrackedVar(vd))
-        return FindVarResult(vd, dr);
-
-  return FindVarResult(0, 0);
-}
-
 void TransferFunctions::VisitBinaryOperator(clang::BinaryOperator *bo) {
   if (bo->isAssignmentOp()) {
     const FindVarResult &res = findBlockVarDecl(bo->getLHS());
diff --git a/test/SemaObjC/uninit-variables.m b/test/SemaObjC/uninit-variables.m
new file mode 100644 (file)
index 0000000..f3917f3
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fblocks %s -verify
+
+// Duplicated from uninit-variables.c.
+// Test just to ensure the analysis is working.
+int test1() {
+  int x; // expected-warning{{use of uninitialized variable 'x'}} expected-note{{add initialization to silence this warning}}
+  return x; // expected-note{{variable 'x' is possibly uninitialized when used here}}
+}
+
+// Test ObjC fast enumeration.
+void test2() {
+  id collection = 0;
+  for (id obj in collection) {
+    if (0 == obj) // no-warning
+      break;
+  }
+}
+
+void test3() {
+  id collection = 0;
+  id obj;
+  for (obj in collection) { // no-warning
+    if (0 == obj) // no-warning
+      break;
+  }
+}
+