]> granicus.if.org Git - clang/commitdiff
Teach the static analyzer's interpretation of Cocoa conventions to
authorDouglas Gregor <dgregor@apple.com>
Wed, 6 Jul 2011 16:00:34 +0000 (16:00 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 6 Jul 2011 16:00:34 +0000 (16:00 +0000)
obey the objc_method_family attribute when provided. Fixes
<rdar://problem/9726279>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134493 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/DomainSpecific/CocoaConventions.h
lib/Analysis/CocoaConventions.cpp
lib/StaticAnalyzer/Core/CFRefCount.cpp
test/Analysis/retain-release.m

index 8c100964f28b741b10fed451f973ba4d0a9ece14..43e7bd236e1d14fabdedb936a1c255b54bc3a60d 100644 (file)
 #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,
index f9cbe12ebc06a7fe02c788d9dda9e595478fa3a3..9068ca39493e12f1c1b91899b02afaead874ba51 100644 (file)
@@ -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<ObjCMethodFamilyAttr>()? MD->getMethodFamily() 
+                                                   : S.getMethodFamily()) {
   case OMF_None:
   case OMF_autorelease:
   case OMF_dealloc:
index 70646e9f8bd18fd7ece6e46469315065f18e7ce5..326ba1c8d27470a52cc1bf8d74a7b9ab477e6319 100644 (file)
@@ -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);
index 5c67941c426c9e868a6874a0baee34ceb87d37f5..65fb82dad18dd9d8c5c1f5f21a7321f22166b2f9 100644 (file)
@@ -1462,3 +1462,28 @@ extern void rdar_9234108_helper(void *key, void * CF_CONSUMED value);
 void rdar_9234108() {
   rdar_9234108_helper(0, CFStringCreate());
 }
+
+// <rdar://problem/9726279> - 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];
+}