]> granicus.if.org Git - clang/commitdiff
Teach -Wuninitialized to recognize common "noreturn" idioms in
authorTed Kremenek <kremenek@apple.com>
Thu, 13 Sep 2012 00:21:35 +0000 (00:21 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 13 Sep 2012 00:21:35 +0000 (00:21 +0000)
Objective-C related to NSException.

Fixes <rdar://problem/12287498>

I debated whether or not this logic should be sunk into the CFG
itself.  It's not clear if we should, as different analyses may
wish to have different policies.  We can re-evaluate this in the
future.

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

lib/Analysis/UninitializedValues.cpp
test/SemaObjC/uninit-variables.m

index 47f2cf67c8e6d3b7c767e70858363b71ca115bcb..8ebee9614ac4b261ffac460f01b2f325e1b5027d 100644 (file)
@@ -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.
 //====------------------------------------------------------------------------//
index cad0f54b2dd3a1965a5299d96f0b6b57bd962fe6..a3312264f0c2c4d432f837786d60690191395229 100644 (file)
@@ -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}}
+}