[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