From b62bdce3e981ea4f357126bc391be1cbc1efa4df Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 8 Mar 2011 20:05:26 +0000 Subject: [PATCH] Make the Objective-C checker look for subclasses of NSString instead of just NSString and NSMutableString. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127268 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/BasicObjCFoundationChecks.cpp | 27 ++++++++++--------- test/Analysis/NSString.m | 7 +++++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index e002a29379..f7a1ebe386 100644 --- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -41,20 +41,21 @@ public: // Utility functions. //===----------------------------------------------------------------------===// -static const ObjCInterfaceType* GetReceiverType(const ObjCMessage &msg) { +static const char* GetReceiverNameType(const ObjCMessage &msg) { if (const ObjCInterfaceDecl *ID = msg.getReceiverInterface()) - return ID->getTypeForDecl()->getAs(); - return NULL; + return ID->getIdentifier()->getNameStart(); + return 0; } -static const char* GetReceiverNameType(const ObjCMessage &msg) { - if (const ObjCInterfaceType *ReceiverType = GetReceiverType(msg)) - return ReceiverType->getDecl()->getIdentifier()->getNameStart(); - return NULL; -} +static bool isReceiverClassOrSuperclass(const ObjCInterfaceDecl *ID, + llvm::StringRef ClassName) { + if (ID->getIdentifier()->getName() == ClassName) + return true; + + if (const ObjCInterfaceDecl *Super = ID->getSuperClass()) + return isReceiverClassOrSuperclass(Super, ClassName); -static bool isNSString(llvm::StringRef ClassName) { - return ClassName == "NSString" || ClassName == "NSMutableString"; + return false; } static inline bool isNil(SVal X) { @@ -98,11 +99,11 @@ void NilArgChecker::WarnNilArg(CheckerContext &C, void NilArgChecker::checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const { - const ObjCInterfaceType *ReceiverType = GetReceiverType(msg); - if (!ReceiverType) + const ObjCInterfaceDecl *ID = msg.getReceiverInterface(); + if (!ID) return; - if (isNSString(ReceiverType->getDecl()->getIdentifier()->getName())) { + if (isReceiverClassOrSuperclass(ID, "NSString")) { Selector S = msg.getSelector(); if (S.isUnarySelector()) diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m index 16b527fcc7..76bf4a1471 100644 --- a/test/Analysis/NSString.m +++ b/test/Analysis/NSString.m @@ -190,6 +190,13 @@ void f13(void) { CFRelease(ref); // expected-warning{{Reference-counted object is used after it is released}} } +@interface MyString : NSString +@end + +void f14(MyString *s) { + [s compare:0]; // expected-warning {{Argument to 'MyString' method 'compare:' cannot be nil.}} +} + // Test regular use of -autorelease @interface TestAutorelease -(NSString*) getString; -- 2.40.0