1 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s 2 3 typedef unsigned long size_t; 4 5 struct Foo { 6 int t[10]; 7 }; 8 9 #define PS(N) __attribute__((pass_object_size(N))) 10 11 int gi = 0; 12 13 // CHECK-LABEL: define i32 @ObjectSize0(i8* %{{.*}}, i64) 14 int ObjectSize0(void *const p PS(0)) { 15 // CHECK-NOT: @llvm.objectsize 16 return __builtin_object_size(p, 0); 17 } 18 19 // CHECK-LABEL: define i32 @ObjectSize1(i8* %{{.*}}, i64) 20 int ObjectSize1(void *const p PS(1)) { 21 // CHECK-NOT: @llvm.objectsize 22 return __builtin_object_size(p, 1); 23 } 24 25 // CHECK-LABEL: define i32 @ObjectSize2(i8* %{{.*}}, i64) 26 int ObjectSize2(void *const p PS(2)) { 27 // CHECK-NOT: @llvm.objectsize 28 return __builtin_object_size(p, 2); 29 } 30 31 // CHECK-LABEL: define i32 @ObjectSize3(i8* %{{.*}}, i64) 32 int ObjectSize3(void *const p PS(3)) { 33 // CHECK-NOT: @llvm.objectsize 34 return __builtin_object_size(p, 3); 35 } 36 37 // CHECK-LABEL: define void @test1 38 void test1() { 39 struct Foo t[10]; 40 41 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360) 42 gi = ObjectSize0(&t[1]); 43 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360) 44 gi = ObjectSize1(&t[1]); 45 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360) 46 gi = ObjectSize2(&t[1]); 47 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360) 48 gi = ObjectSize3(&t[1]); 49 50 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356) 51 gi = ObjectSize0(&t[1].t[1]); 52 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36) 53 gi = ObjectSize1(&t[1].t[1]); 54 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356) 55 gi = ObjectSize2(&t[1].t[1]); 56 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36) 57 gi = ObjectSize3(&t[1].t[1]); 58 } 59 60 // CHECK-LABEL: define void @test2 61 void test2(struct Foo *t) { 62 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36) 63 gi = ObjectSize1(&t->t[1]); 64 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36) 65 gi = ObjectSize3(&t->t[1]); 66 } 67 68 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv 69 int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) { 70 // CHECK: @llvm.objectsize 71 return __builtin_object_size(p, 0); 72 } 73 74 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv 75 int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) { 76 // CHECK: @llvm.objectsize 77 return __builtin_object_size(p, 1); 78 } 79 80 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv 81 int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) { 82 // CHECK: @llvm.objectsize 83 return __builtin_object_size(p, 2); 84 } 85 86 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv 87 int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) { 88 // CHECK-NOT: @llvm.objectsize 89 return __builtin_object_size(p, 3); 90 } 91 92 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv 93 // CHECK-NOT: @llvm.objectsize 94 int NoViableOverloadObjectSize0(void *const p PS(0)) 95 __attribute__((overloadable)) { 96 return __builtin_object_size(p, 0); 97 } 98 99 int NoViableOverloadObjectSize1(void *const p PS(1)) 100 __attribute__((overloadable)) { 101 return __builtin_object_size(p, 1); 102 } 103 104 int NoViableOverloadObjectSize2(void *const p PS(2)) 105 __attribute__((overloadable)) { 106 return __builtin_object_size(p, 2); 107 } 108 109 int NoViableOverloadObjectSize3(void *const p PS(3)) 110 __attribute__((overloadable)) { 111 return __builtin_object_size(p, 3); 112 } 113 114 const static int SHOULDNT_BE_CALLED = -100; 115 int NoViableOverloadObjectSize0(void *const p PS(0)) 116 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 117 return SHOULDNT_BE_CALLED; 118 } 119 120 int NoViableOverloadObjectSize1(void *const p PS(1)) 121 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 122 return SHOULDNT_BE_CALLED; 123 } 124 125 int NoViableOverloadObjectSize2(void *const p PS(2)) 126 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 127 return SHOULDNT_BE_CALLED; 128 } 129 130 int NoViableOverloadObjectSize3(void *const p PS(3)) 131 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 132 return SHOULDNT_BE_CALLED; 133 } 134 135 // CHECK-LABEL: define void @test3 136 void test3() { 137 struct Foo t[10]; 138 139 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360) 140 gi = NoViableOverloadObjectSize0(&t[1]); 141 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360) 142 gi = NoViableOverloadObjectSize1(&t[1]); 143 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360) 144 gi = NoViableOverloadObjectSize2(&t[1]); 145 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360) 146 gi = NoViableOverloadObjectSize3(&t[1]); 147 148 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356) 149 gi = NoViableOverloadObjectSize0(&t[1].t[1]); 150 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36) 151 gi = NoViableOverloadObjectSize1(&t[1].t[1]); 152 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356) 153 gi = NoViableOverloadObjectSize2(&t[1].t[1]); 154 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36) 155 gi = NoViableOverloadObjectSize3(&t[1].t[1]); 156 } 157 158 // CHECK-LABEL: define void @test4 159 void test4(struct Foo *t) { 160 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}}) 161 gi = NoViableOverloadObjectSize0(&t[1]); 162 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}}) 163 gi = NoViableOverloadObjectSize1(&t[1]); 164 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}}) 165 gi = NoViableOverloadObjectSize2(&t[1]); 166 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0) 167 gi = NoViableOverloadObjectSize3(&t[1]); 168 169 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}}) 170 gi = NoViableOverloadObjectSize0(&t[1].t[1]); 171 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36) 172 gi = NoViableOverloadObjectSize1(&t[1].t[1]); 173 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}}) 174 gi = NoViableOverloadObjectSize2(&t[1].t[1]); 175 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36) 176 gi = NoViableOverloadObjectSize3(&t[1].t[1]); 177 } 178 179 void test5() { 180 struct Foo t[10]; 181 182 int (*f)(void *) = &NoViableOverloadObjectSize0; 183 gi = f(&t[1]); 184 } 185 186 // CHECK-LABEL: define i32 @IndirectObjectSize0 187 int IndirectObjectSize0(void *const p PS(0)) { 188 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}}) 189 // CHECK-NOT: @llvm.objectsize 190 return ObjectSize0(p); 191 } 192 193 // CHECK-LABEL: define i32 @IndirectObjectSize1 194 int IndirectObjectSize1(void *const p PS(1)) { 195 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}}) 196 // CHECK-NOT: @llvm.objectsize 197 return ObjectSize1(p); 198 } 199 200 // CHECK-LABEL: define i32 @IndirectObjectSize2 201 int IndirectObjectSize2(void *const p PS(2)) { 202 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}}) 203 // CHECK-NOT: @llvm.objectsize 204 return ObjectSize2(p); 205 } 206 207 // CHECK-LABEL: define i32 @IndirectObjectSize3 208 int IndirectObjectSize3(void *const p PS(3)) { 209 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}}) 210 // CHECK-NOT: @llvm.objectsize 211 return ObjectSize3(p); 212 } 213 214 int Overload0(void *, size_t, void *, size_t); 215 int OverloadNoSize(void *, void *); 216 217 int OverloadedObjectSize(void *const p PS(0), 218 void *const c PS(0)) 219 __attribute__((overloadable)) __asm__("Overload0"); 220 221 int OverloadedObjectSize(void *const p, void *const c) 222 __attribute__((overloadable)) __asm__("OverloadNoSize"); 223 224 // CHECK-LABEL: define void @test6 225 void test6() { 226 int known[10], *opaque; 227 228 // CHECK: call i32 @"\01Overload0" 229 gi = OverloadedObjectSize(&known[0], &known[0]); 230 231 // CHECK: call i32 @"\01Overload0" 232 gi = OverloadedObjectSize(&known[0], opaque); 233 234 // CHECK: call i32 @"\01Overload0" 235 gi = OverloadedObjectSize(opaque, &known[0]); 236 237 // CHECK: call i32 @"\01Overload0" 238 gi = OverloadedObjectSize(opaque, opaque); 239 } 240 241 int Identity(void *p, size_t i) { return i; } 242 243 // CHECK-NOT: define void @AsmObjectSize 244 int AsmObjectSize0(void *const p PS(0)) __asm__("Identity"); 245 246 int AsmObjectSize1(void *const p PS(1)) __asm__("Identity"); 247 248 int AsmObjectSize2(void *const p PS(2)) __asm__("Identity"); 249 250 int AsmObjectSize3(void *const p PS(3)) __asm__("Identity"); 251 252 // CHECK-LABEL: define void @test7 253 void test7() { 254 struct Foo t[10]; 255 256 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 257 gi = AsmObjectSize0(&t[1]); 258 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 259 gi = AsmObjectSize1(&t[1]); 260 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 261 gi = AsmObjectSize2(&t[1]); 262 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 263 gi = AsmObjectSize3(&t[1]); 264 265 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356) 266 gi = AsmObjectSize0(&t[1].t[1]); 267 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 268 gi = AsmObjectSize1(&t[1].t[1]); 269 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356) 270 gi = AsmObjectSize2(&t[1].t[1]); 271 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 272 gi = AsmObjectSize3(&t[1].t[1]); 273 } 274 275 // CHECK-LABEL: define void @test8 276 void test8(struct Foo *t) { 277 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 278 gi = AsmObjectSize1(&t[1].t[1]); 279 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 280 gi = AsmObjectSize3(&t[1].t[1]); 281 } 282 283 void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0)))); 284 void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1)))); 285 void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2)))); 286 void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3)))); 287 288 // CHECK-LABEL: define void @test9 289 void test9(void *const p __attribute__((pass_object_size(0)))) { 290 // CHECK: @llvm.objectsize 291 DifferingObjectSize2(p); 292 293 // CHECK-NOT: @llvm.objectsize 294 DifferingObjectSize0(p); 295 DifferingObjectSize1(p); 296 297 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0) 298 DifferingObjectSize3(p); 299 } 300 301 // CHECK-LABEL: define void @test10 302 void test10(void *const p __attribute__((pass_object_size(1)))) { 303 // CHECK: @llvm.objectsize 304 DifferingObjectSize2(p); 305 // CHECK: @llvm.objectsize 306 DifferingObjectSize0(p); 307 308 // CHECK-NOT: @llvm.objectsize 309 DifferingObjectSize1(p); 310 311 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0) 312 DifferingObjectSize3(p); 313 } 314 315 // CHECK-LABEL: define void @test11 316 void test11(void *const p __attribute__((pass_object_size(2)))) { 317 // CHECK: @llvm.objectsize 318 DifferingObjectSize0(p); 319 // CHECK: @llvm.objectsize 320 DifferingObjectSize1(p); 321 322 // CHECK-NOT: @llvm.objectsize 323 DifferingObjectSize2(p); 324 325 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0) 326 DifferingObjectSize3(p); 327 } 328 329 // CHECK-LABEL: define void @test12 330 void test12(void *const p __attribute__((pass_object_size(3)))) { 331 // CHECK: @llvm.objectsize 332 DifferingObjectSize0(p); 333 // CHECK: @llvm.objectsize 334 DifferingObjectSize1(p); 335 336 // CHECK-NOT: @llvm.objectsize 337 DifferingObjectSize2(p); 338 DifferingObjectSize3(p); 339 } 340 341 // CHECK-LABEL: define void @test13 342 void test13() { 343 // Ensuring that we don't lower objectsize if the expression has side-effects 344 char c[10]; 345 char *p = c; 346 347 // CHECK: @llvm.objectsize 348 ObjectSize0(p); 349 350 // CHECK-NOT: @llvm.objectsize 351 ObjectSize0(++p); 352 ObjectSize0(p++); 353 } 354