[cfe-commits] r48898 - in /cfe/trunk: lib/Analysis/BasicObjCFoundationChecks.cpp test/Analysis-Apple/NSString.m

Ted Kremenek kremenek at apple.com
Thu Mar 27 15:05:33 PDT 2008


Author: kremenek
Date: Thu Mar 27 17:05:32 2008
New Revision: 48898

URL: http://llvm.org/viewvc/llvm-project?rev=48898&view=rev
Log:
Expanded NSString checking to check for nil for a few more methods.

Modified:
    cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
    cfe/trunk/test/Analysis-Apple/NSString.m

Modified: cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp?rev=48898&r1=48897&r2=48898&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp Thu Mar 27 17:05:32 2008
@@ -25,6 +25,7 @@
 #include "llvm/Support/Compiler.h"
 
 #include <vector>
+#include <sstream>
 
 using namespace clang;
   
@@ -43,7 +44,10 @@
   bool isNSString(ObjCInterfaceType* T, const char* suffix);
   bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
       
-  void Warn(NodeTy* N, Expr* E, const char *msg);
+  void Warn(NodeTy* N, Expr* E, const std::string& s);  
+  void WarnNilArg(NodeTy* N, Expr* E);
+  
+  bool CheckNilArg(NodeTy* N, unsigned Arg);
 
 public:
   BasicObjCFoundationChecks(ASTContext& ctx, ValueStateManager* vmgr) 
@@ -67,28 +71,39 @@
   return new BasicObjCFoundationChecks(Ctx, VMgr);  
 }
 
-
-bool BasicObjCFoundationChecks::Audit(ExplodedNode<ValueState>* N) {
-  
-  ObjCMessageExpr* ME =
-    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
-  
+static ObjCInterfaceType* GetReceiverType(ObjCMessageExpr* ME) {
   Expr* Receiver = ME->getReceiver();
   
   if (!Receiver)
-    return false;
+    return NULL;
   
   assert (Receiver->getType()->isPointerType());
-
+  
   const PointerType* T = Receiver->getType()->getAsPointerType();
+  
+  return dyn_cast<ObjCInterfaceType>(T->getPointeeType().getTypePtr());
+}
 
-  ObjCInterfaceType* ReceiverType =
-    dyn_cast<ObjCInterfaceType>(T->getPointeeType().getTypePtr());
+static const char* GetReceiverNameType(ObjCMessageExpr* ME) {
+  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
+  return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName()
+                      : NULL;
+}
+
+bool BasicObjCFoundationChecks::Audit(ExplodedNode<ValueState>* N) {
+  
+  ObjCMessageExpr* ME =
+    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
+
+  ObjCInterfaceType* ReceiverType = GetReceiverType(ME);
   
   if (!ReceiverType)
-    return false;
+    return NULL;
+  
+  const char* name = ReceiverType->getDecl()->getIdentifier()->getName();
   
-  const char* name = ReceiverType->getDecl()->getIdentifier()->getName();  
+  if (!name)
+    return false;
 
   if (name[0] != 'N' || name[1] != 'S')
     return false;
@@ -112,11 +127,9 @@
 //===----------------------------------------------------------------------===//
 
 
-void BasicObjCFoundationChecks::Warn(NodeTy* N,
-                                              Expr* E, const char *msg) {
-  
+void BasicObjCFoundationChecks::Warn(NodeTy* N, Expr* E, const std::string& s) {  
   Errors.push_back(AnnotatedPath<ValueState>());
-  Errors.back().push_back(N, msg, E);
+  Errors.back().push_back(N, s, E);
 }
 
 void BasicObjCFoundationChecks::ReportResults(Diagnostic& D) {
@@ -139,6 +152,34 @@
   }
 }
 
+void BasicObjCFoundationChecks::WarnNilArg(NodeTy* N, Expr* E) {
+
+  ObjCMessageExpr* ME =
+    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());    
+  
+  std::ostringstream os;
+  
+  os << "Argument to '" << GetReceiverNameType(ME) << "' method '"
+    << ME->getSelector().getName()
+    << "' cannot be nil.";
+  
+  Warn(N, E, os.str());
+}
+
+bool BasicObjCFoundationChecks::CheckNilArg(NodeTy* N, unsigned Arg) {
+  ObjCMessageExpr* ME =
+    cast<ObjCMessageExpr>(cast<PostStmt>(N->getLocation()).getStmt());
+  
+  Expr * E = ME->getArg(Arg);
+  
+  if (isNil(GetRVal(N->getState(), E))) {
+    WarnNilArg(N, E);
+    return true;
+  }
+  
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 // NSString checking.
 //===----------------------------------------------------------------------===//
@@ -164,27 +205,47 @@
   assert (!name.empty());
   const char* cstr = &name[0];
   unsigned len = name.size();
-  
-  
-  ValueState* St = N->getState();
-  
+      
   switch (len) {
     default:
       break;
     case 8:
-      if (!strcmp(cstr, "compare:")) {
-        // Check if the compared NSString is nil.
-        Expr * E = ME->getArg(0);
-    
-        if (isNil(GetRVal(St, E))) {
-          Warn(N, E, "Argument to NSString method 'compare:' cannot be nil.");
-          return false;
-        }
-        
-        break;
-      }
       
+      if (!strcmp(cstr, "compare:"))
+        return CheckNilArg(N, 0);
+              
       break;
+    
+    case 16:
+      if (!strcmp(cstr, "compare:options:"))
+        return CheckNilArg(N, 0);
+      
+      break;
+      
+    case 22:
+      if (!strcmp(cstr, "compare:options:range:"))
+        return CheckNilArg(N, 0);
+      
+      break;
+      
+    case 23:
+      
+      if (!strcmp(cstr, "caseInsensitiveCompare:"))
+        return CheckNilArg(N, 0);
+      
+      break;
+      
+    case 29:
+      if (!strcmp(cstr, "compare:options:range:locale:"))
+        return CheckNilArg(N, 0);
+    
+      break;    
+      
+    case 37:
+    if (!strcmp(cstr, "componentsSeparatedByCharactersInSet:"))
+      return CheckNilArg(N, 0);
+    
+    break;    
   }
   
   return false;

Modified: cfe/trunk/test/Analysis-Apple/NSString.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis-Apple/NSString.m?rev=48898&r1=48897&r2=48898&view=diff

==============================================================================
--- cfe/trunk/test/Analysis-Apple/NSString.m (original)
+++ cfe/trunk/test/Analysis-Apple/NSString.m Thu Mar 27 17:05:32 2008
@@ -2,8 +2,33 @@
 
 #include <Foundation/NSString.h>
 #include <Foundation/NSObjCRuntime.h>
+#include <Foundation/NSArray.h>
 
 NSComparisonResult f1(NSString* s) {
   NSString *aString = nil;
-  return [s compare:aString]; // expected-warning {{Argument to NSString method 'compare:' cannot be nil.}}
+  return [s compare:aString]; // expected-warning {{Argument to 'NSString' method 'compare:' cannot be nil.}}
+}
+
+NSComparisonResult f2(NSString* s) {
+  NSString *aString = nil;
+  return [s caseInsensitiveCompare:aString]; // expected-warning {{Argument to 'NSString' method 'caseInsensitiveCompare:' cannot be nil.}}
+}
+
+NSComparisonResult f3(NSString* s, NSStringCompareOptions op) {
+  NSString *aString = nil;
+  return [s compare:aString options:op]; // expected-warning {{Argument to 'NSString' method 'compare:options:' cannot be nil.}}
+}
+
+NSComparisonResult f4(NSString* s, NSStringCompareOptions op, NSRange R) {
+  NSString *aString = nil;
+  return [s compare:aString options:op range:R]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:' cannot be nil.}}
+}
+
+NSComparisonResult f5(NSString* s, NSStringCompareOptions op, NSRange R) {
+  NSString *aString = nil;
+  return [s compare:aString options:op range:R locale:nil]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:locale:' cannot be nil.}}
+}
+
+NSComparisonResult f6(NSString* s) {
+  return [s componentsSeparatedByCharactersInSet:nil]; // expected-warning {{Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil.}}
 }





More information about the cfe-commits mailing list