xref: /llvm-project/clang/test/CodeGenObjC/gnu-nil-receiver.m (revision c5de4dd1eab00df76c1a68c5f397304ceacb71f2)
1// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -fobjc-arc -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 ptr,
38// CHECK:         [[BIG:%.*]] = alloca %struct.Big,
39// CHECK:         br label %for.cond
40//
41// CHECK:       for.cond:
42// CHECK-NEXT:    [[RECEIVER:%.*]] = load ptr, ptr [[P]],
43// CHECK-NEXT:    [[ISNIL:%.*]] = icmp eq ptr [[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:    call void @llvm.memset.p0.i64(ptr align 4 [[BIG]], i8 0, i64 48, i1 false)
53// CHECK-NEXT:    br label %continue
54//
55// CHECK:       continue:
56// CHECK-NEXT:    br label %for.cond
57void test_loop_zeroing(id<P> p) {
58  for (;;) {
59    Big big = [p foo];
60  }
61}
62
63// CHECK-LABEL: define{{.*}} void @test_zeroing_and_consume(
64// CHECK:         [[P:%.*]] = alloca ptr,
65// CHECK:         [[Q:%.*]] = alloca ptr,
66// CHECK:         [[BIG:%.*]] = alloca %struct.Big,
67// CHECK:         br label %for.cond
68//
69// CHECK:       for.cond:
70// CHECK-NEXT:    [[RECEIVER:%.*]] = load ptr, ptr [[P]],
71// CHECK-NEXT:    [[Q_LOAD:%.*]] = load ptr, ptr [[Q]],
72// CHECK-NEXT:    [[Q_RETAIN:%.*]] = call ptr @llvm.objc.retain(ptr [[Q_LOAD]])
73// CHECK-NEXT:    [[ISNIL:%.*]] = icmp eq ptr [[RECEIVER]], null
74// CHECK-NEXT:    br i1 [[ISNIL]], label %nilReceiverCleanup, label %msgSend
75//
76// CHECK:       msgSend:
77// CHECK:         @objc_msg_lookup_sender
78// CHECK:         call void {{%.*}}({{.*}} [[BIG]],
79// CHECK:         br label %continue
80//
81// CHECK:       nilReceiverCleanup:
82// CHECK-NEXT:    call void @llvm.objc.release(ptr [[Q_RETAIN]])
83// CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[BIG]], i8 0, i64 48, i1 false)
84// CHECK-NEXT:    br label %continue
85//
86// CHECK:       continue:
87// CHECK-NEXT:    br label %for.cond
88void test_zeroing_and_consume(id<P> p, id q) {
89  for (;;) {
90    Big big = [p fooConsuming: q];
91  }
92}
93
94// CHECK-LABEL: define{{.*}} void @test_complex(
95// CHECK:         [[P:%.*]] = alloca ptr,
96// CHECK:         [[RECEIVER:%.*]] = load ptr, ptr [[P]],
97// CHECK-NEXT:    [[ISNIL:%.*]] = icmp eq ptr [[RECEIVER]], null
98// CHECK-NEXT:    br i1 [[ISNIL]], label %continue, label %msgSend
99// CHECK:       msgSend:
100// CHECK:         @objc_msg_lookup_sender
101// CHECK:         br label %continue
102// CHECK:       continue:
103// CHECK-NEXT:    phi float
104// CHECK-NEXT:    phi float
105void test_complex(id<P> p) {
106  _Complex float f = [p complex];
107}
108