r344311 - [analyzer] Retain count checker for OSObject: recognize OSDynamicCast

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 11 15:59:16 PDT 2018


Author: george.karpenkov
Date: Thu Oct 11 15:59:16 2018
New Revision: 344311

URL: http://llvm.org/viewvc/llvm-project?rev=344311&view=rev
Log:
[analyzer] Retain count checker for OSObject: recognize OSDynamicCast

For now, tresting the cast as a no-op, and disregarding the case where
the output becomes null due to the type mismatch.

rdar://45174557

Differential Revision: https://reviews.llvm.org/D53156

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
    cfe/trunk/test/Analysis/osobject-retain-release.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp?rev=344311&r1=344310&r2=344311&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp Thu Oct 11 15:59:16 2018
@@ -774,12 +774,23 @@ bool RetainCountChecker::evalCall(const
   // annotate attribute. If it does, we will not inline it.
   bool hasTrustedImplementationAnnotation = false;
 
+  const LocationContext *LCtx = C.getLocationContext();
+
+  // Process OSDynamicCast: should just return the first argument.
+  // For now, tresting the cast as a no-op, and disregarding the case where
+  // the output becomes null due to the type mismatch.
+  if (FD->getNameAsString() == "safeMetaCast") {
+    state = state->BindExpr(CE, LCtx, 
+                            state->getSVal(CE->getArg(0), LCtx));
+    C.addTransition(state);
+    return true;
+  }
+
   // See if it's one of the specific functions we know how to eval.
   if (!SmrMgr.canEval(CE, FD, hasTrustedImplementationAnnotation))
     return false;
 
   // Bind the return value.
-  const LocationContext *LCtx = C.getLocationContext();
   SVal RetVal = state->getSVal(CE->getArg(0), LCtx);
   if (RetVal.isUnknown() ||
       (hasTrustedImplementationAnnotation && !ResultTy.isNull())) {

Modified: cfe/trunk/test/Analysis/osobject-retain-release.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/osobject-retain-release.cpp?rev=344311&r1=344310&r2=344311&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/osobject-retain-release.cpp (original)
+++ cfe/trunk/test/Analysis/osobject-retain-release.cpp Thu Oct 11 15:59:16 2018
@@ -1,18 +1,46 @@
 // RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-config osx.cocoa.RetainCount:CheckOSObject=true -analyzer-output=text -verify %s
 
+struct OSMetaClass;
+
+#define OSTypeID(type)   (type::metaClass)
+
+#define OSDynamicCast(type, inst)   \
+    ((type *) OSMetaClassBase::safeMetaCast((inst), OSTypeID(type)))
+
 struct OSObject {
   virtual void retain();
   virtual void release();
-
   virtual ~OSObject(){}
+
+  static OSObject *generateObject(int);
+
+  static const OSMetaClass * const metaClass;
 };
 
 struct OSArray : public OSObject {
   unsigned int getCount();
 
   static OSArray *withCapacity(unsigned int capacity);
+
+  static const OSMetaClass * const metaClass;
+};
+
+struct OSMetaClassBase {
+  static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
 };
 
+void check_dynamic_cast() {
+  OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1));
+  arr->release();
+}
+
+void check_dynamic_cast_null_check() {
+  OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1));
+  if (!arr)
+    return;
+  arr->release();
+}
+
 void use_after_release() {
   OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
   arr->release(); // expected-note{{Object released}}




More information about the cfe-commits mailing list