Mercurial > hg > CbC > CbC_llvm
comparison clang/test/CodeGenObjC/ubsan-nullability.m @ 252:1f2b6ac9f198 llvm-original
LLVM16-1
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 18 Aug 2023 09:04:13 +0900 |
parents | c4bab56944e8 |
children |
comparison
equal
deleted
inserted
replaced
237:c80f45b162ad | 252:1f2b6ac9f198 |
---|---|
1 // REQUIRES: asserts | 1 // REQUIRES: asserts |
2 // RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s | 2 // RUN: %clang_cc1 -no-enable-noundef-analysis -x objective-c -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s |
3 // RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s | 3 // RUN: %clang_cc1 -no-enable-noundef-analysis -x objective-c++ -emit-llvm -triple x86_64-apple-macosx10.10.0 -fblocks -fobjc-arc -fsanitize=nullability-arg,nullability-assign,nullability-return -w %s -o - | FileCheck %s |
4 | 4 |
5 // CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6 | 5 // CHECK: [[NONNULL_RV_LOC1:@.*]] = private unnamed_addr global {{.*}} i32 100, i32 6 |
6 // CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23 | 6 // CHECK: [[NONNULL_ARG_LOC:@.*]] = private unnamed_addr global {{.*}} i32 204, i32 15 {{.*}} i32 190, i32 23 |
7 // CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9 | 7 // CHECK: [[NONNULL_ASSIGN1_LOC:@.*]] = private unnamed_addr global {{.*}} i32 305, i32 9 |
8 // CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10 | 8 // CHECK: [[NONNULL_ASSIGN2_LOC:@.*]] = private unnamed_addr global {{.*}} i32 405, i32 10 |
14 | 14 |
15 #define NULL ((void *)0) | 15 #define NULL ((void *)0) |
16 #define INULL ((int *)NULL) | 16 #define INULL ((int *)NULL) |
17 #define INNULL ((int *_Nonnull)NULL) | 17 #define INNULL ((int *_Nonnull)NULL) |
18 | 18 |
19 // CHECK-LABEL: define{{.*}} i32* @{{.*}}nonnull_retval1 | 19 // CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval1 |
20 #line 100 | 20 #line 100 |
21 int *_Nonnull nonnull_retval1(int *p) { | 21 int *_Nonnull nonnull_retval1(int *p) { |
22 // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize | 22 // CHECK: nullcheck: |
23 // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize | |
23 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize | 24 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize |
24 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]] | 25 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC1]] |
25 return p; | 26 return p; |
26 // CHECK: ret i32* | 27 // CHECK: ret ptr |
27 } | 28 } |
28 | 29 |
29 #line 190 | 30 #line 190 |
30 void nonnull_arg(int *_Nonnull p) {} | 31 void nonnull_arg(int *_Nonnull p) {} |
31 | 32 |
32 // CHECK-LABEL: define{{.*}} void @{{.*}}call_func_with_nonnull_arg | 33 // CHECK-LABEL: define{{.*}} void @{{.*}}call_func_with_nonnull_arg |
33 #line 200 | 34 #line 200 |
34 void call_func_with_nonnull_arg(int *_Nonnull p) { | 35 void call_func_with_nonnull_arg(int *_Nonnull p) { |
35 // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize | 36 // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize |
36 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 37 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
37 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]] | 38 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}}[[NONNULL_ARG_LOC]] |
38 nonnull_arg(p); | 39 nonnull_arg(p); |
39 } | 40 } |
40 | 41 |
41 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign1 | 42 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign1 |
42 #line 300 | 43 #line 300 |
43 void nonnull_assign1(int *p) { | 44 void nonnull_assign1(int *p) { |
44 // CHECK: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize | 45 // CHECK: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize |
45 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 46 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
46 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]] | 47 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN1_LOC]] |
47 int *_Nonnull local; | 48 int *_Nonnull local; |
48 local = p; | 49 local = p; |
49 } | 50 } |
50 | 51 |
51 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign2 | 52 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign2 |
52 #line 400 | 53 #line 400 |
53 void nonnull_assign2(int *p) { | 54 void nonnull_assign2(int *p) { |
54 // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize | 55 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize |
55 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 56 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
56 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]] | 57 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN2_LOC]] |
57 int *_Nonnull arr[1]; | 58 int *_Nonnull arr[1]; |
58 arr[0] = p; | 59 arr[0] = p; |
59 } | 60 } |
63 }; | 64 }; |
64 | 65 |
65 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign3 | 66 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_assign3 |
66 #line 500 | 67 #line 500 |
67 void nonnull_assign3(int *p) { | 68 void nonnull_assign3(int *p) { |
68 // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize | 69 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize |
69 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 70 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
70 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]] | 71 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_ASSIGN3_LOC]] |
71 // CHECK-NOT: call void @__ubsan_handle_type_mismatch | 72 // CHECK-NOT: call void @__ubsan_handle_type_mismatch |
72 struct S1 s; | 73 struct S1 s; |
73 s.mptr = p; | 74 s.mptr = p; |
74 } | 75 } |
75 | 76 |
76 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init1 | 77 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init1 |
77 #line 600 | 78 #line 600 |
78 void nonnull_init1(int *p) { | 79 void nonnull_init1(int *p) { |
79 // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize | 80 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize |
80 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 81 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
81 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]] | 82 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT1_LOC]] |
82 int *_Nonnull local = p; | 83 int *_Nonnull local = p; |
83 } | 84 } |
84 | 85 |
85 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init2 | 86 // CHECK-LABEL: define{{.*}} void @{{.*}}nonnull_init2 |
86 #line 700 | 87 #line 700 |
87 void nonnull_init2(int *p) { | 88 void nonnull_init2(int *p) { |
88 // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize | 89 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize |
89 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 90 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
90 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]] | 91 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC1]] |
91 // CHECK: [[ICMP:%.*]] = icmp ne i32* %{{.*}}, null, !nosanitize | 92 // CHECK: [[ICMP:%.*]] = icmp ne ptr %{{.*}}, null, !nosanitize |
92 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 93 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
93 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]] | 94 // CHECK: call void @__ubsan_handle_type_mismatch{{.*}}[[NONNULL_INIT2_LOC2]] |
94 int *_Nonnull arr[] = {p, p}; | 95 int *_Nonnull arr[] = {p, p}; |
95 } | 96 } |
96 | 97 |
97 // CHECK-LABEL: define{{.*}} i32* @{{.*}}nonnull_retval2 | 98 // CHECK-LABEL: define{{.*}} ptr @{{.*}}nonnull_retval2 |
98 #line 800 | 99 #line 800 |
99 int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. | 100 int *_Nonnull nonnull_retval2(int *_Nonnull arg1, //< Test this. |
100 int *_Nonnull arg2, //< Test this. | 101 int *_Nonnull arg2, //< Test this. |
101 int *_Nullable arg3, //< Don't test the rest. | 102 int *_Nullable arg3, //< Don't test the rest. |
102 int *arg4, | 103 int *arg4, |
103 int arg5, ...) { | 104 int arg5, ...) { |
104 // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize | 105 // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize |
105 // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize | 106 // CHECK-NEXT: [[DO_RV_CHECK_1:%.*]] = and i1 true, [[ARG1CMP]], !nosanitize |
106 // CHECK: [[ARG2CMP:%.*]] = icmp ne i32* %arg2, null, !nosanitize | 107 // CHECK: [[ARG2CMP:%.*]] = icmp ne ptr %arg2, null, !nosanitize |
107 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]] | 108 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[DO_RV_CHECK_1]], [[ARG2CMP]] |
108 // CHECK: [[SLOC_PTR:%.*]] = load i8*, i8** %return.sloc.ptr | 109 // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr |
109 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne i8* [[SLOC_PTR]], null | 110 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null |
110 // CHECK-NEXT: [[DO_RV_CHECK_3:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK_2]] | 111 // CHECK-NEXT: [[DO_RV_CHECK_3:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK_2]] |
111 // CHECK: br i1 [[DO_RV_CHECK_3]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize | 112 // CHECK: br i1 [[DO_RV_CHECK_3]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
112 // CHECK: [[NULL]]: | 113 // CHECK: [[NULL]]: |
113 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize | 114 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize |
114 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize | 115 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize |
115 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]] | 116 // CHECK: call void @__ubsan_handle_nullability_return{{.*}}[[NONNULL_RV_LOC2]] |
116 return arg1; | 117 return arg1; |
117 // CHECK: [[NONULL]]: | 118 // CHECK: [[NONULL]]: |
118 // CHECK-NEXT: ret i32* | 119 // CHECK-NEXT: ret ptr |
119 } | 120 } |
120 | 121 |
121 @interface A | 122 @interface A |
122 +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1; | 123 +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1; |
123 -(int *_Nonnull) objc_method: (int *_Nonnull) arg1; | 124 -(int *_Nonnull) objc_method: (int *_Nonnull) arg1; |
124 @end | 125 @end |
125 | 126 |
126 @implementation A | 127 @implementation A |
127 | 128 |
128 // CHECK-LABEL: define internal i32* @"\01+[A objc_clsmethod:]" | 129 // CHECK-LABEL: define internal ptr @"\01+[A objc_clsmethod:]" |
129 +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 { | 130 +(int *_Nonnull) objc_clsmethod: (int *_Nonnull) arg1 { |
130 // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize | 131 // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize |
131 // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] | 132 // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] |
132 // CHECK: [[SLOC_PTR:%.*]] = load i8*, i8** %return.sloc.ptr | 133 // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr |
133 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne i8* [[SLOC_PTR]], null | 134 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null |
134 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]] | 135 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]] |
135 // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize | 136 // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
136 // CHECK: [[NULL]]: | 137 // CHECK: [[NULL]]: |
137 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize | 138 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize |
138 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize | 139 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize |
139 // CHECK: call void @__ubsan_handle_nullability_return{{.*}} | 140 // CHECK: call void @__ubsan_handle_nullability_return{{.*}} |
140 return arg1; | 141 return arg1; |
141 // CHECK: [[NONULL]]: | 142 // CHECK: [[NONULL]]: |
142 // CHECK-NEXT: ret i32* | 143 // CHECK-NEXT: ret ptr |
143 } | 144 } |
144 | 145 |
145 // CHECK-LABEL: define internal i32* @"\01-[A objc_method:]" | 146 // CHECK-LABEL: define internal ptr @"\01-[A objc_method:]" |
146 -(int *_Nonnull) objc_method: (int *_Nonnull) arg1 { | 147 -(int *_Nonnull) objc_method: (int *_Nonnull) arg1 { |
147 // CHECK: [[ARG1CMP:%.*]] = icmp ne i32* %arg1, null, !nosanitize | 148 // CHECK: [[ARG1CMP:%.*]] = icmp ne ptr %arg1, null, !nosanitize |
148 // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] | 149 // CHECK-NEXT: [[DO_RV_CHECK:%.*]] = and i1 true, [[ARG1CMP]] |
149 // CHECK: [[SLOC_PTR:%.*]] = load i8*, i8** %return.sloc.ptr | 150 // CHECK: [[SLOC_PTR:%.*]] = load ptr, ptr %return.sloc.ptr |
150 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne i8* [[SLOC_PTR]], null | 151 // CHECK-NEXT: [[SLOC_NONNULL:%.*]] = icmp ne ptr [[SLOC_PTR]], null |
151 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]] | 152 // CHECK-NEXT: [[DO_RV_CHECK_2:%.*]] = and i1 [[SLOC_NONNULL]], [[DO_RV_CHECK]] |
152 // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize | 153 // CHECK: br i1 [[DO_RV_CHECK_2]], label %[[NULL:.*]], label %[[NONULL:.*]], !nosanitize |
153 // CHECK: [[NULL]]: | 154 // CHECK: [[NULL]]: |
154 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne i32* {{.*}}, null, !nosanitize | 155 // CHECK-NEXT: [[ICMP:%.*]] = icmp ne ptr {{.*}}, null, !nosanitize |
155 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize | 156 // CHECK: br i1 [[ICMP]], {{.*}}, !nosanitize |
156 // CHECK: call void @__ubsan_handle_nullability_return{{.*}} | 157 // CHECK: call void @__ubsan_handle_nullability_return{{.*}} |
157 return arg1; | 158 return arg1; |
158 // CHECK: [[NONULL]]: | 159 // CHECK: [[NONULL]]: |
159 // CHECK-NEXT: ret i32* | 160 // CHECK-NEXT: ret ptr |
160 } | 161 } |
161 @end | 162 @end |
162 | 163 |
163 // CHECK-LABEL: define{{.*}} void @{{.*}}call_A | 164 // CHECK-LABEL: define{{.*}} void @{{.*}}call_A |
164 void call_A(A *a, int *p) { | 165 void call_A(A *a, int *p) { |
165 // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P1:%.*]], null, !nosanitize | 166 // CHECK: [[ICMP:%.*]] = icmp ne ptr [[P1:%.*]], null, !nosanitize |
166 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 167 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
167 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize | 168 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize |
168 // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P1]]) | 169 // CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P1]]) |
169 [a objc_method: p]; | 170 [a objc_method: p]; |
170 | 171 |
171 // CHECK: [[ICMP:%.*]] = icmp ne i32* [[P2:%.*]], null, !nosanitize | 172 // CHECK: [[ICMP:%.*]] = icmp ne ptr [[P2:%.*]], null, !nosanitize |
172 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize | 173 // CHECK-NEXT: br i1 [[ICMP]], {{.*}}, !nosanitize |
173 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize | 174 // CHECK: call void @__ubsan_handle_nullability_arg{{.*}} !nosanitize |
174 // CHECK: call i32* {{.*}} @objc_msgSend to i32* {{.*}}({{.*}}, i32* [[P2]]) | 175 // CHECK: call ptr @objc_msgSend({{.*}}, ptr [[P2]]) |
175 [A objc_clsmethod: p]; | 176 [A objc_clsmethod: p]; |
176 } | 177 } |
177 | 178 |
178 void dont_crash(int *_Nonnull p, ...) {} | 179 void dont_crash(int *_Nonnull p, ...) {} |
179 | 180 |