From: Douglas Gregor Date: Wed, 6 Jul 2011 16:00:34 +0000 (+0000) Subject: Teach the static analyzer's interpretation of Cocoa conventions to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=786dcd9dca76e3780fdb9642c0db33ed13db1187;p=clang Teach the static analyzer's interpretation of Cocoa conventions to obey the objc_method_family attribute when provided. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134493 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h index 8c100964f2..43e7bd236e 100644 --- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -17,15 +17,19 @@ #include "clang/AST/Type.h" namespace clang { + +class ObjCMethodDecl; + namespace ento { namespace cocoa { enum NamingConvention { NoConvention, CreateRule, InitRule }; - NamingConvention deriveNamingConvention(Selector S); + NamingConvention deriveNamingConvention(Selector S, const ObjCMethodDecl *MD); - static inline bool followsFundamentalRule(Selector S) { - return deriveNamingConvention(S) == CreateRule; + static inline bool followsFundamentalRule(Selector S, + const ObjCMethodDecl *MD) { + return deriveNamingConvention(S, MD) == CreateRule; } bool isRefType(QualType RetTy, llvm::StringRef Prefix, diff --git a/lib/Analysis/CocoaConventions.cpp b/lib/Analysis/CocoaConventions.cpp index f9cbe12ebc..9068ca3949 100644 --- a/lib/Analysis/CocoaConventions.cpp +++ b/lib/Analysis/CocoaConventions.cpp @@ -36,8 +36,10 @@ using llvm::StringRef; // not release it." // -cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) { - switch (S.getMethodFamily()) { +cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S, + const ObjCMethodDecl *MD) { + switch (MD && MD->hasAttr()? MD->getMethodFamily() + : S.getMethodFamily()) { case OMF_None: case OMF_autorelease: case OMF_dealloc: diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp index 70646e9f8b..326ba1c8d2 100644 --- a/lib/StaticAnalyzer/Core/CFRefCount.cpp +++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp @@ -1349,7 +1349,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD, if (cocoa::isCocoaObjectRef(RetTy)) { // EXPERIMENTAL: assume the Cocoa conventions for all objects returned // by instance methods. - RetEffect E = cocoa::followsFundamentalRule(S) + RetEffect E = cocoa::followsFundamentalRule(S, MD) ? ObjCAllocRetE : RetEffect::MakeNotOwned(RetEffect::ObjC); return getPersistentSummary(E, ReceiverEff, MayEscape); @@ -1357,7 +1357,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD, // Look for methods that return an owned core foundation object. if (cocoa::isCFObjectRef(RetTy)) { - RetEffect E = cocoa::followsFundamentalRule(S) + RetEffect E = cocoa::followsFundamentalRule(S, MD) ? RetEffect::MakeOwned(RetEffect::CF, true) : RetEffect::MakeNotOwned(RetEffect::CF); @@ -1428,7 +1428,7 @@ RetainSummaryManager::getInstanceMethodSummary(Selector S, assert(ScratchArgs.isEmpty()); // "initXXX": pass-through for receiver. - if (cocoa::deriveNamingConvention(S) == cocoa::InitRule) + if (cocoa::deriveNamingConvention(S, MD) == cocoa::InitRule) Summ = getInitMethodSummary(RetTy); else Summ = getCommonMethodSummary(MD, S, RetTy); diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 5c67941c42..65fb82dad1 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1462,3 +1462,28 @@ extern void rdar_9234108_helper(void *key, void * CF_CONSUMED value); void rdar_9234108() { rdar_9234108_helper(0, CFStringCreate()); } + +// - Make sure that objc_method_family works +// to override naming conventions. +struct TwoDoubles { + double one; + double two; +}; +typedef struct TwoDoubles TwoDoubles; + +@interface NSValue (Mine) +- (id)_prefix_initWithTwoDoubles:(TwoDoubles)twoDoubles __attribute__((objc_method_family(init))); +@end + +@implementation NSValue (Mine) +- (id)_prefix_initWithTwoDoubles:(TwoDoubles)twoDoubles +{ + return [self init]; +} +@end + +void rdar9726279() { + TwoDoubles twoDoubles = { 0.0, 0.0 }; + NSValue *value = [[NSValue alloc] _prefix_initWithTwoDoubles:twoDoubles]; + [value release]; +}