From 1ea800c4ca76d5bb41aa8a1e0a6c7628b9fff28d Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 27 Jan 2011 02:01:31 +0000 Subject: [PATCH] Teach -Wuninitialized about ObjC fast enumeration loops. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124347 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/UninitializedValuesV2.cpp | 47 +++++++++++++++++++++----- test/SemaObjC/uninit-variables.m | 27 +++++++++++++++ 2 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 test/SemaObjC/uninit-variables.m diff --git a/lib/Analysis/UninitializedValuesV2.cpp b/lib/Analysis/UninitializedValuesV2.cpp index 3263054959..71a62f7e19 100644 --- a/lib/Analysis/UninitializedValuesV2.cpp +++ b/lib/Analysis/UninitializedValuesV2.cpp @@ -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(ex->IgnoreParenCasts())) + if (VarDecl *vd = dyn_cast(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(element)) { + vd = cast(ds->getSingleDecl()); + if (!isTrackedVar(vd)) + vd = 0; + } + else { + // Initialize the value of the reference variable. + const FindVarResult &res = findBlockVarDecl(cast(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(ex->IgnoreParenCasts())) - if (VarDecl *vd = dyn_cast(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 index 0000000000..f3917f3922 --- /dev/null +++ b/test/SemaObjC/uninit-variables.m @@ -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; + } +} + -- 2.40.0