Index: clang/lib/Analysis/RetainSummaryManager.cpp =================================================================== --- clang/lib/Analysis/RetainSummaryManager.cpp +++ clang/lib/Analysis/RetainSummaryManager.cpp @@ -146,8 +146,15 @@ return !(match(SubclassM, *D, D->getASTContext()).empty()); } ++static bool isExactClass(const Decl *D, StringRef ClassName) { ++ using namespace ast_matchers; ++ DeclarationMatcher sameClassM = ++ cxxRecordDecl(hasName(std::string(ClassName))); ++ return !(match(sameClassM, *D, D->getASTContext()).empty()); ++} ++ static bool isOSObjectSubclass(const Decl *D) { -- return D && isSubclass(D, "OSMetaClassBase"); ++ return D && isSubclass(D, "OSMetaClassBase") && !isExactClass(D, "OSMetaClass"); } static bool isOSObjectDynamicCast(StringRef S) { Index: clang/test/Analysis/os_object_base.h =================================================================== --- clang/test/Analysis/os_object_base.h +++ clang/test/Analysis/os_object_base.h @@ -68,6 +68,8 @@ struct OSMetaClass : public OSMetaClassBase { virtual OSObject * alloc() const; static OSObject * allocClassWithName(const char * name); ++ static const OSMetaClass * copyMetaClassWithName(const char * name); ++ void releaseMetaClass() const; virtual ~OSMetaClass(){} }; Index: clang/test/Analysis/osobject-retain-release.cpp =================================================================== --- clang/test/Analysis/osobject-retain-release.cpp +++ clang/test/Analysis/osobject-retain-release.cpp @@ -721,6 +721,16 @@ obj->release(); } ++void test_osmetaclass_release(){ ++ const char *name = "no_name"; ++ const OSMetaClass *meta = OSMetaClass::copyMetaClassWithName(name); ++ if (!meta) { ++ return; ++ } else { ++ meta->releaseMetaClass(); ++ } ++} ++ class SampleClass { public: OSObjectPtr field;