diff --git a/clang/lib/Analysis/RetainSummaryManager.cpp b/clang/lib/Analysis/RetainSummaryManager.cpp --- a/clang/lib/Analysis/RetainSummaryManager.cpp +++ b/clang/lib/Analysis/RetainSummaryManager.cpp @@ -146,14 +146,20 @@ return !(match(SubclassM, *D, D->getASTContext()).empty()); } -static bool isOSObjectSubclass(const Decl *D) { - return D && isSubclass(D, "OSMetaClassBase"); +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 isOSObjectDynamicCast(StringRef S) { - return S == "safeMetaCast"; +static bool isOSObjectSubclass(const Decl *D) { + return D && isSubclass(D, "OSMetaClassBase") && + !isExactClass(D, "OSMetaClass"); } +static bool isOSObjectDynamicCast(StringRef S) { return S == "safeMetaCast"; } + static bool isOSObjectRequiredCast(StringRef S) { return S == "requiredMetaCast"; } diff --git a/clang/test/Analysis/os_object_base.h b/clang/test/Analysis/os_object_base.h --- a/clang/test/Analysis/os_object_base.h +++ b/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(){} }; diff --git a/clang/test/Analysis/osobject-retain-release.cpp b/clang/test/Analysis/osobject-retain-release.cpp --- a/clang/test/Analysis/osobject-retain-release.cpp +++ b/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;