[cfe-commits] r162398 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp lib/StaticAnalyzer/Checkers/Checkers.td test/Analysis/test-objc-non-nil-return-value-checker.m
Anna Zaks
ganna at apple.com
Wed Aug 22 14:19:56 PDT 2012
Author: zaks
Date: Wed Aug 22 16:19:56 2012
New Revision: 162398
URL: http://llvm.org/viewvc/llvm-project?rev=162398&view=rev
Log:
[analyzer] Add osx.cocoa.NonNilReturnValue checker.
The checker adds assumptions that the return values from the known APIs
are non-nil. Teach the checker about NSArray/NSMutableArray/NSOrderedSet
objectAtIndex, objectAtIndexedSubscript.
Added:
cfe/trunk/test/Analysis/test-objc-non-nil-return-value-checker.m
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp?rev=162398&r1=162397&r2=162398&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp Wed Aug 22 16:19:56 2012
@@ -716,6 +716,47 @@
C.addTransition(State);
}
+namespace {
+/// \class ObjCNonNilReturnValueChecker
+/// \brief The checker restricts the return values of APIs known to never
+/// return nil.
+class ObjCNonNilReturnValueChecker
+ : public Checker<check::PostObjCMessage> {
+ mutable bool Initialized;
+ mutable Selector ObjectAtIndex;
+ mutable Selector ObjectAtIndexedSubscript;
+public:
+ void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
+};
+}
+
+void ObjCNonNilReturnValueChecker::checkPostObjCMessage(const ObjCMethodCall &M,
+ CheckerContext &C)
+ const {
+ ProgramStateRef State = C.getState();
+
+ if (!Initialized) {
+ ASTContext &Ctx = C.getASTContext();
+ ObjectAtIndex = GetUnarySelector("objectAtIndex", Ctx);
+ ObjectAtIndexedSubscript = GetUnarySelector("objectAtIndexedSubscript", Ctx);
+ }
+
+ // Check the receiver type.
+ if (const ObjCInterfaceDecl *Interface = M.getReceiverInterface()) {
+ FoundationClass Cl = findKnownClass(Interface);
+ if (Cl == FC_NSArray || Cl == FC_NSOrderedSet) {
+ Selector Sel = M.getSelector();
+ if (Sel == ObjectAtIndex || Sel == ObjectAtIndexedSubscript) {
+ // Go ahead and assume the value is non-nil.
+ SVal Val = State->getSVal(M.getOriginExpr(), C.getLocationContext());
+ if (!isa<DefinedOrUnknownSVal>(Val))
+ return;
+ State = State->assume(cast<DefinedOrUnknownSVal>(Val), true);
+ C.addTransition(State);
+ }
+ }
+ }
+}
//===----------------------------------------------------------------------===//
// Check registration.
@@ -744,3 +785,7 @@
void ento::registerObjCLoopChecker(CheckerManager &mgr) {
mgr.registerChecker<ObjCLoopChecker>();
}
+
+void ento::registerObjCNonNilReturnValueChecker(CheckerManager &mgr) {
+ mgr.registerChecker<ObjCNonNilReturnValueChecker>();
+}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=162398&r1=162397&r2=162398&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Wed Aug 22 16:19:56 2012
@@ -397,6 +397,10 @@
HelpText<"Improved modeling of loops using Cocoa collection types">,
DescFile<"BasicObjCFoundationChecks.cpp">;
+def ObjCNonNilReturnValueChecker : Checker<"NonNilReturnValue">,
+ HelpText<"Model the APIs that are guaranteed to return a non-nil value">,
+ DescFile<"BasicObjCFoundationChecks.cpp">;
+
def NSErrorChecker : Checker<"NSError">,
HelpText<"Check usage of NSError** parameters">,
DescFile<"NSErrorChecker.cpp">;
Added: cfe/trunk/test/Analysis/test-objc-non-nil-return-value-checker.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/test-objc-non-nil-return-value-checker.m?rev=162398&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/test-objc-non-nil-return-value-checker.m (added)
+++ cfe/trunk/test/Analysis/test-objc-non-nil-return-value-checker.m Wed Aug 22 16:19:56 2012
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=osx.cocoa.NonNilReturnValue,debug.ExprInspection -verify %s
+
+typedef unsigned int NSUInteger;
+typedef signed char BOOL;
+
+ at protocol NSObject - (BOOL)isEqual:(id)object; @end
+
+ at interface NSObject <NSObject> {}
++(id)alloc;
++(id)new;
+-(id)init;
+-(id)autorelease;
+-(id)copy;
+- (Class)class;
+-(id)retain;
+ at end
+
+ at interface NSArray : NSObject
+- (id)objectAtIndex:(unsigned long)index;
+ at end
+
+ at interface NSArray (NSExtendedArray)
+- (id)objectAtIndexedSubscript:(NSUInteger)idx;
+ at end
+
+ at interface NSMutableArray : NSArray
+- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
+ at end
+
+ at interface NSOrderedSet : NSObject
+ at end
+ at interface NSOrderedSet (NSOrderedSetCreation)
+- (id)objectAtIndexedSubscript:(NSUInteger)idx;
+ at end
+
+void clang_analyzer_eval(id);
+
+void assumeThatNSArrayObjectAtIndexIsNeverNull(NSArray *A, NSUInteger i) {
+ clang_analyzer_eval([A objectAtIndex: i]); // expected-warning {{TRUE}}
+ id subscriptObj = A[1];
+ clang_analyzer_eval(subscriptObj); // expected-warning {{TRUE}}
+}
+
+void assumeThatNSMutableArrayObjectAtIndexIsNeverNull(NSMutableArray *A, NSUInteger i) {
+ clang_analyzer_eval([A objectAtIndex: i]); // expected-warning {{TRUE}}
+}
+
+void assumeThatNSArrayObjectAtIndexedSubscriptIsNeverNull(NSOrderedSet *A, NSUInteger i) {
+ clang_analyzer_eval(A[i]); // expected-warning {{TRUE}}
+}
\ No newline at end of file
More information about the cfe-commits
mailing list