]> granicus.if.org Git - clang/commitdiff
objective-C ARC: under -Wexplicit-ownership-type diagnose those
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 30 Aug 2012 23:56:02 +0000 (23:56 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 30 Aug 2012 23:56:02 +0000 (23:56 +0000)
method parameter types which are reference to an objective-C
pointer to object with no explicit ownership. // rdar://10907090

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclObjC.cpp
test/SemaObjC/arc-objc-lifetime.m
test/SemaObjCXX/arc-objc-lifetime.mm [new file with mode: 0644]

index b8d1c6901ae673c2d6f1613feee9ab7481637b77..8e9f2821abf8fcfa15aba0ed2c588e7cdf7ea40f 100644 (file)
@@ -3549,6 +3549,9 @@ def err_arc_illegal_selector : Error<
   "ARC forbids use of %0 in a @selector">;
 def err_arc_illegal_method_def : Error<
   "ARC forbids implementation of %0">;
+def warn_arc_strong_pointer_objc_pointer : Warning<
+  "method parameter of type %0 with no explicit ownership">,
+  InGroup<DiagGroup<"explicit-ownership-type">>, DefaultIgnore;
   
 } // end "ARC Restrictions" category
   
index 457cb1b9757df340d5421bfd4485cf27c89af32d..f4d63faaafabe886301bf80ec1ae449c8bc6a1a3 100644 (file)
@@ -282,6 +282,26 @@ void Sema::AddAnyMethodToGlobalPool(Decl *D) {
     AddFactoryMethodToGlobalPool(MDecl, true);
 }
 
+/// StrongPointerToObjCPointer - returns true when pointer to ObjC pointer
+/// is __strong, or when it is any other type. It returns false when
+/// pointer to ObjC pointer is not __strong.
+static bool
+StrongPointerToObjCPointer(Sema &S, ParmVarDecl *Param) {
+  QualType T = Param->getType();
+  if (!T->isObjCIndirectLifetimeType())
+    return true;
+  if (!T->isPointerType() && !T->isReferenceType())
+    return true;
+  T = T->isPointerType() 
+        ? T->getAs<PointerType>()->getPointeeType() 
+        : T->getAs<ReferenceType>()->getPointeeType();
+  if (T->isObjCLifetimeType()) {
+    Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime();
+    return lifetime == Qualifiers::OCL_Strong;
+  }
+  return true;
+}
+
 /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
 /// and user declared, in the method definition's AST.
 void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
@@ -313,6 +333,12 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
         RequireCompleteType(Param->getLocation(), Param->getType(),
                             diag::err_typecheck_decl_incomplete_type))
           Param->setInvalidDecl();
+    if (!Param->isInvalidDecl() &&
+        getLangOpts().ObjCAutoRefCount &&
+        !StrongPointerToObjCPointer(*this, Param))
+      Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<
+            Param->getType();
+    
     if ((*PI)->getIdentifier())
       PushOnScopeChains(*PI, FnBodyScope);
   }
index 03260e8cdd4a0b9cd7230cb1f0c0a000339566ca..d47428d1d60729e4435e51655b62bb953e4efcba 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
-// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -fblocks -Wexplicit-ownership-type  -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -fblocks -Wexplicit-ownership-type -verify -Wno-objc-root-class %s
 // rdar://10244607
 
 typedef const struct __CFString * CFStringRef;
@@ -40,3 +40,19 @@ __strong I *(__strong (test3)); // expected-error {{the type 'I *__strong' is al
 __unsafe_unretained __typeof__(test3) test4;
 typedef __strong I *strong_I;
 __unsafe_unretained strong_I test5;
+
+// rdar://10907090
+typedef void (^T) ();
+@interface NSObject @end
+@protocol P;
+@interface Radar10907090 @end
+
+@implementation Radar10907090
+- (void) MMM : (NSObject*) arg0 : (NSObject<P>**)arg : (id) arg1 : (id<P>*) arg2 {} // expected-warning {{method parameter of type 'NSObject<P> *__autoreleasing *' with no explicit ownership}} \
+                                       // expected-warning {{method parameter of type '__autoreleasing id<P> *' with no explicit ownership}}
+- (void) MM : (NSObject*) arg0 : (__strong NSObject**)arg : (id) arg1 : (__strong id*) arg2 {}
+- (void) M : (NSObject**)arg0 : (id*)arg {} // expected-warning {{method parameter of type 'NSObject *__autoreleasing *' with no explicit ownership}} \
+                                            // expected-warning {{method parameter of type '__autoreleasing id *' with no explicit ownership}}
+- (void) N : (__strong NSObject***) arg0 : (__strong NSObject<P>***)arg : (float**) arg1 : (double) arg2 {} 
+- (void) BLOCK : (T*) arg0 : (T)arg  : (__strong T*) arg1 {} // expected-warning {{method parameter of type '__autoreleasing T *' (aka 'void (^__autoreleasing *)()') with no explicit ownership}}
+@end
diff --git a/test/SemaObjCXX/arc-objc-lifetime.mm b/test/SemaObjCXX/arc-objc-lifetime.mm
new file mode 100644 (file)
index 0000000..634fe14
--- /dev/null
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -fblocks -Wexplicit-ownership-type -verify -Wno-objc-root-class %s
+// rdar://10244607
+
+typedef const struct __CFString * CFStringRef;
+@class NSString;
+
+NSString *CFBridgingRelease();
+
+typedef NSString * PNSString;
+
+typedef __autoreleasing NSString * AUTORELEASEPNSString;
+
+@interface I @end
+
+@implementation I
+- (CFStringRef)myString
+{
+    CFStringRef myString =
+      (__bridge CFStringRef) (__strong NSString *)CFBridgingRelease(); // expected-error {{explicit ownership qualifier on cast result has no effect}}
+
+    myString =
+      (__bridge CFStringRef) (__autoreleasing PNSString) CFBridgingRelease(); // expected-error {{explicit ownership qualifier on cast result has no effect}}
+    myString =
+      (__bridge CFStringRef) (AUTORELEASEPNSString) CFBridgingRelease(); // OK
+    myString =
+      (__bridge CFStringRef) (typeof(__strong NSString *)) CFBridgingRelease(); // expected-error {{explicit ownership qualifier on cast result has no effect}}
+    return myString;
+}
+
+- (void)decodeValueOfObjCType:(const char *)type at:(void *)addr {
+        __autoreleasing id *stuff = (__autoreleasing id *)addr;
+}
+@end
+
+// rdar://problem/10711456
+__strong I *__strong test1; // expected-error {{the type 'I *__strong' is already explicitly ownership-qualified}}
+__strong I *(__strong test2); // expected-error {{the type 'I *__strong' is already explicitly ownership-qualified}}
+__strong I *(__strong (test3)); // expected-error {{the type 'I *__strong' is already explicitly ownership-qualified}}
+__unsafe_unretained __typeof__(test3) test4;
+typedef __strong I *strong_I;
+__unsafe_unretained strong_I test5;
+
+// rdar://10907090
+typedef void (^T) ();
+@interface NSObject @end
+@protocol P;
+@interface Radar10907090 @end
+
+@implementation Radar10907090
+- (void) MMM : (NSObject*) arg0 : (NSObject<P>*&)arg : (id) arg1 : (id<P>&) arg2 {} // expected-warning {{method parameter of type 'NSObject<P> *__autoreleasing &' with no explicit ownership}} \
+                                       // expected-warning {{method parameter of type '__autoreleasing id<P> &' with no explicit ownership}}
+- (void) MM : (NSObject*) arg0 : (__strong NSObject**)arg : (id) arg1 : (__strong id*) arg2 {}
+- (void) M : (NSObject**)arg0 : (id*)arg {} // expected-warning {{method parameter of type 'NSObject *__autoreleasing *' with no explicit ownership}} \
+                                            // expected-warning {{method parameter of type '__autoreleasing id *' with no explicit ownership}}
+- (void) N : (__strong NSObject***) arg0 : (__strong NSObject<P>***)arg : (float**) arg1 : (double) arg2 {} 
+- (void) BLOCK : (T&) arg0 : (T)arg  : (__strong T*) arg1 {} // expected-warning {{method parameter of type '__autoreleasing T &' (aka 'void (^__autoreleasing &)()') with no explicit ownership}}
+@end