1// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-freebsd -fobjc-arc -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
2
3typedef struct {
4  int x[12];
5} Big;
6
7@protocol P
8- (Big) foo;
9- (Big) fooConsuming: (__attribute__((ns_consumed)) id) arg;
10- (_Complex float) complex;
11@end
12
13@interface SuperClass
14- (Big) foo;
15@end
16
17@implementation TestClass : SuperClass
18//   Check that we don't do a nil check when messaging self in ARC
19//   (which forbids reassigning self)
20// CHECK-LABEL: define{{.*}} void @_i_TestClass__test_self_send(
21// CHECK-NOT:   icmp
22// CHECK:       @objc_msg_lookup_sender
23- (void) test_self_send {
24  Big big = [self foo];
25}
26
27//   Check that we don't do a nil test when messaging super.
28// CHECK-LABEL: define{{.*}} void @_i_TestClass__test_super_send(
29// CHECK-NOT:   icmp
30// CHECK:       @objc_msg_lookup_super
31- (void) test_super_send {
32  Big big = [super foo];
33}
34@end
35
36// CHECK-LABEL: define{{.*}} void @test_loop_zeroing(
37// CHECK:         [[P:%.*]] = alloca i8*,
38// CHECK:         [[BIG:%.*]] = alloca %struct.Big,
39// CHECK:         br label %for.cond
40//
41// CHECK:       for.cond:
42// CHECK-NEXT:    [[RECEIVER:%.*]] = load i8*, i8** [[P]],
43// CHECK-NEXT:    [[ISNIL:%.*]] = icmp eq i8* [[RECEIVER]], null
44// CHECK-NEXT:    br i1 [[ISNIL]], label %nilReceiverCleanup, label %msgSend
45//
46// CHECK:       msgSend:
47// CHECK:         @objc_msg_lookup_sender
48// CHECK:         call void {{%.*}}({{.*}} [[BIG]],
49// CHECK:         br label %continue
50//
51// CHECK:       nilReceiverCleanup:
52// CHECK-NEXT:    [[T0:%.*]] = bitcast %struct.Big* [[BIG]] to i8*
53// CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[T0]], i8 0, i64 48, i1 false)
54// CHECK-NEXT:    br label %continue
55//
56// CHECK:       continue:
57// CHECK-NEXT:    br label %for.cond
58void test_loop_zeroing(id<P> p) {
59  for (;;) {
60    Big big = [p foo];
61  }
62}
63
64// CHECK-LABEL: define{{.*}} void @test_zeroing_and_consume(
65// CHECK:         [[P:%.*]] = alloca i8*,
66// CHECK:         [[Q:%.*]] = alloca i8*,
67// CHECK:         [[BIG:%.*]] = alloca %struct.Big,
68// CHECK:         br label %for.cond
69//
70// CHECK:       for.cond:
71// CHECK-NEXT:    [[RECEIVER:%.*]] = load i8*, i8** [[P]],
72// CHECK-NEXT:    [[Q_LOAD:%.*]] = load i8*, i8** [[Q]],
73// CHECK-NEXT:    [[Q_RETAIN:%.*]] = call i8* @llvm.objc.retain(i8* [[Q_LOAD]])
74// CHECK-NEXT:    [[ISNIL:%.*]] = icmp eq i8* [[RECEIVER]], null
75// CHECK-NEXT:    br i1 [[ISNIL]], label %nilReceiverCleanup, label %msgSend
76//
77// CHECK:       msgSend:
78// CHECK:         @objc_msg_lookup_sender
79// CHECK:         call void {{%.*}}({{.*}} [[BIG]],
80// CHECK:         br label %continue
81//
82// CHECK:       nilReceiverCleanup:
83// CHECK-NEXT:    call void @llvm.objc.release(i8* [[Q_RETAIN]])
84// CHECK-NEXT:    [[T0:%.*]] = bitcast %struct.Big* [[BIG]] to i8*
85// CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[T0]], i8 0, i64 48, i1 false)
86// CHECK-NEXT:    br label %continue
87//
88// CHECK:       continue:
89// CHECK-NEXT:    br label %for.cond
90void test_zeroing_and_consume(id<P> p, id q) {
91  for (;;) {
92    Big big = [p fooConsuming: q];
93  }
94}
95
96// CHECK-LABEL: define{{.*}} void @test_complex(
97// CHECK:         [[P:%.*]] = alloca i8*,
98// CHECK:         [[RECEIVER:%.*]] = load i8*, i8** [[P]],
99// CHECK-NEXT:    [[ISNIL:%.*]] = icmp eq i8* [[RECEIVER]], null
100// CHECK-NEXT:    br i1 [[ISNIL]], label %continue, label %msgSend
101// CHECK:       msgSend:
102// CHECK:         @objc_msg_lookup_sender
103// CHECK:         br label %continue
104// CHECK:       continue:
105// CHECK-NEXT:    phi float
106// CHECK-NEXT:    phi float
107void test_complex(id<P> p) {
108  _Complex float f = [p complex];
109}
110