diff options
-rw-r--r-- | lib/Analysis/UninitializedValues.cpp | 20 | ||||
-rw-r--r-- | test/SemaObjC/uninit-variables.m | 29 |
2 files changed, 45 insertions, 4 deletions
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index 47f2cf67c8..8ebee9614a 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -22,6 +22,7 @@ #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h" #include "clang/Analysis/Analyses/UninitializedValues.h" +#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" #include "llvm/Support/SaveAndRestore.h" using namespace clang; @@ -412,6 +413,7 @@ class TransferFunctions : public StmtVisitor<TransferFunctions> { const CFGBlock *block; AnalysisDeclContext ∾ const ClassifyRefs &classification; + ObjCNoReturn objCNoRet; UninitVariablesHandler *handler; public: @@ -420,16 +422,18 @@ public: const ClassifyRefs &classification, UninitVariablesHandler *handler) : vals(vals), cfg(cfg), block(block), ac(ac), - classification(classification), handler(handler) {} + classification(classification), objCNoRet(ac.getASTContext()), + handler(handler) {} void reportUse(const Expr *ex, const VarDecl *vd); - void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); + void VisitBinaryOperator(BinaryOperator *bo); void VisitBlockExpr(BlockExpr *be); void VisitCallExpr(CallExpr *ce); - void VisitDeclStmt(DeclStmt *ds); void VisitDeclRefExpr(DeclRefExpr *dr); - void VisitBinaryOperator(BinaryOperator *bo); + void VisitDeclStmt(DeclStmt *ds); + void VisitObjCForCollectionStmt(ObjCForCollectionStmt *FS); + void VisitObjCMessageExpr(ObjCMessageExpr *ME); bool isTrackedVar(const VarDecl *vd) { return ::isTrackedVar(vd, cast<DeclContext>(ac.getDecl())); @@ -689,6 +693,14 @@ void TransferFunctions::VisitDeclStmt(DeclStmt *DS) { } } +void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) { + // If the Objective-C message expression is an implicit no-return that + // is not modeled in the CFG, set the tracked dataflow values to Unknown. + if (objCNoRet.isImplicitNoReturn(ME)) { + vals.setAllScratchValues(Unknown); + } +} + //------------------------------------------------------------------------====// // High-level "driver" logic for uninitialized values analysis. //====------------------------------------------------------------------------// diff --git a/test/SemaObjC/uninit-variables.m b/test/SemaObjC/uninit-variables.m index cad0f54b2d..a3312264f0 100644 --- a/test/SemaObjC/uninit-variables.m +++ b/test/SemaObjC/uninit-variables.m @@ -1,5 +1,16 @@ // RUN: %clang_cc1 -fsyntax-only -Wuninitialized -fsyntax-only -fblocks %s -verify +#include <stdarg.h> + +@interface NSObject {} @end +@class NSString; + +@interface NSException ++ (void)raise:(NSString *)name format:(NSString *)format, ...; ++ (void)raise:(NSString *)name format:(NSString *)format arguments:(va_list)argList; +- (void)raise; +@end + // Duplicated from uninit-variables.c. // Test just to ensure the analysis is working. int test1() { @@ -25,3 +36,21 @@ void test3() { } } +int test_abort_on_exceptions(int y, NSException *e, NSString *s, int *z, ...) { + int x; // expected-note {{initialize the variable 'x' to silence this warning}} + if (y == 1) { + va_list alist; + va_start(alist, z); + [NSException raise:@"Blah" format:@"Blah %@" arguments:alist]; + return x; + } + else if (y == 2) { + [NSException raise:@"Blah" format:s]; + return x; + } + else if (y == 3) { + [e raise]; + return x; + } + return x; // expected-warning {{variable 'x' is uninitialized when used here}} +} |