]> granicus.if.org Git - clang/commitdiff
Objective-C ARC. Use of non-retain/autorelease API
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 8 Aug 2014 17:31:14 +0000 (17:31 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 8 Aug 2014 17:31:14 +0000 (17:31 +0000)
for building Objective-C array literals in ARC
mode. rdar://17554063

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

include/clang/Sema/Sema.h
lib/Sema/Sema.cpp
lib/Sema/SemaExprObjC.cpp
test/CodeGenObjC/Inputs/literal-support.h
test/CodeGenObjC/arc-literals.m
test/CodeGenObjCXX/Inputs/literal-support.h
test/CodeGenObjCXX/literals.mm
test/SemaObjC/arc.m
test/SemaObjC/objc-literal-comparison.m

index ed31a9f86e2f6422ab480199883bfa9c7068886f..f82974e274aa7492e0af9e156b1fbab6818544e7 100644 (file)
@@ -685,6 +685,9 @@ public:
   /// \brief The declaration of the initWithObjects:forKeys:count: method.
   ObjCMethodDecl *InitDictionaryWithObjectsMethod;
     
+  /// \brief The declaration for + (id) alloc method used in [NSArray alloc]
+  ObjCMethodDecl *ArrayAllocObjectsMethod;
+    
   /// \brief The declaration for + (id) alloc method used in [NSDictionary alloc]
   ObjCMethodDecl *DictAllocObjectsMethod;
 
index 4ed5aa8a2870c30a5bd27007425217a5b8dfa09d..205081b656a6aa2b9f9d4c3820c30d18feb529b2 100644 (file)
@@ -98,6 +98,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     InitArrayWithObjectsMethod(nullptr),
     NSDictionaryDecl(nullptr), DictionaryWithObjectsMethod(nullptr),
     InitDictionaryWithObjectsMethod(nullptr),
+    ArrayAllocObjectsMethod(nullptr),
     DictAllocObjectsMethod(nullptr),
     GlobalNewDeleteDeclared(false),
     TUKind(TUKind),
index e4625bc98c26161a6991056e513c2f8db50ed1d4..786637c205e61831609141ff535e29c9cd5907ab 100644 (file)
@@ -630,6 +630,7 @@ ExprResult Sema::BuildObjCSubscriptExpression(SourceLocation RB, Expr *BaseExpr,
 }
 
 ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
+  bool Arc = getLangOpts().ObjCAutoRefCount;
   // Look up the NSArray class, if we haven't done so already.
   if (!NSArrayDecl) {
     NamedDecl *IF = LookupSingleName(TUScope,
@@ -649,18 +650,45 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
       return ExprError();
     }
   }
-  
-  // Find the arrayWithObjects:count: method, if we haven't done so already.
   QualType IdT = Context.getObjCIdType();
+  if (Arc && !ArrayAllocObjectsMethod) {
+    // Find +[NSArray alloc] method.
+    IdentifierInfo *II = &Context.Idents.get("alloc");
+    Selector AllocSel = Context.Selectors.getSelector(0, &II);
+    ArrayAllocObjectsMethod = NSArrayDecl->lookupClassMethod(AllocSel);
+    if (!ArrayAllocObjectsMethod && getLangOpts().DebuggerObjCLiteral) {
+      ArrayAllocObjectsMethod = ObjCMethodDecl::Create(Context,
+                                  SourceLocation(), SourceLocation(), AllocSel,
+                                  IdT,
+                                  nullptr /*TypeSourceInfo */,
+                                  Context.getTranslationUnitDecl(),
+                                  false /*Instance*/, false/*isVariadic*/,
+                                  /*isPropertyAccessor=*/false,
+                                  /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
+                                  ObjCMethodDecl::Required,
+                                  false);
+      SmallVector<ParmVarDecl *, 1> Params;
+      ArrayAllocObjectsMethod->setMethodParams(Context, Params, None);
+    }
+    if (!ArrayAllocObjectsMethod) {
+      Diag(SR.getBegin(), diag::err_undeclared_alloc);
+      return ExprError();
+    }
+  }
+  // Find the arrayWithObjects:count: method, if we haven't done so already.
   if (!ArrayWithObjectsMethod) {
     Selector
-      Sel = NSAPIObj->getNSArraySelector(NSAPI::NSArr_arrayWithObjectsCount);
-    ObjCMethodDecl *Method = NSArrayDecl->lookupClassMethod(Sel);
+      Sel = NSAPIObj->getNSArraySelector(
+        Arc? NSAPI::NSArr_initWithObjectsCount : NSAPI::NSArr_arrayWithObjectsCount);
+      ObjCMethodDecl *Method =
+        Arc? NSArrayDecl->lookupInstanceMethod(Sel)
+           : NSArrayDecl->lookupClassMethod(Sel);
     if (!Method && getLangOpts().DebuggerObjCLiteral) {
       TypeSourceInfo *ReturnTInfo = nullptr;
       Method = ObjCMethodDecl::Create(
           Context, SourceLocation(), SourceLocation(), Sel, IdT, ReturnTInfo,
-          Context.getTranslationUnitDecl(), false /*Instance*/,
+          Context.getTranslationUnitDecl(),
+          Arc /*Instance for Arc, Class for MRR*/,
           false /*isVariadic*/,
           /*isPropertyAccessor=*/false,
           /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
@@ -740,7 +768,8 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) {
 
   return MaybeBindToTemporary(
            ObjCArrayLiteral::Create(Context, Elements, Ty,
-                                    ArrayWithObjectsMethod, nullptr, SR));
+                                    ArrayWithObjectsMethod,
+                                    ArrayAllocObjectsMethod, SR));
 }
 
 ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, 
index 475c86af241f8ecf2c6115eea2ea882130d29472..caa69c24caf629317eae08bf38a24f42aab687d6 100644 (file)
@@ -30,6 +30,7 @@ typedef unsigned char BOOL;
 
 @interface NSArray (NSArrayCreation)
 + (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
+- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt;
 @end
 
 @interface NSDictionary : NSObject
index 427c65aa0546d692627524a21e4a8e477b9c7ca8..29f2b45a8087b3fa24fdbb0eb7b697b40079e1e8 100644 (file)
@@ -8,7 +8,7 @@
 // CHECK: c"numberWithUnsignedInt:\00"
 // CHECK: c"numberWithUnsignedLongLong:\00"
 // CHECK: c"numberWithChar:\00"
-// CHECK: c"arrayWithObjects:count:\00"
+// CHECK: c"initWithObjects:count:\00"
 // CHECK: c"initWithObjects:forKeys:count:\00"
 // CHECK: c"prop\00"
 
@@ -53,10 +53,12 @@ void test_array(id a, id b) {
   // CHECK-NEXT: [[T0:%.*]] = load [[CLASS_T:%.*]]** @"\01L_OBJC_CLASSLIST
   // CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8*
-  // CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
-  // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 2)
-  // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]])
-  // CHECK: call void (...)* @clang.arc.use(i8* [[V0]], i8* [[V1]])
+
+  // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[T1]], i8* [[SEL]])
+  // CHECK-NEXT: [[T9:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+  // CHECK-NEXT: [[T10:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
+  // CHECK-NEXT: [[ARRAYINIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8**, i64)*)(i8* [[ALLOC]], i8* [[T9]], i8** [[T10]], i64 2)
+  // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[V0]], i8* [[V1]])
   id arr = @[a, b];
 
   // CHECK: call void @objc_release
@@ -140,13 +142,15 @@ void test_property(B *b) {
   // Store to array.
   // CHECK-NEXT: store i8* [[V1]], i8** [[T0]]
 
-  // Invoke arrayWithObjects:count:
+  // Invoke initWithObjects:count:
   // CHECK-NEXT: [[T0:%.*]] = load [[CLASS_T]]** @"\01L_OBJC_CLASSLIST
   // CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
   // CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8*
-  // CHECK-NEXT: [[T2:%.*]] = bitcast [1 x i8*]* [[OBJECTS]] to i8**
-  // CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}}(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 1)
-  // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue(i8* [[T3]])
+
+  // CHECK-NEXT: [[ALLOC:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* [[T1]], i8* [[SEL]])
+  // CHECK-NEXT: [[T9:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+  // CHECK-NEXT: [[T10:%.*]] = bitcast [1 x i8*]* [[OBJECTS]] to i8**
+  // CHECK-NEXT: [[INIT:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8**, i64)*)(i8* [[ALLOC]], i8* [[T9]], i8** [[T10]], i64 1)
   // CHECK-NEXT: call void (...)* @clang.arc.use(i8* [[V1]])
   // CHECK-NEXT: bitcast
   // CHECK-NEXT: bitcast
index fc80d88b13d099937aa45649ee6ea66470b42487..174ec3a83cf5a5027dacf372f4546eb828e60f72 100644 (file)
@@ -30,6 +30,7 @@ typedef unsigned char BOOL;
 
 @interface NSArray (NSArrayCreation)
 + (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
+- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt;
 @end
 
 @interface NSDictionary : NSObject
index f21bba75f3747a51d83119139e4de2d301033876..42ec4bee3880bde32fd8988868c5d769639840dc 100644 (file)
@@ -33,8 +33,15 @@ void test_array() {
   // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]]
 
   // Build the array
-  // CHECK: {{invoke.*@objc_msgSend}}
-  // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+  // CHECK: [[T4:%.*]] = load [[CLASS:%.*]]** @"\01L_OBJC_CLASSLIST_REFERENCES_$_"
+  // CHECK-NEXT: [[T5:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_
+  // CHECK-NEXT: [[T6:%.*]] = bitcast [[CLASS]]* [[T4]] to i8*
+  // CHECK-NEXT: [[ALLOC:%.*]] = {{invoke.*@objc_msgSend}}
+
+  // CHECK: [[T7:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_
+  // CHECK-NEXT: [[T8:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
+  // CHECK-NEXT: [[INIT:%.*]]  = {{invoke.*@objc_msgSend}}
+
   id arr = @[ X(), Y() ];
 
   // Destroy temporaries
@@ -81,7 +88,7 @@ void test_array_instantiation() {
 
   // Build the array
   // CHECK: {{invoke.*@objc_msgSend}}
-  // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+
   id arr = @[ X(), Y() ];
 
   // Destroy temporaries
index e60fd970f3834211da678fee91a2a5ba3af7772f..285c7371cccfdad382877471a54a96c87528d89a 100644 (file)
@@ -21,8 +21,9 @@ id CFBridgingRelease(CFTypeRef);
 @interface NSNumber 
 + (NSNumber *)numberWithInt:(int)value;
 @end
-@interface NSArray <NSFastEnumeration>
+@interface NSArray : NSObject <NSFastEnumeration>
 + (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+- (id)initWithObjects:(const id [])objects count:(NSUInteger)cnt;
 @end
 
 void test0(void (*fn)(int), int val) {
@@ -748,7 +749,7 @@ void rdar12569201(id key, id value) {
     // Declarations.
     __weak id x = @"foo"; // no-warning
     __weak id y = @{ key : value }; // expected-warning {{assigning retained object to weak variable; object will be released after assignment}}
-    __weak id z = @[ value ]; // expected-warning {{assigning array literal to a weak variable; object will be released after assignment}}
+    __weak id z = @[ value ]; // expected-warning {{assigning retained object to weak variable; object will be released after assignment}}
     __weak id b = ^() {}; // expected-warning {{assigning block literal to a weak variable; object will be released after assignment}}
     __weak id n = @42; // expected-warning {{assigning numeric literal to a weak variable; object will be released after assignment}}
     __weak id e = @(42); // expected-warning {{assigning numeric literal to a weak variable; object will be released after assignment}}
@@ -756,7 +757,7 @@ void rdar12569201(id key, id value) {
     
     // Assignments.
     y = @{ key : value }; // expected-warning {{assigning retained object to weak variable; object will be released after assignment}}
-    z = @[ value ]; // expected-warning {{assigning array literal to a weak variable; object will be released after assignment}}
+    z = @[ value ]; // expected-warning {{assigning retained object to weak variable; object will be released after assignment}}
     b = ^() {}; // expected-warning {{assigning block literal to a weak variable; object will be released after assignment}}
     n = @42; // expected-warning {{assigning numeric literal to a weak variable; object will be released after assignment}}
     e = @(42); // expected-warning {{assigning numeric literal to a weak variable; object will be released after assignment}}
index febce3a267251a429c7e1f677a557e763a43ac8a..409d7134ef362db414fb761995450cb69244ce42 100644 (file)
@@ -29,6 +29,7 @@ typedef signed char BOOL;
 
 @interface NSArray : NSObject
 + (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
+- (id)initWithObjects:(const id [])objects count:(unsigned long)cnt;
 @end
 
 @interface NSDictionary : NSObject