aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Analysis/UninitializedValues.cpp20
-rw-r--r--test/SemaObjC/uninit-variables.m29
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 &ac;
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}}
+}