summaryrefslogtreecommitdiff
path: root/test/CodeGenObjC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2012-04-14 14:01:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2012-04-14 14:01:31 +0000
commitdbe13110f59f48b4dbb7552b3ac2935acdeece7f (patch)
treebe1815eb79b42ff482a8562b13c2dcbf0c5dcbee /test/CodeGenObjC
parent9da628931ebf2609493570f87824ca22402cc65f (diff)
Notes
Diffstat (limited to 'test/CodeGenObjC')
-rw-r--r--test/CodeGenObjC/2009-08-05-utf16.m2
-rw-r--r--test/CodeGenObjC/Inputs/literal-support.h35
-rw-r--r--test/CodeGenObjC/arc-blocks.m523
-rw-r--r--test/CodeGenObjC/arc-cond-stmt.m48
-rw-r--r--test/CodeGenObjC/arc-exceptions.m45
-rw-r--r--test/CodeGenObjC/arc-foreach.m6
-rw-r--r--test/CodeGenObjC/arc-ivar-layout.m11
-rw-r--r--test/CodeGenObjC/arc-literals.m121
-rw-r--r--test/CodeGenObjC/arc-no-arc-exceptions.m78
-rw-r--r--test/CodeGenObjC/arc-property.m15
-rw-r--r--test/CodeGenObjC/arc.m537
-rw-r--r--test/CodeGenObjC/auto-property-synthesize-protocol.m37
-rw-r--r--test/CodeGenObjC/catch-lexical-block.m16
-rw-r--r--test/CodeGenObjC/complex-double-abi.m16
-rw-r--r--test/CodeGenObjC/constant-strings.m2
-rw-r--r--test/CodeGenObjC/debug-info-block-helper.m4
-rw-r--r--test/CodeGenObjC/debug-info-fwddecl.m5
-rw-r--r--test/CodeGenObjC/debug-info-getter-name.m8
-rw-r--r--test/CodeGenObjC/debug-info-impl.m16
-rw-r--r--test/CodeGenObjC/debug-info-property.m2
-rw-r--r--test/CodeGenObjC/debug-info-property3.m12
-rw-r--r--test/CodeGenObjC/debug-info-property4.m17
-rw-r--r--test/CodeGenObjC/debug-info-property5.m32
-rw-r--r--test/CodeGenObjC/debug-info-pubtypes.m9
-rw-r--r--test/CodeGenObjC/debug-info-static-var.m5
-rw-r--r--test/CodeGenObjC/debug-info-synthesis.m34
-rw-r--r--test/CodeGenObjC/debug-property-synth.m3
-rw-r--r--test/CodeGenObjC/exceptions.m6
-rw-r--r--test/CodeGenObjC/forward-class-impl-metadata.m6
-rw-r--r--test/CodeGenObjC/fp2ret.m28
-rw-r--r--test/CodeGenObjC/image-info.m13
-rw-r--r--test/CodeGenObjC/ivar-base-as-invariant-load.m29
-rw-r--r--test/CodeGenObjC/ns_consume_null_check.m32
-rw-r--r--test/CodeGenObjC/objc-align.m2
-rw-r--r--test/CodeGenObjC/objc-arc-container-subscripting.m21
-rw-r--r--test/CodeGenObjC/objc-container-subscripting-1.m56
-rw-r--r--test/CodeGenObjC/objc-container-subscripting.m45
-rw-r--r--test/CodeGenObjC/objc-dictionary-literal.m25
-rw-r--r--test/CodeGenObjC/objc-literal-debugger-test.m16
-rw-r--r--test/CodeGenObjC/objc-literal-tests.m95
-rw-r--r--test/CodeGenObjC/optimized-setter.m33
-rw-r--r--test/CodeGenObjC/property.m54
-rw-r--r--test/CodeGenObjC/selector-ref-invariance.m9
-rw-r--r--test/CodeGenObjC/variadic-sends.m8
44 files changed, 1612 insertions, 505 deletions
diff --git a/test/CodeGenObjC/2009-08-05-utf16.m b/test/CodeGenObjC/2009-08-05-utf16.m
index 38c9c82e78355..06458e730ae2a 100644
--- a/test/CodeGenObjC/2009-08-05-utf16.m
+++ b/test/CodeGenObjC/2009-08-05-utf16.m
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -emit-llvm -w -x objective-c %s -o - | FileCheck %s
// rdar://7095855 rdar://7115749
-// CHECK: internal unnamed_addr constant [12 x i8]
+// CHECK: internal unnamed_addr constant [6 x i16] [i16 105, i16 80, i16 111, i16 100, i16 8482, i16 0], align 2
void *P = @"iPod™";
diff --git a/test/CodeGenObjC/Inputs/literal-support.h b/test/CodeGenObjC/Inputs/literal-support.h
new file mode 100644
index 0000000000000..5680a20c9fb56
--- /dev/null
+++ b/test/CodeGenObjC/Inputs/literal-support.h
@@ -0,0 +1,35 @@
+#ifndef OBJC_LITERAL_SUPPORT_H
+#define OBJC_LITERAL_SUPPORT_H
+
+typedef unsigned char BOOL;
+
+@interface NSNumber @end
+
+@interface NSNumber (NSNumberCreation)
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
++ (NSNumber *)numberWithShort:(short)value;
++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
++ (NSNumber *)numberWithInt:(int)value;
++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
++ (NSNumber *)numberWithLong:(long)value;
++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
++ (NSNumber *)numberWithLongLong:(long long)value;
++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
++ (NSNumber *)numberWithFloat:(float)value;
++ (NSNumber *)numberWithDouble:(double)value;
++ (NSNumber *)numberWithBool:(BOOL)value;
+@end
+
+@interface NSArray
+@end
+
+@interface NSArray (NSArrayCreation)
++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt;
+@end
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt;
+@end
+
+#endif // OBJC_LITERAL_SUPPORT_H
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
new file mode 100644
index 0000000000000..06acf01ce0f73
--- /dev/null
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -0,0 +1,523 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+
+// This shouldn't crash.
+void test0(id (^maker)(void)) {
+ maker();
+}
+
+int (^test1(int x))(void) {
+ // CHECK: define i32 ()* @test1(
+ // CHECK: [[X:%.*]] = alloca i32,
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+ // CHECK-NEXT: store i32 {{%.*}}, i32* [[X]]
+ // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) nounwind
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()*
+ // CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8*
+ // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) nounwind
+ // CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()*
+ // CHECK-NEXT: ret i32 ()* [[T6]]
+ return ^{ return x; };
+}
+
+void test2(id x) {
+// CHECK: define void @test2(
+// CHECK: [[X:%.*]] = alloca i8*,
+// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
+// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]],
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
+// CHECK-NEXT: bitcast
+// CHECK-NEXT: call void @test2_helper(
+// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOTREL]]
+// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
+// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
+// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
+// CHECK-NEXT: ret void
+ extern void test2_helper(id (^)(void));
+ test2_helper(^{ return x; });
+}
+
+void test3(void (^sink)(id*)) {
+ __strong id strong;
+ sink(&strong);
+
+ // CHECK: define void @test3(
+ // CHECK: [[SINK:%.*]] = alloca void (i8**)*
+ // CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
+ // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
+ // CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8*
+ // CHECK-NEXT: call i8* @objc_retain(
+ // CHECK-NEXT: bitcast i8*
+ // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
+ // CHECK-NEXT: store i8* null, i8** [[STRONG]]
+
+ // CHECK-NEXT: load void (i8**)** [[SINK]]
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: [[BLOCK:%.*]] = bitcast
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]]
+ // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP]]
+ // CHECK-NEXT: [[F0:%.*]] = load i8**
+ // CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)*
+ // CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP]])
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP]]
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: [[T2:%.*]] = load i8** [[STRONG]]
+ // CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+
+ // CHECK-NEXT: load void (i8**)** [[SINK]]
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: call void @objc_release
+ // CHECK-NEXT: ret void
+
+}
+
+void test4(void) {
+ id test4_source(void);
+ void test4_helper(void (^)(void));
+ __block id var = test4_source();
+ test4_helper(^{ var = 0; });
+
+ // CHECK: define void @test4()
+ // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2
+ // 0x02000000 - has copy/dispose helpers
+ // CHECK-NEXT: store i32 33554432, i32* [[T0]]
+ // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source()
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
+ // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
+ // 0x42000000 - has signature, copy/dispose helpers
+ // CHECK: store i32 1107296256,
+ // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
+ // CHECK-NEXT: store i8* [[T0]], i8**
+ // CHECK: call void @test4_helper(
+ // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
+ // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: ret void
+
+ // CHECK: define internal void @__Block_byref_object_copy_
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
+ // CHECK-NEXT: load i8**
+ // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
+ // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
+ // CHECK-NEXT: [[T2:%.*]] = load i8** [[T1]]
+ // CHECK-NEXT: store i8* [[T2]], i8** [[T0]]
+ // CHECK-NEXT: store i8* null, i8** [[T1]]
+
+ // CHECK: define internal void @__Block_byref_object_dispose_
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
+ // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+
+ // CHECK: define internal void @__test4_block_invoke_
+ // CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]], align 8
+ // CHECK-NEXT: store i8* null, i8** [[SLOT]],
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: ret void
+
+ // CHECK: define internal void @__copy_helper_block_
+ // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
+
+ // CHECK: define internal void @__destroy_helper_block_
+ // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
+}
+
+void test5(void) {
+ extern id test5_source(void);
+ void test5_helper(void (^)(void));
+ __unsafe_unretained id var = test5_source();
+ test5_helper(^{ (void) var; });
+
+ // CHECK: define void @test5()
+ // CHECK: [[VAR:%.*]] = alloca i8*
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+ // CHECK: [[T0:%.*]] = call i8* @test5_source()
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // 0x40000000 - has signature but no copy/dispose
+ // CHECK: store i32 1073741824, i32*
+ // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]]
+ // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
+ // CHECK: call void @test5_helper
+ // CHECK-NEXT: ret void
+}
+
+void test6(void) {
+ id test6_source(void);
+ void test6_helper(void (^)(void));
+ __block __weak id var = test6_source();
+ test6_helper(^{ var = 0; });
+
+ // CHECK: define void @test6()
+ // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2
+ // 0x02000000 - has copy/dispose helpers
+ // CHECK-NEXT: store i32 33554432, i32* [[T0]]
+ // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source()
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]])
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
+ // 0x42000000 - has signature, copy/dispose helpers
+ // CHECK: store i32 1107296256,
+ // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
+ // CHECK-NEXT: store i8* [[T0]], i8**
+ // CHECK: call void @test6_helper(
+ // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
+ // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
+ // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
+ // CHECK-NEXT: ret void
+
+ // CHECK: define internal void @__Block_byref_object_copy_
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
+ // CHECK-NEXT: load i8**
+ // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
+ // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
+ // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
+
+ // CHECK: define internal void @__Block_byref_object_dispose_
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
+ // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+
+ // CHECK: define internal void @__test6_block_invoke_
+ // CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
+ // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null)
+ // CHECK-NEXT: ret void
+
+ // CHECK: define internal void @__copy_helper_block_
+ // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
+ // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
+
+ // CHECK: define internal void @__destroy_helper_block_
+ // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
+ // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
+}
+
+void test7(void) {
+ id test7_source(void);
+ void test7_helper(void (^)(void));
+ void test7_consume(id);
+ __weak id var = test7_source();
+ test7_helper(^{ test7_consume(var); });
+
+ // CHECK: define void @test7()
+ // CHECK: [[VAR:%.*]] = alloca i8*,
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+ // CHECK: [[T0:%.*]] = call i8* @test7_source()
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]])
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+ // 0x42000000 - has signature, copy/dispose helpers
+ // CHECK: store i32 1107296256,
+ // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[VAR]])
+ // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]])
+ // CHECK: call void @test7_helper(
+ // CHECK-NEXT: call void @objc_destroyWeak(i8** {{%.*}})
+ // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
+ // CHECK-NEXT: ret void
+
+ // CHECK: define internal void @__test7_block_invoke_
+ // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[SLOT]])
+ // CHECK-NEXT: call void @test7_consume(i8* [[T0]])
+ // CHECK-NEXT: ret void
+
+ // CHECK: define internal void @__copy_helper_block_
+ // CHECK: getelementptr
+ // CHECK-NEXT: getelementptr
+ // CHECK-NEXT: call void @objc_copyWeak(
+
+ // CHECK: define internal void @__destroy_helper_block_
+ // CHECK: getelementptr
+ // CHECK-NEXT: call void @objc_destroyWeak(
+}
+
+@interface Test8 @end
+@implementation Test8
+- (void) test {
+// CHECK: define internal void @"\01-[Test8 test]"
+// CHECK: [[SELF:%.*]] = alloca [[TEST8:%.*]]*,
+// CHECK-NEXT: alloca i8*
+// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+// CHECK: store
+// CHECK-NEXT: store
+// CHECK: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[SELF]],
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
+// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST8]]*
+// CHECK-NEXT: store [[TEST8]]* [[T4]], [[TEST8]]** [[T0]]
+// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
+// CHECK: call void @test8_helper(
+// CHECK-NEXT: [[T1:%.*]] = load [[TEST8]]** [[D0]]
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST8]]* [[T1]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T2]])
+// CHECK-NEXT: ret void
+
+ extern void test8_helper(void (^)(void));
+ test8_helper(^{ (void) self; });
+}
+@end
+
+id test9(void) {
+ typedef id __attribute__((ns_returns_retained)) blocktype(void);
+ extern void test9_consume_block(blocktype^);
+ return ^blocktype {
+ extern id test9_produce(void);
+ return test9_produce();
+ }();
+
+// CHECK: define i8* @test9(
+// CHECK: load i8** getelementptr
+// CHECK-NEXT: bitcast i8*
+// CHECK-NEXT: call i8*
+// CHECK-NEXT: call i8* @objc_autoreleaseReturnValue
+// CHECK-NEXT: ret i8*
+
+// CHECK: call i8* @test9_produce()
+// CHECK-NEXT: call i8* @objc_retain
+// CHECK-NEXT: ret i8*
+}
+
+// rdar://problem/9814099
+// Test that we correctly initialize __block variables
+// when the initialization captures the variable.
+void test10a(void) {
+ __block void (^block)(void) = ^{ block(); };
+ // CHECK: define void @test10a()
+ // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
+
+ // Zero-initialization before running the initializer.
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+ // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
+
+ // Run the initializer as an assignment.
+ // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
+ // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
+ // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1
+ // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]]
+ // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6
+ // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8
+ // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
+ // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T7]])
+
+ // Destroy at end of function.
+ // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
+ // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
+ // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]
+ // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: ret void
+}
+
+// <rdar://problem/10402698>: do this copy and dispose with
+// objc_retainBlock/release instead of _Block_object_assign/destroy.
+// We can also use _Block_object_assign/destroy with
+// BLOCK_FIELD_IS_BLOCK as long as we don't pass BLOCK_BYREF_CALLER.
+
+// CHECK: define internal void @__Block_byref_object_copy
+// CHECK: [[D0:%.*]] = load i8** {{%.*}}
+// CHECK-NEXT: [[D1:%.*]] = bitcast i8* [[D0]] to [[BYREF_T]]*
+// CHECK-NEXT: [[D2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[D1]], i32 0, i32 6
+// CHECK-NEXT: [[S0:%.*]] = load i8** {{%.*}}
+// CHECK-NEXT: [[S1:%.*]] = bitcast i8* [[S0]] to [[BYREF_T]]*
+// CHECK-NEXT: [[S2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[S1]], i32 0, i32 6
+// CHECK-NEXT: [[T0:%.*]] = load void ()** [[S2]], align 8
+// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+// CHECK-NEXT: store void ()* [[T3]], void ()** [[D2]], align 8
+// CHECK-NEXT: ret void
+
+// CHECK: define internal void @__Block_byref_object_dispose
+// CHECK: [[T0:%.*]] = load i8** {{%.*}}
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[BYREF_T]]*
+// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T1]], i32 0, i32 6
+// CHECK-NEXT: [[T3:%.*]] = load void ()** [[T2]], align 8
+// CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T4]])
+// CHECK-NEXT: ret void
+
+// Test that we correctly assign to __block variables when the
+// assignment captures the variable.
+void test10b(void) {
+ __block void (^block)(void);
+ block = ^{ block(); };
+
+ // CHECK: define void @test10b()
+ // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
+
+ // Zero-initialize.
+ // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+ // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
+
+ // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
+
+ // The assignment.
+ // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
+ // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
+ // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1
+ // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]]
+ // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6
+ // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8
+ // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
+ // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T7]])
+
+ // Destroy at end of function.
+ // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
+ // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
+ // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]
+ // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T2]])
+ // CHECK-NEXT: ret void
+}
+
+// rdar://problem/10088932
+void test11_helper(id);
+void test11a(void) {
+ int x;
+ test11_helper(^{ (void) x; });
+
+ // CHECK: define void @test11a()
+ // CHECK: [[X:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
+ // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+ // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
+ // CHECK-NEXT: call void @test11_helper(i8* [[T4]])
+ // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: ret void
+}
+void test11b(void) {
+ int x;
+ id b = ^{ (void) x; };
+
+ // CHECK: define void @test11b()
+ // CHECK: [[X:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
+ // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+ // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
+ // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8
+ // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: ret void
+}
+
+// rdar://problem/9979150
+@interface Test12
+@property (strong) void(^ablock)(void);
+@property (nonatomic, strong) void(^nblock)(void);
+@end
+@implementation Test12
+@synthesize ablock, nblock;
+// CHECK: define internal void ()* @"\01-[Test12 ablock]"(
+// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext true)
+
+// CHECK: define internal void @"\01-[Test12 setAblock:]"(
+// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true)
+
+// CHECK: define internal void ()* @"\01-[Test12 nblock]"(
+// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false)
+
+// CHECK: define internal void @"\01-[Test12 setNblock:]"(
+// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true)
+@end
+
+// rdar://problem/10131784
+void test13(id x) {
+ extern void test13_helper(id);
+ extern void test13_use(void(^)(void));
+
+ void (^b)(void) = (x ? ^{test13_helper(x);} : 0);
+ test13_use(b);
+
+ // CHECK: define void @test13(
+ // CHECK: [[X:%.*]] = alloca i8*, align 8
+ // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8
+ // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1
+ // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retain(i8* {{%.*}})
+ // CHECK-NEXT: store i8* [[T0]], i8** [[X]], align 8
+ // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8
+ // CHECK-NEXT: [[T1:%.*]] = icmp ne i8* [[T0]], null
+ // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]]
+ // CHECK-NEXT: br i1 [[T1]],
+
+ // CHECK-NOT: br
+ // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+ // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]], align 8
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+ // CHECK-NEXT: store i8* [[T1]], i8** [[CAPTURE]], align 8
+ // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
+ // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
+ // CHECK-NEXT: br label
+ // CHECK: br label
+ // CHECK: [[T0:%.*]] = phi void ()*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+ // CHECK-NEXT: store void ()* [[T3]], void ()** [[B]], align 8
+ // CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]], align 8
+ // CHECK-NEXT: call void @test13_use(void ()* [[T0]])
+ // CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]]
+ // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T1]])
+
+ // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]]
+ // CHECK-NEXT: br i1 [[T0]]
+ // CHECK: [[T0:%.*]] = load i8** [[CLEANUP_ADDR]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: br label
+
+ // CHECK: [[T0:%.*]] = load i8** [[X]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T0]])
+ // CHECK-NEXT: ret void
+}
+
+// <rdar://problem/10907510>
+void test14() {
+ void (^const x[1])(void) = { ^{} };
+}
+
+// rdar://11149025
+// Don't make invalid ASTs and crash.
+void test15_helper(void (^block)(void), int x);
+void test15(int a) {
+ test15_helper(^{ (void) a; }, ({ a; }));
+}
diff --git a/test/CodeGenObjC/arc-cond-stmt.m b/test/CodeGenObjC/arc-cond-stmt.m
new file mode 100644
index 0000000000000..d8ee6bb084b5e
--- /dev/null
+++ b/test/CodeGenObjC/arc-cond-stmt.m
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - %s
+// rdar://10327068
+
+@class NSString;
+
+@interface NSAssertionHandler {
+}
+
++ (NSAssertionHandler *)currentHandler;
+
+- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(int)line ,...;
+
+@end
+
+typedef enum
+{
+ MWRaceOrder_MeetName,
+ MWRaceOrder_MeetPosition,
+ MWRaceOrder_MeetDistance,
+ MWRaceOrder_Name,
+ MWRaceOrder_Position,
+ MWRaceOrder_Distance,
+ MWRaceOrder_Default = MWRaceOrder_Name,
+ MWRaceOrder_MeetDefault = MWRaceOrder_MeetName,
+} MWRaceOrder;
+
+@interface MWViewMeetController
+@property (nonatomic, assign) MWRaceOrder raceOrder;
+@end
+
+@implementation MWViewMeetController
+
+- (int)orderSegment
+{
+ switch (self.raceOrder)
+ {
+
+ default:
+ { [(NSAssertionHandler *)0 handleFailureInMethod:_cmd object:self file:(NSString*)0 lineNumber:192 ]; };
+ break;
+ }
+
+ return 0;
+}
+
+@synthesize raceOrder;
+
+@end
diff --git a/test/CodeGenObjC/arc-exceptions.m b/test/CodeGenObjC/arc-exceptions.m
new file mode 100644
index 0000000000000..5ef5ababe695f
--- /dev/null
+++ b/test/CodeGenObjC/arc-exceptions.m
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fobjc-runtime-has-weak -o - %s | FileCheck %s
+
+@class Ety;
+
+// These first two tests are all PR11732 / rdar://problem/10667070.
+
+void test0_helper(void);
+void test0(void) {
+ @try {
+ test0_helper();
+ } @catch (Ety *e) {
+ }
+}
+// CHECK: define void @test0()
+// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @test0_helper()
+// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
+// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
+// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
+// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: call void @objc_end_catch() nounwind
+
+void test1_helper(void);
+void test1(void) {
+ @try {
+ test1_helper();
+ } @catch (__weak Ety *e) {
+ }
+}
+// CHECK: define void @test1()
+// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @test1_helper()
+// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind
+// CHECK-NEXT: call void @objc_end_catch() nounwind
diff --git a/test/CodeGenObjC/arc-foreach.m b/test/CodeGenObjC/arc-foreach.m
index 9449b3d2d602a..67fad4d9b04a1 100644
--- a/test/CodeGenObjC/arc-foreach.m
+++ b/test/CodeGenObjC/arc-foreach.m
@@ -60,13 +60,14 @@ void test0(NSArray *array) {
// CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]]
// CHECK-LP64-NEXT: store i8* [[T3]], i8** [[X]]
+// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[X]]
// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
// CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]]
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]]
// CHECK-LP64: call void @use_block(
-// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[T0]]
+// CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[D0]]
// CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]])
// CHECK-LP64: [[T0:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_
@@ -108,12 +109,13 @@ void test1(NSArray *array) {
// CHECK-LP64-NEXT: [[T3:%.*]] = load i8** [[T2]]
// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[X]], i8* [[T3]])
+// CHECK-LP64: [[D0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
// CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]])
// CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]])
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
// CHECK-LP64: call void @use_block
-// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[T0]])
+// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[D0]])
// CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]])
// rdar://problem/9817306
diff --git a/test/CodeGenObjC/arc-ivar-layout.m b/test/CodeGenObjC/arc-ivar-layout.m
index 30c90fac9e404..7f58a0cad3bd6 100644
--- a/test/CodeGenObjC/arc-ivar-layout.m
+++ b/test/CodeGenObjC/arc-ivar-layout.m
@@ -42,3 +42,14 @@
// CHECK-LP64: L_OBJC_CLASS_NAME_15:
// CHECK-LP64-NEXT: .asciz "\022"
+@interface UnsafePerson {
+@public
+ __unsafe_unretained id name;
+ __unsafe_unretained id age;
+ id value;
+}
+@end
+
+@implementation UnsafePerson @end
+// CHECK-LP64: L_OBJC_CLASS_NAME_20:
+// CHECK-LP64-NEXT: .asciz "!"
diff --git a/test/CodeGenObjC/arc-literals.m b/test/CodeGenObjC/arc-literals.m
new file mode 100644
index 0000000000000..203c2ad1eea17
--- /dev/null
+++ b/test/CodeGenObjC/arc-literals.m
@@ -0,0 +1,121 @@
+// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+
+#include "literal-support.h"
+
+// Check the various selector names we'll be using, in order.
+
+// CHECK: c"numberWithInt:\00"
+// CHECK: c"numberWithUnsignedInt:\00"
+// CHECK: c"numberWithUnsignedLongLong:\00"
+// CHECK: c"numberWithChar:\00"
+// CHECK: c"arrayWithObjects:count:\00"
+// CHECK: c"dictionaryWithObjects:forKeys:count:\00"
+// CHECK: c"prop\00"
+
+// CHECK: define void @test_numeric()
+void test_numeric() {
+ // CHECK: {{call.*objc_msgSend.*i32 17}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id ilit = @17;
+ // CHECK: {{call.*objc_msgSend.*i32 25}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id ulit = @25u;
+ // CHECK: {{call.*objc_msgSend.*i64 42}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id ulllit = @42ull;
+ // CHECK: {{call.*objc_msgSend.*i8 signext 97}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id charlit = @'a';
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
+
+// CHECK: define void @test_array
+void test_array(id a, id b) {
+ // Retaining parameters
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+
+ // Constructing the array
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
+ // CHECK: store i8*
+
+ // CHECK: {{call i8*.*objc_msgSend.*i64 2}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id arr = @[a, b];
+
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
+
+// CHECK: define void @test_dictionary
+void test_dictionary(id k1, id o1, id k2, id o2) {
+ // Retaining parameters
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+ // CHECK: call i8* @objc_retain(i8*
+
+ // Constructing the arrays
+ // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS:%[A-Za-z0-9]+]], i32 0, i32 0
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS:%[A-Za-z0-9]+]], i32 0, i32 0
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[KEYS]], i32 0, i32 1
+ // CHECK: store i8*
+ // CHECK: getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1
+ // CHECK: store i8*
+
+ // Constructing the dictionary
+ // CHECK: {{call i8.*@objc_msgSend}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id dict = @{ k1 : o1, k2 : o2 };
+
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
+
+@interface A
+@end
+
+@interface B
+@property (retain) A* prop;
+@end
+
+// CHECK: define void @test_property
+void test_property(B *b) {
+ // Retain parameter
+ // CHECK: call i8* @objc_retain
+
+ // Invoke 'prop'
+ // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+ // CHECK: {{call.*@objc_msgSend}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+
+ // Invoke arrayWithObjects:count:
+ // CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+ // CHECK: {{call.*objc_msgSend}}
+ // CHECK: call i8* @objc_retainAutoreleasedReturnValue
+ id arr = @[ b.prop ];
+
+ // Release b.prop
+ // CHECK: call void @objc_release
+
+ // Destroy arr
+ // CHECK: call void @objc_release
+
+ // Destroy b
+ // CHECK: call void @objc_release
+ // CHECK-NEXT: ret void
+}
diff --git a/test/CodeGenObjC/arc-no-arc-exceptions.m b/test/CodeGenObjC/arc-no-arc-exceptions.m
new file mode 100644
index 0000000000000..7ae061f414674
--- /dev/null
+++ b/test/CodeGenObjC/arc-no-arc-exceptions.m
@@ -0,0 +1,78 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O0 -disable-llvm-optzns -o - %s | FileCheck -check-prefix=NO-METADATA %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fblocks -fexceptions -fobjc-exceptions -O2 -disable-llvm-optzns -o - %s -fobjc-arc-exceptions | FileCheck -check-prefix=NO-METADATA %s
+
+// The front-end should emit clang.arc.no_objc_arc_exceptions in -fobjc-arc-exceptions
+// mode when optimization is enabled, and not otherwise.
+
+void thrower(void);
+void not(void) __attribute__((nothrow));
+
+// CHECK: define void @test0(
+// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions !
+// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions !
+// NO-METADATA: define void @test0(
+// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
+// NO-METADATA: }
+void test0(void) {
+ thrower();
+ not();
+}
+
+// CHECK: define void @test1(
+// CHECK: call void @thrower(), !clang.arc.no_objc_arc_exceptions !
+// CHECK: call void @not() nounwind, !clang.arc.no_objc_arc_exceptions !
+// NO-METADATA: define void @test1(
+// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
+// NO-METADATA: }
+void test1(id x) {
+ id y = x;
+ thrower();
+ not();
+}
+
+void NSLog(id, ...);
+
+// CHECK: define void @test2(
+// CHECK: invoke void (i8*, ...)* @NSLog(i8* bitcast (%struct.NSConstantString* @_unnamed_cfstring_ to i8*), i32* %{{.*}})
+// CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions !
+// NO-METADATA: define void @test2(
+// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
+// NO-METADATA: }
+void test2(void) {
+ @autoreleasepool {
+ __attribute__((__blocks__(byref))) int x;
+ NSLog(@"Address of x outside of block: %p", &x);
+ }
+}
+
+// CHECK: define void @test3(
+// CHECK: invoke void %{{.*}}(i8* %{{.*}})
+// CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions !
+// NO-METADATA: define void @test3(
+// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
+// NO-METADATA: }
+void test3(void) {
+ @autoreleasepool {
+ __attribute__((__blocks__(byref))) int x;
+ ^{
+ NSLog(@"Address of x in non-assigned block: %p", &x);
+ }();
+ }
+}
+
+// CHECK: define void @test4(
+// CHECK: invoke void %{{.*}}(i8* %{{.*}})
+// CHECK: to label %{{.*}} unwind label %{{.*}}, !clang.arc.no_objc_arc_exceptions !
+// NO-METADATA: define void @test4(
+// NO-METADATA-NOT: !clang.arc.no_objc_arc_exceptions
+// NO-METADATA: }
+void test4(void) {
+ @autoreleasepool {
+ __attribute__((__blocks__(byref))) int x;
+ void (^b)(void) = ^{
+ NSLog(@"Address of x in assigned block: %p", &x);
+ };
+ b();
+ }
+}
diff --git a/test/CodeGenObjC/arc-property.m b/test/CodeGenObjC/arc-property.m
new file mode 100644
index 0000000000000..6c5180b1c347e
--- /dev/null
+++ b/test/CodeGenObjC/arc-property.m
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -emit-llvm %s -o - | FileCheck %s
+
+// rdar://problem/10290317
+@interface Test0
+- (void) setValue: (id) x;
+@end
+void test0(Test0 *t0, id value) {
+ t0.value = value;
+}
+// CHECK: define void @test0(
+// CHECK: call i8* @objc_retain(
+// CHECK: call i8* @objc_retain(
+// CHECK: @objc_msgSend
+// CHECK: call void @objc_release(
+// CHECK: call void @objc_release(
diff --git a/test/CodeGenObjC/arc.m b/test/CodeGenObjC/arc.m
index e97e625b06eb5..2a98b10909bb8 100644
--- a/test/CodeGenObjC/arc.m
+++ b/test/CodeGenObjC/arc.m
@@ -13,23 +13,20 @@ void test0(id x) {
// CHECK: define i8* @test1(i8*
id test1(id x) {
- // CHECK: [[RET:%.*]] = alloca i8*
- // CHECK-NEXT: [[X:%.*]] = alloca i8*
+ // CHECK: [[X:%.*]] = alloca i8*
// CHECK-NEXT: [[Y:%.*]] = alloca i8*
// CHECK-NEXT: alloca i32
// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
// CHECK-NEXT: store i8* null, i8** [[Y]]
// CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
- // CHECK-NEXT: store i8* [[T1]], i8** [[RET]]
+ // CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T0]])
// CHECK-NEXT: store i32
// CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]]
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
// CHECK-NEXT: [[T1:%.*]] = load i8** [[X]]
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[RET]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T0]])
+ // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[RET]])
// CHECK-NEXT: ret i8* [[T1]]
id y;
return y;
@@ -449,11 +446,6 @@ void test13(void) {
- (int) x { return super.x + 1; }
@end
-// This shouldn't crash.
-void test18(id (^maker)(void)) {
- maker();
-}
-
void test19() {
// CHECK: define void @test19()
// CHECK: [[X:%.*]] = alloca [5 x i8*], align 16
@@ -615,22 +607,6 @@ void test22(_Bool cond) {
@interface Test24 {} @end
@implementation Test24 @end
-int (^test25(int x))(void) {
- // CHECK: define i32 ()* @test25(
- // CHECK: [[X:%.*]] = alloca i32,
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
- // CHECK-NEXT: store i32 {{%.*}}, i32* [[X]]
- // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to i32 ()*
- // CHECK-NEXT: [[T1:%.*]] = bitcast i32 ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) nounwind
- // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()*
- // CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8*
- // CHECK-NEXT: [[T5:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) nounwind
- // CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()*
- // CHECK-NEXT: ret i32 ()* [[T6]]
- return ^{ return x; };
-}
-
// rdar://problem/8941012
@interface Test26 { id x[4]; } @end
@implementation Test26 @end
@@ -657,24 +633,19 @@ int (^test25(int x))(void) {
@implementation Test27
- (id) init { return self; }
// CHECK: define internal i8* @"\01-[Test27 init]"
-// CHECK: [[RET:%.*]] = alloca i8*,
-// CHECK-NEXT: [[SELF:%.*]] = alloca [[TEST27:%.*]]*,
+// CHECK: [[SELF:%.*]] = alloca [[TEST27:%.*]]*,
// CHECK-NEXT: [[CMD:%.*]] = alloca i8*,
// CHECK-NEXT: [[DEST:%.*]] = alloca i32
// CHECK-NEXT: store [[TEST27]]* {{%.*}}, [[TEST27]]** [[SELF]]
// CHECK-NEXT: store i8* {{%.*}}, i8** [[CMD]]
// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
-// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]]
-// CHECK-NEXT: [[T2:%.*]] = bitcast
-// CHECK-NEXT: store i8* [[T2]], i8** [[RET]]
+// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]])
// CHECK-NEXT: store i32 {{[0-9]+}}, i32* [[DEST]]
// CHECK-NEXT: [[T0:%.*]] = load [[TEST27]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST27]]* [[T0]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[RET]]
-// CHECK-NEXT: ret i8* [[T0]]
+// CHECK-NEXT: ret i8* [[RET]]
@end
@@ -705,8 +676,7 @@ int (^test25(int x))(void) {
static id _test29_allocator = 0;
- (id) init {
// CHECK: define internal i8* @"\01-[Test29 init]"([[TEST29:%.*]]* {{%.*}},
-// CHECK: [[RET:%.*]] = alloca i8*, align 8
-// CHECK-NEXT: [[SELF:%.*]] = alloca [[TEST29]]*, align 8
+// CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8
// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[CLEANUP:%.*]] = alloca i32
// CHECK-NEXT: store [[TEST29]]* {{%.*}}, [[TEST29]]** [[SELF]]
@@ -734,10 +704,7 @@ static id _test29_allocator = 0;
// Return statement.
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[CALL]]
// CHECK-NEXT: [[CALL:%.*]] = bitcast
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[CALL]]) nounwind
-// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]]
-// CHECK-NEXT: [[T1:%.*]] = bitcast
-// CHECK-NEXT: store i8* [[T1]], i8** [[RET]]
+// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[CALL]]) nounwind
// CHECK-NEXT: store i32 1, i32* [[CLEANUP]]
// Cleanup.
@@ -746,14 +713,12 @@ static id _test29_allocator = 0;
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release
// Return.
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[RET]]
-// CHECK-NEXT: ret i8* [[T0]]
+// CHECK-NEXT: ret i8* [[RET]]
return [self initWithAllocator: _test29_allocator];
}
- (id) initWithAllocator: (id) allocator {
// CHECK: define internal i8* @"\01-[Test29 initWithAllocator:]"(
-// CHECK: [[RET:%.*]] = alloca i8*, align 8
-// CHECK-NEXT: [[SELF:%.*]] = alloca [[TEST29]]*, align 8
+// CHECK: [[SELF:%.*]] = alloca [[TEST29]]*, align 8
// CHECK-NEXT: [[CMD:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[ALLOCATOR:%.*]] = alloca i8*, align 8
// CHECK-NEXT: alloca
@@ -793,10 +758,7 @@ static id _test29_allocator = 0;
// Return statement.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST29]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST29]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind
-// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]]
-// CHECK-NEXT: [[T2:%.*]] = bitcast
-// CHECK-NEXT: store i8* [[T2]], i8** [[RET]]
+// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]]) nounwind
// CHECK-NEXT: store i32 1, i32* [[CLEANUP]]
// Cleanup.
@@ -808,8 +770,7 @@ static id _test29_allocator = 0;
// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind, !clang.imprecise_release
// Return.
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[RET]]
-// CHECK-NEXT: ret i8* [[T0]]
+// CHECK-NEXT: ret i8* [[RET]]
self = [super initWithAllocator: allocator];
return self;
}
@@ -825,8 +786,7 @@ char *helper;
}
- (id) init {
// CHECK: define internal i8* @"\01-[Test30 init]"([[TEST30:%.*]]* {{%.*}},
-// CHECK: [[RET:%.*]] = alloca i8*
-// CHECK-NEXT: [[SELF:%.*]] = alloca [[TEST30]]*
+// CHECK: [[RET:%.*]] = alloca [[TEST30]]*
// CHECK-NEXT: alloca i8*
// CHECK-NEXT: alloca i32
// CHECK-NEXT: store [[TEST30]]* {{%.*}}, [[TEST30]]** [[SELF]]
@@ -853,10 +813,7 @@ char *helper;
// Return.
// CHECK-NEXT: [[T0:%.*]] = load [[TEST30]]** [[SELF]]
// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST30]]* [[T0]] to i8*
-// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
-// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]]
-// CHECK-NEXT: [[T2:%.*]] = bitcast
-// CHECK-NEXT: store i8* [[T2]], i8** [[RET]]
+// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_retain(i8* [[T1]])
// CHECK-NEXT: store i32 1
// Cleanup.
@@ -865,8 +822,7 @@ char *helper;
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
// Epilogue.
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[RET]]
-// CHECK-NEXT: ret i8* [[T0]]
+// CHECK-NEXT: ret i8* [[RET]]
self->helper = [self initHelper];
return self;
}
@@ -882,27 +838,6 @@ char *helper;
@end
-void test31(id x) {
-// CHECK: define void @test31(
-// CHECK: [[X:%.*]] = alloca i8*,
-// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
-// CHECK-NEXT: [[PARM:%.*]] = call i8* @objc_retain(i8* {{%.*}})
-// CHECK-NEXT: store i8* [[PARM]], i8** [[X]]
-// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]],
-// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
-// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]],
-// CHECK-NEXT: bitcast
-// CHECK-NEXT: call void @test31_helper(
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
-// CHECK-NEXT: [[T0:%.*]] = load i8** [[X]]
-// CHECK-NEXT: call void @objc_release(i8* [[T0]]) nounwind, !clang.imprecise_release
-// CHECK-NEXT: ret void
- extern void test31_helper(id (^)(void));
- test31_helper(^{ return x; });
-}
-
__attribute__((ns_returns_retained)) id test32(void) {
// CHECK: define i8* @test32()
// CHECK: [[CALL:%.*]] = call i8* @test32_helper()
@@ -1060,45 +995,6 @@ void test34(int cond) {
// CHECK: ret void
}
-void test35(void (^sink)(id*)) {
- __strong id strong;
- sink(&strong);
-
- // CHECK: define void @test35(
- // CHECK: [[SINK:%.*]] = alloca void (i8**)*
- // CHECK-NEXT: [[STRONG:%.*]] = alloca i8*
- // CHECK-NEXT: [[TEMP:%.*]] = alloca i8*
- // CHECK-NEXT: bitcast void (i8**)* {{%.*}} to i8*
- // CHECK-NEXT: call i8* @objc_retain(
- // CHECK-NEXT: bitcast i8*
- // CHECK-NEXT: store void (i8**)* {{%.*}}, void (i8**)** [[SINK]]
- // CHECK-NEXT: store i8* null, i8** [[STRONG]]
-
- // CHECK-NEXT: load void (i8**)** [[SINK]]
- // CHECK-NEXT: bitcast
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: [[BLOCK:%.*]] = bitcast
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]]
- // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]]
- // CHECK-NEXT: [[F0:%.*]] = load i8**
- // CHECK-NEXT: [[F1:%.*]] = bitcast i8* [[F0]] to void (i8*, i8**)*
- // CHECK-NEXT: call void [[F1]](i8* [[BLOCK]], i8** [[TEMP1]])
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[TEMP1]]
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
- // CHECK-NEXT: [[T2:%.*]] = load i8** [[STRONG]]
- // CHECK-NEXT: store i8* [[T1]], i8** [[STRONG]]
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
-
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[STRONG]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
-
- // CHECK-NEXT: load void (i8**)** [[SINK]]
- // CHECK-NEXT: bitcast
- // CHECK-NEXT: call void @objc_release
- // CHECK-NEXT: ret void
-
-}
-
// CHECK: define void @test36
void test36(id x) {
// CHECK: [[X:%.*]] = alloca i8*
@@ -1152,205 +1048,6 @@ void test37(void) {
// CHECK-NEXT: ret void
}
-void test38(void) {
- id test38_source(void);
- void test38_helper(void (^)(void));
- __block id var = test38_source();
- test38_helper(^{ var = 0; });
-
- // CHECK: define void @test38()
- // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2
- // 0x02000000 - has copy/dispose helpers
- // CHECK-NEXT: store i32 33554432, i32* [[T0]]
- // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
- // CHECK-NEXT: [[T0:%.*]] = call i8* @test38_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
- // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
- // 0x42000000 - has signature, copy/dispose helpers
- // CHECK: store i32 1107296256,
- // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
- // CHECK-NEXT: store i8* [[T0]], i8**
- // CHECK: call void @test38_helper(
- // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
- // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]]
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
- // CHECK-NEXT: ret void
-
- // CHECK: define internal void @__Block_byref_object_copy_
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: load i8**
- // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
- // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: [[T2:%.*]] = load i8** [[T1]]
- // CHECK-NEXT: store i8* [[T2]], i8** [[T0]]
- // CHECK-NEXT: store i8* null, i8** [[T1]]
-
- // CHECK: define internal void @__Block_byref_object_dispose_
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: [[T1:%.*]] = load i8** [[T0]]
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
-
- // CHECK: define internal void @__test38_block_invoke_
- // CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[SLOT]], align 8
- // CHECK-NEXT: store i8* null, i8** [[SLOT]],
- // CHECK-NEXT: call void @objc_release(i8* [[T0]])
- // CHECK-NEXT: ret void
-
- // CHECK: define internal void @__copy_helper_block_
- // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
-
- // CHECK: define internal void @__destroy_helper_block_
- // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
-}
-
-void test39(void) {
- extern id test39_source(void);
- void test39_helper(void (^)(void));
- __unsafe_unretained id var = test39_source();
- test39_helper(^{ (void) var; });
-
- // CHECK: define void @test39()
- // CHECK: [[VAR:%.*]] = alloca i8*
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
- // CHECK: [[T0:%.*]] = call i8* @test39_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // 0x40000000 - has signature but no copy/dispose
- // CHECK: store i32 1073741824, i32*
- // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
- // CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]]
- // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]]
- // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to
- // CHECK: call void @test39_helper
- // CHECK-NEXT: ret void
-}
-
-void test40(void) {
- id test40_source(void);
- void test40_helper(void (^)(void));
- __block __weak id var = test40_source();
- test40_helper(^{ var = 0; });
-
- // CHECK: define void @test40()
- // CHECK: [[VAR:%.*]] = alloca [[BYREF_T:%.*]],
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 2
- // 0x02000000 - has copy/dispose helpers
- // CHECK-NEXT: store i32 33554432, i32* [[T0]]
- // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
- // CHECK-NEXT: [[T0:%.*]] = call i8* @test40_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[VAR]], i32 0, i32 6
- // 0x42000000 - has signature, copy/dispose helpers
- // CHECK: store i32 1107296256,
- // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
- // CHECK-NEXT: store i8* [[T0]], i8**
- // CHECK: call void @test40_helper(
- // CHECK: [[T0:%.*]] = bitcast [[BYREF_T]]* [[VAR]] to i8*
- // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
- // CHECK-NEXT: ret void
-
- // CHECK: define internal void @__Block_byref_object_copy_
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: load i8**
- // CHECK-NEXT: bitcast i8* {{%.*}} to [[BYREF_T]]*
- // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: call void @objc_moveWeak(i8** [[T0]], i8** [[T1]])
-
- // CHECK: define internal void @__Block_byref_object_dispose_
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* {{%.*}}, i32 0, i32 6
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]])
-
- // CHECK: define internal void @__test40_block_invoke_
- // CHECK: [[SLOT:%.*]] = getelementptr inbounds {{.*}}, i32 0, i32 6
- // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[SLOT]], i8* null)
- // CHECK-NEXT: ret void
-
- // CHECK: define internal void @__copy_helper_block_
- // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
- // CHECK: call void @_Block_object_assign(i8* {{%.*}}, i8* {{%.*}}, i32 8)
-
- // CHECK: define internal void @__destroy_helper_block_
- // 0x8 - FIELD_IS_BYREF (no FIELD_IS_WEAK because clang in control)
- // CHECK: call void @_Block_object_dispose(i8* {{%.*}}, i32 8)
-}
-
-void test41(void) {
- id test41_source(void);
- void test41_helper(void (^)(void));
- void test41_consume(id);
- __weak id var = test41_source();
- test41_helper(^{ test41_consume(var); });
-
- // CHECK: define void @test41()
- // CHECK: [[VAR:%.*]] = alloca i8*,
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
- // CHECK: [[T0:%.*]] = call i8* @test41_source()
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[VAR]], i8* [[T1]])
- // CHECK-NEXT: call void @objc_release(i8* [[T1]])
- // 0x42000000 - has signature, copy/dispose helpers
- // CHECK: store i32 1107296256,
- // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[VAR]])
- // CHECK-NEXT: call i8* @objc_initWeak(i8** [[SLOT]], i8* [[T0]])
- // CHECK: call void @test41_helper(
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[SLOT]])
- // CHECK-NEXT: call void @objc_destroyWeak(i8** [[VAR]])
- // CHECK-NEXT: ret void
-
- // CHECK: define internal void @__test41_block_invoke_
- // CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* {{%.*}}, i32 0, i32 5
- // CHECK-NEXT: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[SLOT]])
- // CHECK-NEXT: call void @test41_consume(i8* [[T0]])
- // CHECK-NEXT: ret void
-
- // CHECK: define internal void @__copy_helper_block_
- // CHECK: getelementptr
- // CHECK-NEXT: getelementptr
- // CHECK-NEXT: call void @objc_copyWeak(
-
- // CHECK: define internal void @__destroy_helper_block_
- // CHECK: getelementptr
- // CHECK-NEXT: call void @objc_destroyWeak(
-}
-
-@interface Test42 @end
-@implementation Test42
-- (void) test {
-// CHECK: define internal void @"\01-[Test42 test]"
-// CHECK: [[SELF:%.*]] = alloca [[TEST42:%.*]]*,
-// CHECK-NEXT: alloca i8*
-// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
-// CHECK: store
-// CHECK-NEXT: store
-// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
-// CHECK-NEXT: [[T1:%.*]] = load [[TEST42]]** [[SELF]],
-// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST42]]* [[T1]] to i8*
-// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]])
-// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST42]]*
-// CHECK-NEXT: store [[TEST42]]* [[T4]], [[TEST42]]** [[T0]]
-// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to
-// CHECK: call void @test42_helper(
-// CHECK-NEXT: [[T1:%.*]] = load [[TEST42]]** [[T0]]
-// CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST42]]* [[T1]] to i8*
-// CHECK-NEXT: call void @objc_release(i8* [[T2]])
-// CHECK-NEXT: ret void
-
- extern void test42_helper(void (^)(void));
- test42_helper(^{ (void) self; });
-}
-@end
-
@interface Test43 @end
@implementation Test43
- (id) test __attribute__((ns_returns_retained)) {
@@ -1362,26 +1059,6 @@ void test41(void) {
}
@end
-id test44(void) {
- typedef id __attribute__((ns_returns_retained)) blocktype(void);
- extern test44_consume_block(blocktype^);
- return ^blocktype {
- extern id test44_produce(void);
- return test44_produce();
- }();
-
-// CHECK: define i8* @test44(
-// CHECK: load i8** getelementptr
-// CHECK-NEXT: bitcast i8*
-// CHECK-NEXT: call i8*
-// CHECK-NEXT: call i8* @objc_autoreleaseReturnValue
-// CHECK-NEXT: ret i8*
-
-// CHECK: call i8* @test44_produce()
-// CHECK-NEXT: call i8* @objc_retain
-// CHECK-NEXT: ret i8*
-}
-
@interface Test45
@property (retain) id x;
@end
@@ -1685,76 +1362,6 @@ void test59(void) {
// CHECK-NEXT: ret void
}
-// rdar://problem/9814099
-// Test that we correctly initialize __block variables
-// when the initialization captures the variable.
-void test60a(void) {
- __block void (^block)(void) = ^{ block(); };
- // CHECK: define void @test60a()
- // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
-
- // Zero-initialization before running the initializer.
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
- // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
-
- // Run the initializer as an assignment.
- // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
- // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
- // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1
- // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]]
- // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6
- // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8
- // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
- // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T7]])
-
- // Destroy at end of function.
- // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
- // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
- // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
- // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]
- // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
- // CHECK-NEXT: ret void
-}
-
-// Test that we correctly assign to __block variables when the
-// assignment captures the variable.
-void test60b(void) {
- __block void (^block)(void);
- block = ^{ block(); };
-
- // CHECK: define void @test60b()
- // CHECK: [[BYREF:%.*]] = alloca [[BYREF_T:%.*]],
-
- // Zero-initialize.
- // CHECK: [[T0:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
- // CHECK-NEXT: store void ()* null, void ()** [[T0]], align 8
-
- // CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 6
-
- // The assignment.
- // CHECK: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
- // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainBlock(i8* [[T0]])
- // CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
- // CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds [[BYREF_T]]* [[BYREF]], i32 0, i32 1
- // CHECK-NEXT: [[T4:%.*]] = load [[BYREF_T]]** [[T3]]
- // CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[BYREF_T]]* [[T4]], i32 0, i32 6
- // CHECK-NEXT: [[T6:%.*]] = load void ()** [[T5]], align 8
- // CHECK-NEXT: store void ()* {{%.*}}, void ()** [[T5]], align 8
- // CHECK-NEXT: [[T7:%.*]] = bitcast void ()* [[T6]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T7]])
-
- // Destroy at end of function.
- // CHECK-NEXT: [[T0:%.*]] = bitcast [[BYREF_T]]* [[BYREF]] to i8*
- // CHECK-NEXT: call void @_Block_object_dispose(i8* [[T0]], i32 8)
- // CHECK-NEXT: [[T1:%.*]] = load void ()** [[SLOT]]
- // CHECK-NEXT: [[T2:%.*]] = bitcast void ()* [[T1]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T2]])
- // CHECK-NEXT: ret void
-}
-
// Verify that we don't try to reclaim the result of performSelector.
// rdar://problem/9887545
@interface Test61
@@ -1855,64 +1462,6 @@ void test62(void) {
// CHECK: call i8* @objc_getProperty
// CHECK: call void @objc_setProperty
-// rdar://problem/10088932
-void test64_helper(id);
-void test64a(void) {
- int x;
- test64_helper(^{ (void) x; });
-
- // CHECK: define void @test64a()
- // CHECK: [[X:%.*]] = alloca i32, align 4
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
- // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
- // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
- // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
- // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
- // CHECK-NEXT: call void @test64_helper(i8* [[T4]])
- // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
- // CHECK-NEXT: ret void
-}
-void test64b(void) {
- int x;
- id b = ^{ (void) x; };
-
- // CHECK: define void @test64b()
- // CHECK: [[X:%.*]] = alloca i32, align 4
- // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8
- // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
- // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
- // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
- // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
- // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
- // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
- // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8
- // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]]
- // CHECK-NEXT: call void @objc_release(i8* [[T5]])
- // CHECK-NEXT: ret void
-}
-
-// rdar://problem/9979150
-@interface Test65
-@property (strong) void(^ablock)(void);
-@property (nonatomic, strong) void(^nblock)(void);
-@end
-@implementation Test65
-@synthesize ablock, nblock;
-// CHECK: define internal void ()* @"\01-[Test65 ablock]"(
-// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext true)
-
-// CHECK: define internal void @"\01-[Test65 setAblock:]"(
-// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext true, i1 zeroext true)
-
-// CHECK: define internal void ()* @"\01-[Test65 nblock]"(
-// CHECK: call i8* @objc_getProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i1 zeroext false)
-
-// CHECK: define internal void @"\01-[Test65 setNblock:]"(
-// CHECK: call void @objc_setProperty(i8* {{%.*}}, i8* {{%.*}}, i64 {{%.*}}, i8* {{%.*}}, i1 zeroext false, i1 zeroext true)
-@end
-
// Verify that we successfully parse and preserve this attribute in
// this position.
@interface Test66
@@ -1932,7 +1481,59 @@ void test66(void) {
// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T4]])
// CHECK-NEXT: [[T6:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
// CHECK-NEXT: [[T7:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
-// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]])
-// CHECK-NEXT: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
+// CHECK-NEXT: [[SIX:%.*]] = icmp eq i8* [[T7]], null
+// CHECK-NEXT: br i1 [[SIX]], label [[NULINIT:%.*]], label [[CALL:%.*]]
+// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*)*)(i8* [[T7]], i8* [[T6]], i8* [[T5]])
+// CHECK-NEXT: br label [[CONT:%.*]]
+// CHECK: call void @objc_release(i8* [[T5]]) nounwind
+// CHECK-NEXT: br label [[CONT:%.*]]
+// CHECK: [[T8:%.*]] = bitcast [[TEST66]]* [[T3]] to i8*
// CHECK-NEXT: call void @objc_release(i8* [[T8]])
// CHECK-NEXT: ret void
+
+// rdar://problem/9953540
+Class test67_helper(void);
+void test67(void) {
+ Class cl = test67_helper();
+}
+// CHECK: define void @test67()
+// CHECK: [[CL:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()
+// CHECK-NEXT: store i8* [[T0]], i8** [[CL]], align 8
+// CHECK-NEXT: ret void
+
+Class test68_helper(void);
+void test68(void) {
+ __strong Class cl = test67_helper();
+}
+// CHECK: define void @test68()
+// CHECK: [[CL:%.*]] = alloca i8*, align 8
+// CHECK-NEXT: [[T0:%.*]] = call i8* @test67_helper()
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: store i8* [[T1]], i8** [[CL]], align 8
+// CHECK-NEXT: [[T2:%.*]] = load i8** [[CL]]
+// CHECK-NEXT: call void @objc_release(i8* [[T2]])
+// CHECK-NEXT: ret void
+
+// rdar://problem/10564852
+@interface Test69 @end
+@implementation Test69
+- (id) foo { return self; }
+@end
+// CHECK: define internal i8* @"\01-[Test69 foo]"(
+// CHECK: [[SELF:%.*]] = alloca [[TEST69:%.*]]*, align 8
+// CHECK: [[T0:%.*]] = load [[TEST69]]** [[SELF]], align 8
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST69]]* [[T0]] to i8*
+// CHECK-NEXT: ret i8* [[T1]]
+
+// rdar://problem/10907547
+void test70(id i) {
+ // CHECK: define void @test70
+ // CHECK: store i8* null, i8**
+ // CHECK: store i8* null, i8**
+ // CHECK: [[ID:%.*]] = call i8* @objc_retain(i8*
+ // CHECK: store i8* [[ID]], i8**
+ id x[3] = {
+ [2] = i
+ };
+}
diff --git a/test/CodeGenObjC/auto-property-synthesize-protocol.m b/test/CodeGenObjC/auto-property-synthesize-protocol.m
new file mode 100644
index 0000000000000..49a4037e26453
--- /dev/null
+++ b/test/CodeGenObjC/auto-property-synthesize-protocol.m
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fobjc-default-synthesize-properties -emit-llvm %s -o - | FileCheck %s
+// rdar://10907410
+
+@protocol P
+@optional
+@property int auto_opt_window;
+@property int no_auto_opt_window;
+@end
+
+@interface I<P>
+@property int auto_opt_window;
+@end
+
+@implementation I
+@end
+
+@protocol P1
+@property int auto_req_window;
+@property int no_auto_req_window; // expected-note {{property declared here}}
+@end
+
+@interface I1<P1>
+@property int auto_req_window;
+@end
+
+@implementation I1 // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}}
+@end
+
+// CHECK: define internal i32 @"\01-[I auto_opt_window]"(
+// CHECK: define internal void @"\01-[I setAuto_opt_window:]"(
+// CHECK: define internal i32 @"\01-[I1 auto_req_window]"(
+// CHECK: define internal void @"\01-[I1 setAuto_req_window:]"(
+
+// CHECK-NOT: define internal i32 @"\01-[I1 no_auto_opt_window]"(
+// CHECK-NOT: define internal void @"\01-[I1 setNo_auto_opt_window:]"(
+// CHECK-NOT: define internal i32 @"\01-[I no_auto_req_window]"(
+// CHECK-NOT: define internal void @"\01-[I setNo_auto_req_window:]"(
diff --git a/test/CodeGenObjC/catch-lexical-block.m b/test/CodeGenObjC/catch-lexical-block.m
new file mode 100644
index 0000000000000..f4a6a222182e6
--- /dev/null
+++ b/test/CodeGenObjC/catch-lexical-block.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -g -fobjc-exceptions -emit-llvm %s -o - | FileCheck %s
+@interface Foo @end
+void f0() {
+ @try {
+ @throw @"a";
+ } @catch(Foo *e) {
+ }
+}
+
+// We should have 4 lexical blocks here at the moment, including one
+// for the catch block.
+// CHECK: lexical_block
+// CHECK: lexical_block
+// CHECK: lexical_block
+// CHECK: auto_variable
+// CHECK: lexical_block
diff --git a/test/CodeGenObjC/complex-double-abi.m b/test/CodeGenObjC/complex-double-abi.m
new file mode 100644
index 0000000000000..08246d5824f68
--- /dev/null
+++ b/test/CodeGenObjC/complex-double-abi.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -emit-llvm -triple i386-apple-macosx10.7.2 %s -o - | FileCheck %s
+// rdar://10331109
+
+@interface CNumber
+- (double _Complex)sum;
+@end
+
+double _Complex foo(CNumber *x) {
+ return [x sum];
+}
+
+// CHECK: [[T4:%.*]] = phi double [ 0.000000e+00, [[NULLINIT:%.*]] ], [ [[R1:%.*]], [[MSGCALL:%.*]] ]
+// CHECK: [[T5:%.*]] = phi double [ 0.000000e+00, [[NULLINIT:%.*]] ], [ [[I1:%.*]], [[MSGCALL:%.*]] ]
+
+// CHECK: store double [[T4]]
+// CHECK: store double [[T5]]
diff --git a/test/CodeGenObjC/constant-strings.m b/test/CodeGenObjC/constant-strings.m
index 398981362e086..c308d7a475dc8 100644
--- a/test/CodeGenObjC/constant-strings.m
+++ b/test/CodeGenObjC/constant-strings.m
@@ -8,11 +8,9 @@
// RUN: %clang_cc1 -fgnu-runtime -emit-llvm -o %t %s
// RUN: FileCheck --check-prefix=CHECK-GNU < %t %s
// CHECK-GNU: NXConstantString
-// CHECK-GNU-NOT: NXConstantString
// RUN: %clang_cc1 -fgnu-runtime -fconstant-string-class NSConstantString -emit-llvm -o %t %s
// RUN: FileCheck --check-prefix=CHECK-GNU-WITH-CLASS < %t %s
// CHECK-GNU-WITH-CLASS: NSConstantString
-// CHECK-GNU-WITH-CLASS-NOT: NSConstantString
id a = @"Hello World!";
diff --git a/test/CodeGenObjC/debug-info-block-helper.m b/test/CodeGenObjC/debug-info-block-helper.m
index 644e458bbd2c5..83db0c97e5a80 100644
--- a/test/CodeGenObjC/debug-info-block-helper.m
+++ b/test/CodeGenObjC/debug-info-block-helper.m
@@ -1,8 +1,8 @@
// REQUIRES: x86-64-registered-target
-// RUN: %clang_cc1 -masm-verbose -S -fblocks -g -triple x86_64-apple-darwin10 -fobjc-fragile-abi %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -fblocks -g -triple x86_64-apple-darwin10 -fobjc-fragile-abi %s -o - | FileCheck %s
extern void foo(void(^)(void));
-// CHECK: .ascii "__destroy_helper_block_" ## DW_AT_name
+// CHECK: metadata !{i32 786478, i32 0, metadata !27, metadata !"__destroy_helper_block_", metadata !"__destroy_helper_block_", metadata !"", metadata !27, i32 24, metadata !43, i1 true, i1 true, i32 0, i32 0, null, i32 0, i1 false, void (i8*)* @__destroy_helper_block_, null, null, metadata !45, i32 24} ; [ DW_TAG_subprogram ]
@interface NSObject {
struct objc_object *isa;
diff --git a/test/CodeGenObjC/debug-info-fwddecl.m b/test/CodeGenObjC/debug-info-fwddecl.m
new file mode 100644
index 0000000000000..ebdc5f290a571
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-fwddecl.m
@@ -0,0 +1,5 @@
+// RUN: %clang -fverbose-asm -g -S -emit-llvm %s -o - | FileCheck %s
+@class ForwardObjcClass;
+ForwardObjcClass *ptr = 0;
+
+// CHECK: metadata !{i32 {{.*}}, null, metadata !"ForwardObjcClass", metadata !{{.*}}, i32 2, i32 0, i32 0, i32 0, i32 4, null, null, i32 16} ; [ DW_TAG_structure_type ]
diff --git a/test/CodeGenObjC/debug-info-getter-name.m b/test/CodeGenObjC/debug-info-getter-name.m
index e7d3a9a8749e5..3939f355b68f6 100644
--- a/test/CodeGenObjC/debug-info-getter-name.m
+++ b/test/CodeGenObjC/debug-info-getter-name.m
@@ -1,11 +1,7 @@
// REQUIRES: x86-64-registered-target
-// RUN: %clang_cc1 -fno-dwarf2-cfi-asm -triple x86_64-apple-darwin10 -fexceptions -fobjc-exceptions -S -g %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -fexceptions -fobjc-exceptions -g %s -o - | FileCheck %s
-//CHECK: "-[InstanceVariablesEverywhereButTheInterface someString]":
-//CHECK: .quad "-[InstanceVariablesEverywhereButTheInterface someString]"
-//CHECK: .ascii "-[InstanceVariablesEverywhereButTheInterface someString]"
-//CHECK: .asciz "-[InstanceVariablesEverywhereButTheInterface someString]"
-//CHECK: "-[InstanceVariablesEverywhereButTheInterface someString].eh":
+// CHECK: {{.*}}, metadata !"-[InstanceVariablesEverywhereButTheInterface someString]", {{.*}}} ; [ DW_TAG_subprogram ]
//rdar: //8498026
diff --git a/test/CodeGenObjC/debug-info-impl.m b/test/CodeGenObjC/debug-info-impl.m
new file mode 100644
index 0000000000000..8ad590357b0d6
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-impl.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -S -emit-llvm %s -o - | FileCheck %s
+// CHECK: metadata !{i32 {{.*}}, metadata {{.*}}, metadata !"Circle", metadata {{.*}}, i32 11, i64 64, i64 64, i32 0, i32 512, null, metadata {{.*}}, i32 16, i32 0} ; [ DW_TAG_structure_type ]
+@interface NSObject {
+ struct objc_object *isa;
+}
+@end
+
+@interface Shape : NSObject
+
+@end
+@interface Circle : Shape
+
+@end
+@implementation Circle
+
+@end
diff --git a/test/CodeGenObjC/debug-info-property.m b/test/CodeGenObjC/debug-info-property.m
index d86b7c7a5eba0..dd105a58bdf41 100644
--- a/test/CodeGenObjC/debug-info-property.m
+++ b/test/CodeGenObjC/debug-info-property.m
@@ -1,6 +1,8 @@
// RUN: %clang_cc1 -masm-verbose -S -g %s -o - | FileCheck %s
// CHECK: AT_APPLE_property_name
+// CHECK: AT_APPLE_property_attribute
+// CHECK: AT_APPLE_property
@interface I1 {
int p1;
}
diff --git a/test/CodeGenObjC/debug-info-property3.m b/test/CodeGenObjC/debug-info-property3.m
new file mode 100644
index 0000000000000..f96ec44c6b216
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-property3.m
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -S -emit-llvm -g %s -o - | FileCheck %s
+
+// CHECK: metadata !"p1", metadata !6, i32 5, metadata !"", metadata !"", i32 2316, metadata !9} ; [ DW_TAG_APPLE_property ]
+@interface I1
+@property int p1;
+@end
+
+@implementation I1
+@synthesize p1;
+@end
+
+void foo(I1 *iptr) {}
diff --git a/test/CodeGenObjC/debug-info-property4.m b/test/CodeGenObjC/debug-info-property4.m
new file mode 100644
index 0000000000000..6d9973c3e0e20
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-property4.m
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fobjc-default-synthesize-properties -masm-verbose -S -g %s -o - | FileCheck %s
+
+// CHECK: AT_APPLE_property_name
+// CHECK-NOT: AT_APPLE_property_getter
+// CHECK-NOT: AT_APPLE_property_setter
+// CHECK: AT_APPLE_property_attribute
+// CHECK: AT_APPLE_property
+
+
+@interface I1
+@property int p1;
+@end
+
+@implementation I1
+@end
+
+void foo(I1 *ptr) {}
diff --git a/test/CodeGenObjC/debug-info-property5.m b/test/CodeGenObjC/debug-info-property5.m
new file mode 100644
index 0000000000000..35215749ecd98
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-property5.m
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fobjc-default-synthesize-properties -masm-verbose -S -g %s -o - | FileCheck %s
+
+// CHECK: AT_APPLE_property_name
+// CHECK: AT_APPLE_property_getter
+// CHECK: AT_APPLE_property_setter
+// CHECK: AT_APPLE_property_attribute
+// CHECK: AT_APPLE_property
+
+@interface BaseClass2
+{
+ int _baseInt;
+}
+- (int) myGetBaseInt;
+- (void) mySetBaseInt: (int) in_int;
+@property(getter=myGetBaseInt,setter=mySetBaseInt:) int baseInt;
+@end
+
+@implementation BaseClass2
+
+- (int) myGetBaseInt
+{
+ return _baseInt;
+}
+
+- (void) mySetBaseInt: (int) in_int
+{
+ _baseInt = 2 * in_int;
+}
+@end
+
+
+void foo(BaseClass2 *ptr) {}
diff --git a/test/CodeGenObjC/debug-info-pubtypes.m b/test/CodeGenObjC/debug-info-pubtypes.m
index 744a366ce7c5f..658430d9307b1 100644
--- a/test/CodeGenObjC/debug-info-pubtypes.m
+++ b/test/CodeGenObjC/debug-info-pubtypes.m
@@ -1,12 +1,7 @@
// REQUIRES: x86-64-registered-target
-// RUN: %clang -cc1 -triple x86_64-apple-darwin10 -g -S %s -o %t
-// RUN: FileCheck %s < %t
+// RUN: %clang -cc1 -triple x86_64-apple-darwin10 -g -emit-llvm %s -o - | FileCheck %s
-//CHECK: .long Lset6
-//CHECK-NEXT: .long
-//CHECK-NEXT: .asciz "H"
-//CHECK-NEXT: .long 0
-//CHECK-NEXT: Lpubtypes_end1:
+// CHECK: !5 = metadata !{i32 {{.*}}, metadata !6, metadata !"H", metadata !6, i32 6, i64 0, i64 8, i32 0, i32 512, null, metadata !2, i32 16, i32 0} ; [ DW_TAG_structure_type ]
@interface H
-(void) foo;
diff --git a/test/CodeGenObjC/debug-info-static-var.m b/test/CodeGenObjC/debug-info-static-var.m
index 1f281d042d106..c65e77c4d8d4c 100644
--- a/test/CodeGenObjC/debug-info-static-var.m
+++ b/test/CodeGenObjC/debug-info-static-var.m
@@ -3,9 +3,8 @@
// Radar 8801045
// Do not emit AT_MIPS_linkage_name for static variable i
-// CHECK: DW_TAG_variable
-// CHECK-NEXT: .byte 105 ## DW_AT_name
-// CHECK-NEXT: .byte 0
+// CHECK: Lset6 = Lstring3-Lsection_str ## DW_AT_name
+// CHECK-NEXT: .long Lset6
// CHECK-NEXT: DW_AT_type
// CHECK-NEXT: DW_AT_decl_file
// CHECK-NEXT: DW_AT_decl_line
diff --git a/test/CodeGenObjC/debug-info-synthesis.m b/test/CodeGenObjC/debug-info-synthesis.m
new file mode 100644
index 0000000000000..7e263cf74c6ee
--- /dev/null
+++ b/test/CodeGenObjC/debug-info-synthesis.m
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -emit-llvm -g -w -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
+# 1 "foo.m" 1
+# 1 "foo.m" 2
+# 1 "./foo.h" 1
+@interface NSObject {
+ struct objc_object *isa;
+}
+@end
+@class NSDictionary;
+
+@interface Foo : NSObject {}
+@property (strong, nonatomic) NSDictionary *dict;
+@end
+# 2 "foo.m" 2
+
+
+
+
+@implementation Foo
+@synthesize dict = _dict;
+
+- (void) bork {
+}
+@end
+
+int main(int argc, char *argv[]) {
+ @autoreleasepool {
+ Foo *f = [Foo new];
+ [f bork];
+ }
+}
+
+// CHECK: !7 = metadata !{i32 {{.*}}, metadata !"./foo.h"
+// CHECK: !31 = metadata !{i32 {{.*}}, i32 0, metadata !7, metadata !"-[Foo dict]", metadata !"-[Foo dict]", metadata !"", metadata !7, i32 8, metadata !32, i1 true, i1 true, i32 0, i32 0, null, i32 320, i1 false, %1* (%0*, i8*)* @"\01-[Foo dict]", null, null, metadata !34, i32 8} ; [ DW_TAG_subprogram ]
diff --git a/test/CodeGenObjC/debug-property-synth.m b/test/CodeGenObjC/debug-property-synth.m
index 05852b7e29254..954620a635980 100644
--- a/test/CodeGenObjC/debug-property-synth.m
+++ b/test/CodeGenObjC/debug-property-synth.m
@@ -16,4 +16,5 @@ int main() {
return 0;
}
-// CHECK: .loc 2 10 0
+// FIXME: Make this test ir files.
+// CHECK: .loc 2 6 0
diff --git a/test/CodeGenObjC/exceptions.m b/test/CodeGenObjC/exceptions.m
index 2472869ff58b5..24fb6575e4403 100644
--- a/test/CodeGenObjC/exceptions.m
+++ b/test/CodeGenObjC/exceptions.m
@@ -53,11 +53,7 @@ int f2() {
// CHECK-NEXT: [[CAUGHT:%.*]] = icmp eq i32 [[SETJMP]], 0
// CHECK-NEXT: br i1 [[CAUGHT]]
@try {
- // If the optimizers ever figure out how to make this store 6,
- // that's okay.
- // CHECK: [[T1:%.*]] = load i32* [[X]]
- // CHECK-NEXT: [[T2:%.*]] = add nsw i32 [[T1]], 1
- // CHECK-NEXT: store i32 [[T2]], i32* [[X]]
+ // CHECK: store i32 6, i32* [[X]]
x++;
// CHECK-NEXT: call void asm sideeffect "", "*m,*m"(i32* [[X]]
// CHECK-NEXT: call void @foo()
diff --git a/test/CodeGenObjC/forward-class-impl-metadata.m b/test/CodeGenObjC/forward-class-impl-metadata.m
index e9e08589d19f1..371abf2ade9cd 100644
--- a/test/CodeGenObjC/forward-class-impl-metadata.m
+++ b/test/CodeGenObjC/forward-class-impl-metadata.m
@@ -39,3 +39,9 @@ int f0(A *a) {
@implementation A
@synthesize p0 = _p0;
@end
+
+@interface B
+@end
+@class B;
+@implementation B
+@end
diff --git a/test/CodeGenObjC/fp2ret.m b/test/CodeGenObjC/fp2ret.m
new file mode 100644
index 0000000000000..9c956aec9b3f2
--- /dev/null
+++ b/test/CodeGenObjC/fp2ret.m
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple i386-apple-darwin9 -fobjc-fragile-abi -emit-llvm -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-X86_32 %s
+//
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-X86_64 %s
+//
+// RUN: %clang_cc1 -triple armv7-apple-darwin10 -fobjc-fragile-abi -emit-llvm -target-abi apcs-gnu -o - %s | \
+// RUN: FileCheck --check-prefix=CHECK-ARMV7 %s
+
+@interface A
+-(_Complex long double) complexLongDoubleValue;
+@end
+
+
+// CHECK-X86_32: define void @t0()
+// CHECK-X86_32: call void bitcast {{.*}} @objc_msgSend_stret to
+// CHECK-X86_32: }
+//
+// CHECK-X86_64: define void @t0()
+// CHECK-X86_64: call { x86_fp80, x86_fp80 } bitcast {{.*}} @objc_msgSend_fp2ret to
+// CHECK-X86_64: }
+//
+// CHECK-ARMV7: define void @t0()
+// CHECK-ARMV7: call i128 bitcast {{.*}} @objc_msgSend to
+// CHECK-ARMV7: }
+void t0() {
+ [(A*)0 complexLongDoubleValue];
+}
diff --git a/test/CodeGenObjC/image-info.m b/test/CodeGenObjC/image-info.m
index 22f7229b69508..613b272bdea25 100644
--- a/test/CodeGenObjC/image-info.m
+++ b/test/CodeGenObjC/image-info.m
@@ -4,5 +4,14 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o %t %s
// RUN: FileCheck --check-prefix CHECK-NONFRAGILE < %t %s
-// CHECK-FRAGILE: @"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__OBJC, __image_info,regular"
-// CHECK-NONFRAGILE: @"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"
+// CHECK-FRAGILE: !llvm.module.flags = !{!0, !1, !2, !3}
+// CHECK-FRAGILE: !0 = metadata !{i32 1, metadata !"Objective-C Version", i32 1}
+// CHECK-FRAGILE-NEXT: !1 = metadata !{i32 1, metadata !"Objective-C Image Info Version", i32 0}
+// CHECK-FRAGILE-NEXT: !2 = metadata !{i32 1, metadata !"Objective-C Image Info Section", metadata !"__OBJC, __image_info,regular"}
+// CHECK-FRAGILE-NEXT: !3 = metadata !{i32 4, metadata !"Objective-C Garbage Collection", i32 0}
+
+// CHECK-NONFRAGILE: !llvm.module.flags = !{!0, !1, !2, !3}
+// CHECK-NONFRAGILE: !0 = metadata !{i32 1, metadata !"Objective-C Version", i32 2}
+// CHECK-NONFRAGILE-NEXT: !1 = metadata !{i32 1, metadata !"Objective-C Image Info Version", i32 0}
+// CHECK-NONFRAGILE-NEXT: !2 = metadata !{i32 1, metadata !"Objective-C Image Info Section", metadata !"__DATA, __objc_imageinfo, regular, no_dead_strip"}
+// CHECK-NONFRAGILE-NEXT: !3 = metadata !{i32 4, metadata !"Objective-C Garbage Collection", i32 0}
diff --git a/test/CodeGenObjC/ivar-base-as-invariant-load.m b/test/CodeGenObjC/ivar-base-as-invariant-load.m
new file mode 100644
index 0000000000000..8b660cf483d95
--- /dev/null
+++ b/test/CodeGenObjC/ivar-base-as-invariant-load.m
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -x objective-c %s -o - | FileCheck %s
+// rdar://10840980
+
+@interface A {
+ struct {
+ unsigned char a : 1;
+ unsigned char b : 1;
+ unsigned char c : 1;
+ } _flags;
+}
+
+@end
+
+@implementation A
+
+- (id)init {
+ _flags.a = 1;
+ _flags.b = 1;
+ _flags.c = 1;
+
+ return self;
+}
+
+@end
+
+// CHECK: [[T1:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4
+// CHECK: [[T2:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4
+// CHECK: [[T3:%.*]] = load i64* @"OBJC_IVAR_$_A._flags", !invariant.load !4
+
diff --git a/test/CodeGenObjC/ns_consume_null_check.m b/test/CodeGenObjC/ns_consume_null_check.m
new file mode 100644
index 0000000000000..e3b60759e91b3
--- /dev/null
+++ b/test/CodeGenObjC/ns_consume_null_check.m
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-dispatch-method=mixed -o - %s | FileCheck %s
+// rdar://10444476
+
+@interface NSObject
+- (id) new;
+@end
+
+@interface MyObject : NSObject
+- (char)isEqual:(id) __attribute__((ns_consumed)) object;
+@end
+
+MyObject *x;
+
+void foo()
+{
+ id obj = [NSObject new];
+ [x isEqual : obj];
+}
+
+// CHECK: [[TMP:%.*]] = alloca i8
+// CHECK: [[FIVE:%.*]] = call i8* @objc_retain
+// CHECK-NEXT: [[SIX:%.*]] = bitcast
+// CHECK-NEXT: [[SEVEN:%.*]] = icmp eq i8* [[SIX]], null
+// CHECK-NEXT: br i1 [[SEVEN]], label [[NULLINIT:%.*]], label [[CALL_LABEL:%.*]]
+// CHECK: [[FN:%.*]] = load i8** getelementptr inbounds
+// CHECK-NEXT: [[EIGHT:%.*]] = bitcast i8* [[FN]]
+// CHECK-NEXT: [[CALL:%.*]] = call signext i8 [[EIGHT]]
+// CHECK-NEXT store i8 [[CALL]], i8* [[TMP]]
+// CHECK-NEXT br label [[CONT:%.*]]
+// CHECK: call void @objc_release(i8* [[FIVE]]) nounwind
+// CHECK-NEXT: call void @llvm.memset
+// CHECK-NEXT br label [[CONT]]
diff --git a/test/CodeGenObjC/objc-align.m b/test/CodeGenObjC/objc-align.m
index f07272516f1c0..f3c586eeb2149 100644
--- a/test/CodeGenObjC/objc-align.m
+++ b/test/CodeGenObjC/objc-align.m
@@ -6,7 +6,6 @@
// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t
// RUN: grep '@"\\01L_OBJC_CLASS_C" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t
// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_C" = internal global .*, section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t
-// RUN: grep '@"\\01L_OBJC_IMAGE_INFO" = internal constant .*, section "__OBJC, __image_info,regular"' %t
// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t
// RUN: grep '@"\\01L_OBJC_METACLASS_C" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t
// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*, section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t
@@ -20,7 +19,6 @@
// RUNX: grep '@"OBJC_METACLASS_$_A" = global' %t &&
// RUNX: grep '@"OBJC_METACLASS_$_C" = global' %t &&
// RUNX: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_0" = internal global .*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t &&
-// RUNX: grep '@"\\01L_OBJC_IMAGE_INFO" = internal constant .*, section "__DATA, __objc_imageinfo, regular, no_dead_strip"' %t &&
// RUNX: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .*, section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t &&
// RUNX: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .*, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t &&
// RUNX: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .*, section "__DATA, __objc_const", align 8' %t &&
diff --git a/test/CodeGenObjC/objc-arc-container-subscripting.m b/test/CodeGenObjC/objc-arc-container-subscripting.m
new file mode 100644
index 0000000000000..892491630e6e5
--- /dev/null
+++ b/test/CodeGenObjC/objc-arc-container-subscripting.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fobjc-arc -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
+
+@interface NSMutableArray
+- (id)objectAtIndexedSubscript:(int)index;
+- (void)setObject:(id)object atIndexedSubscript:(int)index;
+@end
+
+id func() {
+ NSMutableArray *array;
+ array[3] = 0;
+ return array[3];
+}
+
+// CHECK: [[call:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend
+// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind
+// CHECK: [[ARRAY:%.*]] = load %0**
+// CHECK: [[ARRAY_CASTED:%.*]] = bitcast{{.*}}[[ARRAY]] to i8*
+// CHECK: call void @objc_release(i8* [[ARRAY_CASTED]])
+// CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind
+// CHECK: ret i8* [[EIGHT]]
+
diff --git a/test/CodeGenObjC/objc-container-subscripting-1.m b/test/CodeGenObjC/objc-container-subscripting-1.m
new file mode 100644
index 0000000000000..91b7f468ea958
--- /dev/null
+++ b/test/CodeGenObjC/objc-container-subscripting-1.m
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s
+
+typedef unsigned int size_t;
+@protocol P @end
+
+@interface NSMutableArray
+- (id)objectAtIndexedSubscript:(size_t)index;
+- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
+@end
+
+@interface NSMutableDictionary
+- (id)objectForKeyedSubscript:(id)key;
+- (void)setObject:(id)object forKeyedSubscript:(id)key;
+@end
+
+int main() {
+ NSMutableArray *array;
+ id val;
+
+ id oldObject = array[10];
+// CHECK: [[ARR:%.*]] = load {{%.*}} [[array:%.*]], align 8
+// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_"
+// CHECK-NEXT: [[ARRC:%.*]] = bitcast {{%.*}} [[ARR]] to i8*
+// CHECK-NEXT: [[CALL:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i32)*)(i8* [[ARRC]], i8* [[SEL]], i32 10)
+// CHECK-NEXT: store i8* [[CALL]], i8** [[OLDOBJ:%.*]], align 8
+
+ val = (array[10] = oldObject);
+// CHECK: [[THREE:%.*]] = load {{%.*}} [[array:%.*]], align 8
+// CHECK-NEXT: [[FOUR:%.*]] = load i8** [[oldObject:%.*]], align 8
+// CHECK-NEXT: [[FIVE:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_2"
+// CHECK-NEXT: [[SIX:%.*]] = bitcast {{%.*}} [[THREE]] to i8*
+// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i32)*)(i8* [[SIX]], i8* [[FIVE]], i8* [[FOUR]], i32 10)
+// CHECK-NEXT: store i8* [[FOUR]], i8** [[val:%.*]]
+
+ NSMutableDictionary *dictionary;
+ id key;
+ id newObject;
+ oldObject = dictionary[key];
+// CHECK: [[SEVEN:%.*]] = load {{%.*}} [[DICTIONARY:%.*]], align 8
+// CHECK-NEXT: [[EIGHT:%.*]] = load i8** [[KEY:%.*]], align 8
+// CHECK-NEXT: [[TEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_4"
+// CHECK-NEXT: [[ELEVEN:%.*]] = bitcast {{%.*}} [[SEVEN]] to i8*
+// CHECK-NEXT: [[CALL1:%.*]] = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*, i8*)*)(i8* [[ELEVEN]], i8* [[TEN]], i8* [[EIGHT]])
+// CHECK-NEXT: store i8* [[CALL1]], i8** [[oldObject:%.*]], align 8
+
+
+ val = (dictionary[key] = newObject);
+// CHECK: [[TWELVE:%.*]] = load {{%.*}} [[DICTIONARY]], align 8
+// CHECK-NEXT: [[THIRTEEN:%.*]] = load i8** [[KEY]], align 8
+// CHECK-NEXT: [[FOURTEEN:%.*]] = load i8** [[NEWOBJECT:%.*]], align 8
+// CHECK-NEXT: [[SIXTEEN:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_6"
+// CHECK-NEXT: [[SEVENTEEN:%.*]] = bitcast {{%.*}} [[TWELVE]] to i8*
+// CHECK-NEXT: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8*, i8*)*)(i8* [[SEVENTEEN]], i8* [[SIXTEEN]], i8* [[FOURTEEN]], i8* [[THIRTEEN]])
+// CHECK-NEXT: store i8* [[FOURTEEN]], i8** [[val:%.*]]
+}
+
diff --git a/test/CodeGenObjC/objc-container-subscripting.m b/test/CodeGenObjC/objc-container-subscripting.m
new file mode 100644
index 0000000000000..fd8f8effac6d0
--- /dev/null
+++ b/test/CodeGenObjC/objc-container-subscripting.m
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o /dev/null
+
+typedef unsigned int size_t;
+@protocol P @end
+
+@interface NSMutableArray
+#if __has_feature(objc_subscripting)
+- (id)objectAtIndexedSubscript:(size_t)index;
+- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
+#endif
+@end
+
+#if __has_feature(objc_subscripting)
+@interface XNSMutableArray
+- (id)objectAtIndexedSubscript:(size_t)index;
+- (void)setObject:(id)object atIndexedSubscript:(size_t)index;
+#endif
+@end
+
+@interface NSMutableDictionary
+- (id)objectForKeyedSubscript:(id)key;
+- (void)setObject:(id)object forKeyedSubscript:(id)key;
+@end
+
+@class NSString;
+
+int main() {
+ NSMutableArray<P> * array;
+ id oldObject = array[10];
+
+ array[10] = oldObject;
+
+ id unknown_array;
+ oldObject = unknown_array[1];
+
+ unknown_array[1] = oldObject;
+
+ NSMutableDictionary *dictionary;
+ NSString *key;
+ id newObject;
+ oldObject = dictionary[key];
+ dictionary[key] = newObject; // replace oldObject with newObject
+
+}
+
diff --git a/test/CodeGenObjC/objc-dictionary-literal.m b/test/CodeGenObjC/objc-dictionary-literal.m
new file mode 100644
index 0000000000000..b335582ed2be8
--- /dev/null
+++ b/test/CodeGenObjC/objc-dictionary-literal.m
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o /dev/null
+// rdar://10614657
+
+@interface NSNumber
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithInt:(int)value;
+@end
+
+@protocol NSCopying @end
+typedef unsigned long NSUInteger;
+
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
+@end
+
+@interface NSString<NSCopying>
+@end
+
+int main() {
+ NSDictionary *dict = @{ @"name":@666 };
+ NSDictionary *dict1 = @{ @"name":@666 };
+ NSDictionary *dict2 = @{ @"name":@666 };
+ return 0;
+}
diff --git a/test/CodeGenObjC/objc-literal-debugger-test.m b/test/CodeGenObjC/objc-literal-debugger-test.m
new file mode 100644
index 0000000000000..389ef2248a481
--- /dev/null
+++ b/test/CodeGenObjC/objc-literal-debugger-test.m
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fdebugger-objc-literal -emit-llvm -o - %s | FileCheck %s
+
+int main() {
+ id l = @'a';
+ l = @'a';
+ l = @42;
+ l = @-42;
+ l = @42u;
+ l = @3.141592654f;
+ l = @__objc_yes;
+ l = @__objc_no;
+ l = @{ @"name":@666 };
+ l = @[ @"foo", @"bar" ];
+}
+
+// CHECK: declare i8* @objc_msgSend(i8*, i8*, ...) nonlazybind
diff --git a/test/CodeGenObjC/objc-literal-tests.m b/test/CodeGenObjC/objc-literal-tests.m
new file mode 100644
index 0000000000000..c513d4961103a
--- /dev/null
+++ b/test/CodeGenObjC/objc-literal-tests.m
@@ -0,0 +1,95 @@
+// RUN: %clang_cc1 -x objective-c -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fblocks -emit-llvm %s -o - | FileCheck %s
+// rdar://10111397
+
+#if __has_feature(objc_bool)
+#define YES __objc_yes
+#define NO __objc_no
+#else
+#define YES ((BOOL)1)
+#define NO ((BOOL)0)
+#endif
+
+#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
+typedef unsigned long NSUInteger;
+typedef long NSInteger;
+#else
+typedef unsigned int NSUInteger;
+typedef int NSInteger;
+#endif
+typedef signed char BOOL;
+
+@interface NSNumber @end
+
+@interface NSNumber (NSNumberCreation)
+#if __has_feature(objc_array_literals)
++ (NSNumber *)numberWithChar:(char)value;
++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value;
++ (NSNumber *)numberWithShort:(short)value;
++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value;
++ (NSNumber *)numberWithInt:(int)value;
++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value;
++ (NSNumber *)numberWithLong:(long)value;
++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value;
++ (NSNumber *)numberWithLongLong:(long long)value;
++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value;
++ (NSNumber *)numberWithFloat:(float)value;
++ (NSNumber *)numberWithDouble:(double)value;
++ (NSNumber *)numberWithBool:(BOOL)value;
++ (NSNumber *)numberWithInteger:(NSInteger)value ;
++ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value ;
+#endif
+@end
+
+@interface NSDate
++ (NSDate *) date;
+@end
+
+#if __has_feature(objc_dictionary_literals)
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(NSUInteger)cnt;
+@end
+#endif
+
+id NSUserName();
+
+// CHECK: define i32 @main() nounwind
+int main() {
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 97
+ NSNumber *aNumber = @'a';
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
+ NSNumber *fortyTwo = @42;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 -42
+ NSNumber *negativeFortyTwo = @-42;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
+ NSNumber *positiveFortyTwo = @+42;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i32 42
+ NSNumber *fortyTwoUnsigned = @42u;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42
+ NSNumber *fortyTwoLong = @42l;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i64 42
+ NSNumber *fortyTwoLongLong = @42ll;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}float 0x400921FB60000000
+ NSNumber *piFloat = @3.141592654f;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}double 0x400921FB54411744
+ NSNumber *piDouble = @3.1415926535;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1
+ NSNumber *yesNumber = @__objc_yes;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0
+ NSNumber *noNumber = @__objc_no;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 1
+ NSNumber *yesNumber1 = @YES;
+ // CHECK: call{{.*}}@objc_msgSend{{.*}}i8 signext 0
+ NSNumber *noNumber1 = @NO;
+NSDictionary *dictionary = @{@"name" : NSUserName(),
+ @"date" : [NSDate date] };
+ return __objc_yes == __objc_no;
+}
+
+// rdar://10579122
+typedef BOOL (^foo)(void);
+extern void bar(foo a);
+
+void baz(void) {
+ bar(^(void) { return YES; });
+}
diff --git a/test/CodeGenObjC/optimized-setter.m b/test/CodeGenObjC/optimized-setter.m
new file mode 100644
index 0000000000000..0e1b388595198
--- /dev/null
+++ b/test/CodeGenObjC/optimized-setter.m
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 %s -emit-llvm -triple x86_64-apple-macosx10.8.0 -o - | FileCheck %s
+// rdar://10179974
+
+@interface I
+// void objc_setProperty_nonatomic(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., NO, NO)
+@property (nonatomic, retain) id nonatomicProperty;
+
+// void objc_setProperty_nonatomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., NO, YES)
+@property (nonatomic, copy) id nonatomicPropertyCopy;
+
+// void objc_setProperty_atomic(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., YES, NO)
+@property (retain) id atomicProperty;
+
+// void objc_setProperty_atomic_copy(id self, SEL _cmd, id newValue, ptrdiff_t offset);
+// objc_setProperty(..., YES, YES)
+@property (copy) id atomicPropertyCopy;
+@end
+
+@implementation I
+@synthesize nonatomicProperty;
+@synthesize nonatomicPropertyCopy;
+@synthesize atomicProperty;
+@synthesize atomicPropertyCopy;
+@end
+
+// CHECK: call void @objc_setProperty_nonatomic
+// CHECK: call void @objc_setProperty_nonatomic_copy
+// CHECK: call void @objc_setProperty_atomic
+// CHECK: call void @objc_setProperty_atomic_copy
+
diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m
index 3cc9200f333c8..16881d608bf2e 100644
--- a/test/CodeGenObjC/property.m
+++ b/test/CodeGenObjC/property.m
@@ -112,3 +112,57 @@ void test4(Test4 *t) {
@implementation Test5
@synthesize x = _x;
@end
+
+// rdar://problem/10410531
+@interface Test6
+@property void (*prop)(void);
+@end
+
+void test6_func(void);
+void test6(Test6 *a) {
+ a.prop = test6_func;
+}
+
+// rdar://problem/10507455
+@interface Test7
+@property unsigned char x;
+@end
+void test7(Test7 *t) {
+ t.x &= 2;
+ t.x |= 5;
+ t.x ^= 8;
+}
+// CHECK: define void @test7([[TEST7:%.*]]*
+// CHECK: [[T:%.*]] = alloca [[TEST7]]*,
+// CHECK-NEXT: store
+// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align
+// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast
+// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
+// CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], 2
+// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
+// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
+// CHECK-NEXT: call void bitcast
+// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align
+// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast
+// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
+// CHECK-NEXT: [[T4:%.*]] = or i32 [[T3]], 5
+// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
+// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
+// CHECK-NEXT: call void bitcast
+// CHECK-NEXT: [[T0:%.*]] = load [[TEST7]]** [[T]], align
+// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call zeroext i8 bitcast
+// CHECK-NEXT: [[T3:%.*]] = zext i8 [[T2]] to i32
+// CHECK-NEXT: [[T4:%.*]] = xor i32 [[T3]], 8
+// CHECK-NEXT: [[T5:%.*]] = trunc i32 [[T4]] to i8
+// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T6:%.*]] = bitcast [[TEST7]]* [[T0]] to i8*
+// CHECK-NEXT: call void bitcast
+// CHECK-NEXT: ret void
diff --git a/test/CodeGenObjC/selector-ref-invariance.m b/test/CodeGenObjC/selector-ref-invariance.m
new file mode 100644
index 0000000000000..e356419de9e8c
--- /dev/null
+++ b/test/CodeGenObjC/selector-ref-invariance.m
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -emit-llvm -fblocks -o - %s | FileCheck %s
+
+// rdar://6027699
+
+void test(id x) {
+// CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", !invariant.load
+// CHECK: @objc_msgSend
+ [x foo];
+}
diff --git a/test/CodeGenObjC/variadic-sends.m b/test/CodeGenObjC/variadic-sends.m
index 7e557b0178d8d..94d7bafba472a 100644
--- a/test/CodeGenObjC/variadic-sends.m
+++ b/test/CodeGenObjC/variadic-sends.m
@@ -20,8 +20,8 @@ void f1(A *a) {
}
void f2(A *a) {
- // CHECK-X86-32: call void (i8*, i8*, i32, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, i32, ...)*)
- // CHECK-X86-64: call void (i8*, i8*, i32, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, i32, ...)*)
+ // CHECK-X86-32: call void (i8*, i8*, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, ...)*)
+ // CHECK-X86-64: call void (i8*, i8*, i32, ...)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i32, ...)*)
[a im2: 1, 2];
}
@@ -33,8 +33,8 @@ void f2(A *a) {
[super im1: 1];
}
-(void) bar {
- // CHECK-X86-32: call void (%struct._objc_super*, i8*, i32, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, i32, ...)*)
- // CHECK-X86-64: call void (%struct._objc_super*, i8*, i32, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, i32, ...)*)
+ // CHECK-X86-32: call void (%struct._objc_super*, i8*, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, ...)*)
+ // CHECK-X86-64: call void (%struct._objc_super*, i8*, i32, ...)* bitcast (i8* (%struct._objc_super*, i8*, ...)* @objc_msgSendSuper to void (%struct._objc_super*, i8*, i32, ...)*)
[super im2: 1, 2];
}