494 lines · c
1// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s2 3typedef unsigned long size_t;4 5struct Foo {6 int t[10];7};8 9#define PS(N) __attribute__((pass_object_size(N)))10#define PDS(N) __attribute__((pass_dynamic_object_size(N)))11 12int gi = 0;13 14// CHECK-LABEL: define{{.*}} i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef %0)15int ObjectSize0(void *const p PS(0)) {16 // CHECK-NOT: @llvm.objectsize17 return __builtin_object_size(p, 0);18}19 20// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize0(ptr noundef %{{.*}}, i64 noundef %0)21int DynamicObjectSize0(void *const p PDS(0)) {22 // CHECK-NOT: @llvm.objectsize23 return __builtin_dynamic_object_size(p, 0);24}25 26// CHECK-LABEL: define{{.*}} i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef %0)27int ObjectSize1(void *const p PS(1)) {28 // CHECK-NOT: @llvm.objectsize29 return __builtin_object_size(p, 1);30}31 32// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize1(ptr noundef %{{.*}}, i64 noundef %0)33int DynamicObjectSize1(void *const p PDS(1)) {34 // CHECK-NOT: @llvm.objectsize35 return __builtin_dynamic_object_size(p, 1);36}37 38// CHECK-LABEL: define{{.*}} i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef %0)39int ObjectSize2(void *const p PS(2)) {40 // CHECK-NOT: @llvm.objectsize41 return __builtin_object_size(p, 2);42}43 44// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize2(ptr noundef %{{.*}}, i64 noundef %0)45int DynamicObjectSize2(void *const p PDS(2)) {46 // CHECK-NOT: @llvm.objectsize47 return __builtin_object_size(p, 2);48}49 50// CHECK-LABEL: define{{.*}} i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef %0)51int ObjectSize3(void *const p PS(3)) {52 // CHECK-NOT: @llvm.objectsize53 return __builtin_object_size(p, 3);54}55 56// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize3(ptr noundef %{{.*}}, i64 noundef %0)57int DynamicObjectSize3(void *const p PDS(3)) {58 // CHECK-NOT: @llvm.objectsize59 return __builtin_object_size(p, 3);60}61 62void *malloc(unsigned long) __attribute__((alloc_size(1)));63 64// CHECK-LABEL: define{{.*}} void @test165void test1(unsigned long sz) {66 struct Foo t[10];67 68 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 360)69 gi = ObjectSize0(&t[1]);70 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 360)71 gi = ObjectSize1(&t[1]);72 // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 360)73 gi = ObjectSize2(&t[1]);74 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 360)75 gi = ObjectSize3(&t[1]);76 77 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef 356)78 gi = ObjectSize0(&t[1].t[1]);79 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef 36)80 gi = ObjectSize1(&t[1].t[1]);81 // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef 356)82 gi = ObjectSize2(&t[1].t[1]);83 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 36)84 gi = ObjectSize3(&t[1].t[1]);85 86 char *ptr = (char *)malloc(sz);87 88 // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0({{.*}}, i1 false, i1 true, i1 true)89 // CHECK: call i32 @DynamicObjectSize0(ptr noundef %{{.*}}, i64 noundef [[REG]])90 gi = DynamicObjectSize0(ptr);91 92 // CHECK: [[WITH_OFFSET:%.*]] = getelementptr93 // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0(ptr [[WITH_OFFSET]], i1 false, i1 true, i1 true)94 // CHECK: call i32 @DynamicObjectSize0(ptr noundef {{.*}}, i64 noundef [[REG]])95 gi = DynamicObjectSize0(ptr+10);96 97 // CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0({{.*}}, i1 true, i1 true, i1 true)98 // CHECK: call i32 @DynamicObjectSize2(ptr noundef {{.*}}, i64 noundef [[REG]])99 gi = DynamicObjectSize2(ptr);100}101 102// CHECK-LABEL: define{{.*}} void @test2103void test2(struct Foo *t) {104 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize105 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef [[VAR]])106 gi = ObjectSize1(&t->t[1]);107 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef 36)108 gi = ObjectSize3(&t->t[1]);109}110 111// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv112int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {113 // CHECK: @llvm.objectsize114 return __builtin_object_size(p, 0);115}116 117// CHECK-LABEL: define{{.*}} i32 @_Z34NoViableOverloadDynamicObjectSize0Pv118int NoViableOverloadDynamicObjectSize0(void *const p)119 __attribute__((overloadable)) {120 // CHECK: @llvm.objectsize121 return __builtin_object_size(p, 0);122}123 124// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize1Pv125int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {126 // CHECK: @llvm.objectsize127 return __builtin_object_size(p, 1);128}129 130// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize2Pv131int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {132 // CHECK: @llvm.objectsize133 return __builtin_object_size(p, 2);134}135 136// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize3Pv137int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {138 // CHECK-NOT: @llvm.objectsize139 return __builtin_object_size(p, 3);140}141 142// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv143// CHECK-NOT: @llvm.objectsize144int NoViableOverloadObjectSize0(void *const p PS(0))145 __attribute__((overloadable)) {146 return __builtin_object_size(p, 0);147}148 149int NoViableOverloadDynamicObjectSize0(void *const p PDS(0))150 __attribute__((overloadable)) {151 return __builtin_dynamic_object_size(p, 0);152}153 154int NoViableOverloadObjectSize1(void *const p PS(1))155 __attribute__((overloadable)) {156 return __builtin_object_size(p, 1);157}158 159int NoViableOverloadObjectSize2(void *const p PS(2))160 __attribute__((overloadable)) {161 return __builtin_object_size(p, 2);162}163 164int NoViableOverloadObjectSize3(void *const p PS(3))165 __attribute__((overloadable)) {166 return __builtin_object_size(p, 3);167}168 169const static int SHOULDNT_BE_CALLED = -100;170int NoViableOverloadObjectSize0(void *const p PS(0))171 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {172 return SHOULDNT_BE_CALLED;173}174 175int NoViableOverloadObjectSize1(void *const p PS(1))176 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {177 return SHOULDNT_BE_CALLED;178}179 180int NoViableOverloadObjectSize2(void *const p PS(2))181 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {182 return SHOULDNT_BE_CALLED;183}184 185int NoViableOverloadObjectSize3(void *const p PS(3))186 __attribute__((overloadable, enable_if(p == 0, "never selected"))) {187 return SHOULDNT_BE_CALLED;188}189 190// CHECK-LABEL: define{{.*}} void @test3191void test3(void) {192 struct Foo t[10];193 194 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef 360)195 gi = NoViableOverloadObjectSize0(&t[1]);196 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef 360)197 gi = NoViableOverloadObjectSize1(&t[1]);198 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef 360)199 gi = NoViableOverloadObjectSize2(&t[1]);200 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 360)201 gi = NoViableOverloadObjectSize3(&t[1]);202 203 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef 356)204 gi = NoViableOverloadObjectSize0(&t[1].t[1]);205 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef 36)206 gi = NoViableOverloadObjectSize1(&t[1].t[1]);207 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef 356)208 gi = NoViableOverloadObjectSize2(&t[1].t[1]);209 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 36)210 gi = NoViableOverloadObjectSize3(&t[1].t[1]);211 212 // CHECK: call i32 @_Z34NoViableOverloadDynamicObjectSize0PvU25pass_dynamic_object_size0(ptr noundef %{{.*}}, i64 noundef 360)213 gi = NoViableOverloadDynamicObjectSize0(&t[1]);214}215 216// CHECK-LABEL: define{{.*}} void @test4217void test4(struct Foo *t) {218 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef %{{.*}})219 gi = NoViableOverloadObjectSize0(&t[1]);220 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef %{{.*}})221 gi = NoViableOverloadObjectSize1(&t[1]);222 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef %{{.*}})223 gi = NoViableOverloadObjectSize2(&t[1]);224 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 0)225 gi = NoViableOverloadObjectSize3(&t[1]);226 227 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(ptr noundef %{{.*}}, i64 noundef %{{.*}})228 gi = NoViableOverloadObjectSize0(&t[1].t[1]);229 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize230 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(ptr noundef %{{.*}}, i64 noundef [[VAR]])231 gi = NoViableOverloadObjectSize1(&t[1].t[1]);232 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(ptr noundef %{{.*}}, i64 noundef %{{.*}})233 gi = NoViableOverloadObjectSize2(&t[1].t[1]);234 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(ptr noundef %{{.*}}, i64 noundef 36)235 gi = NoViableOverloadObjectSize3(&t[1].t[1]);236}237 238void test5(void) {239 struct Foo t[10];240 241 int (*f)(void *) = &NoViableOverloadObjectSize0;242 gi = f(&t[1]);243 244 int (*g)(void *) = &NoViableOverloadDynamicObjectSize0;245 gi = g(&t[1]);246}247 248// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize0249int IndirectObjectSize0(void *const p PS(0)) {250 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef %{{.*}})251 // CHECK-NOT: @llvm.objectsize252 return ObjectSize0(p);253}254 255// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize1256int IndirectObjectSize1(void *const p PS(1)) {257 // CHECK: call i32 @ObjectSize1(ptr noundef %{{.*}}, i64 noundef %{{.*}})258 // CHECK-NOT: @llvm.objectsize259 return ObjectSize1(p);260}261 262// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize2263int IndirectObjectSize2(void *const p PS(2)) {264 // CHECK: call i32 @ObjectSize2(ptr noundef %{{.*}}, i64 noundef %{{.*}})265 // CHECK-NOT: @llvm.objectsize266 return ObjectSize2(p);267}268 269// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize3270int IndirectObjectSize3(void *const p PS(3)) {271 // CHECK: call i32 @ObjectSize3(ptr noundef %{{.*}}, i64 noundef %{{.*}})272 // CHECK-NOT: @llvm.objectsize273 return ObjectSize3(p);274}275 276int IndirectDynamicObjectSize0(void *const p PDS(0)) {277 // CHECK: call i32 @ObjectSize0(ptr noundef %{{.*}}, i64 noundef %{{.*}})278 // CHECK-NOT: @llvm.objectsize279 return ObjectSize0(p);280}281 282int Overload0(void *, size_t, void *, size_t);283int OverloadNoSize(void *, void *);284 285int OverloadedObjectSize(void *const p PS(0),286 void *const c PS(0))287 __attribute__((overloadable)) __asm__("Overload0");288 289int OverloadedObjectSize(void *const p, void *const c)290 __attribute__((overloadable)) __asm__("OverloadNoSize");291 292// CHECK-LABEL: define{{.*}} void @test6293void test6(void) {294 int known[10], *opaque;295 296 // CHECK: call i32 @"\01Overload0"297 gi = OverloadedObjectSize(&known[0], &known[0]);298 299 // CHECK: call i32 @"\01Overload0"300 gi = OverloadedObjectSize(&known[0], opaque);301 302 // CHECK: call i32 @"\01Overload0"303 gi = OverloadedObjectSize(opaque, &known[0]);304 305 // CHECK: call i32 @"\01Overload0"306 gi = OverloadedObjectSize(opaque, opaque);307}308 309int Identity(void *p, size_t i) { return i; }310 311// CHECK-NOT: define{{.*}} void @AsmObjectSize312int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");313 314int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");315 316int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");317 318int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");319 320// CHECK-LABEL: define{{.*}} void @test7321void test7(void) {322 struct Foo t[10];323 324 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)325 gi = AsmObjectSize0(&t[1]);326 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)327 gi = AsmObjectSize1(&t[1]);328 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)329 gi = AsmObjectSize2(&t[1]);330 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 360)331 gi = AsmObjectSize3(&t[1]);332 333 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 356)334 gi = AsmObjectSize0(&t[1].t[1]);335 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 36)336 gi = AsmObjectSize1(&t[1].t[1]);337 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 356)338 gi = AsmObjectSize2(&t[1].t[1]);339 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 36)340 gi = AsmObjectSize3(&t[1].t[1]);341}342 343// CHECK-LABEL: define{{.*}} void @test8344void test8(struct Foo *t) {345 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize346 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef [[VAR]])347 gi = AsmObjectSize1(&t[1].t[1]);348 // CHECK: call i32 @"\01Identity"(ptr noundef %{{.*}}, i64 noundef 36)349 gi = AsmObjectSize3(&t[1].t[1]);350}351 352void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));353void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));354void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));355void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));356 357// CHECK-LABEL: define{{.*}} void @test9358void test9(void *const p __attribute__((pass_object_size(0)))) {359 // CHECK: @llvm.objectsize360 DifferingObjectSize2(p);361 362 // CHECK-NOT: @llvm.objectsize363 DifferingObjectSize0(p);364 DifferingObjectSize1(p);365 366 // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)367 DifferingObjectSize3(p);368}369 370// CHECK-LABEL: define{{.*}} void @test10371void test10(void *const p __attribute__((pass_object_size(1)))) {372 // CHECK: @llvm.objectsize373 DifferingObjectSize2(p);374 // CHECK: @llvm.objectsize375 DifferingObjectSize0(p);376 377 // CHECK-NOT: @llvm.objectsize378 DifferingObjectSize1(p);379 380 // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)381 DifferingObjectSize3(p);382}383 384// CHECK-LABEL: define{{.*}} void @test11385void test11(void *const p __attribute__((pass_object_size(2)))) {386 // CHECK: @llvm.objectsize387 DifferingObjectSize0(p);388 // CHECK: @llvm.objectsize389 DifferingObjectSize1(p);390 391 // CHECK-NOT: @llvm.objectsize392 DifferingObjectSize2(p);393 394 // CHECK: call void @DifferingObjectSize3(ptr noundef %{{.*}}, i64 noundef 0)395 DifferingObjectSize3(p);396}397 398// CHECK-LABEL: define{{.*}} void @test12399void test12(void *const p __attribute__((pass_object_size(3)))) {400 // CHECK: @llvm.objectsize401 DifferingObjectSize0(p);402 // CHECK: @llvm.objectsize403 DifferingObjectSize1(p);404 405 // CHECK-NOT: @llvm.objectsize406 DifferingObjectSize2(p);407 DifferingObjectSize3(p);408}409 410// CHECK-LABEL: define{{.*}} void @test13411void test13(void) {412 char c[10];413 unsigned i = 0;414 char *p = c;415 416 // CHECK: @llvm.objectsize417 ObjectSize0(p);418 419 // Allow side-effects, since they always need to happen anyway. Just make sure420 // we don't perform them twice.421 // CHECK: = add422 // CHECK-NOT: = add423 // CHECK: @llvm.objectsize424 // CHECK: call i32 @ObjectSize0425 ObjectSize0(p + ++i);426 427 // CHECK: = add428 // CHECK: @llvm.objectsize429 // CHECK-NOT: = add430 // CHECK: call i32 @ObjectSize0431 ObjectSize0(p + i++);432}433 434// There was a bug where variadic functions with pass_object_size would cause435// problems in the form of failed assertions.436void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}437 438// CHECK-LABEL: define{{.*}} void @test14439void test14(char *c) {440 // CHECK: @llvm.objectsize441 // CHECK: call void (ptr, i64, ...) @my_sprintf442 my_sprintf(c);443 444 // CHECK: @llvm.objectsize445 // CHECK: call void (ptr, i64, ...) @my_sprintf446 my_sprintf(c, 1, 2, 3);447}448 449void pass_size_unsigned(unsigned *const PS(0));450 451// Bug: we weren't lowering to the proper @llvm.objectsize for pointers that452// don't turn into ptr s, which caused crashes.453// CHECK-LABEL: define{{.*}} void @test15454void test15(unsigned *I) {455 // CHECK: @llvm.objectsize.i64.p0456 // CHECK: call void @pass_size_unsigned457 pass_size_unsigned(I);458}459 460void pass_size_as1(__attribute__((address_space(1))) void *const PS(0));461 462void pass_size_unsigned_as1(463 __attribute__((address_space(1))) unsigned *const PS(0));464 465// CHECK-LABEL: define{{.*}} void @test16466void test16(__attribute__((address_space(1))) unsigned *I) {467 // CHECK: call i64 @llvm.objectsize.i64.p1468 // CHECK: call void @pass_size_as1469 pass_size_as1(I);470 // CHECK: call i64 @llvm.objectsize.i64.p1471 // CHECK: call void @pass_size_unsigned_as1472 pass_size_unsigned_as1(I);473}474 475// This used to cause assertion failures, since we'd try to emit the statement476// expression (and definitions for `a`) twice.477// CHECK-LABEL: define{{.*}} void @test17478void test17(char *C) {479 // Check for 65535 to see if we're emitting this pointer twice.480 // CHECK: 65535481 // CHECK-NOT: 65535482 // CHECK: @llvm.objectsize.i64.p0(ptr [[PTR:%[^,]+]],483 // CHECK-NOT: 65535484 // CHECK: call i32 @ObjectSize0(ptr noundef [[PTR]]485 ObjectSize0(C + ({ int a = 65535; a; }));486}487 488// CHECK-LABEL: define{{.*}} void @test18489void test18(char *const p PDS(0)) {490 // CHECK-NOT: llvm.objectsize491 gi = __builtin_dynamic_object_size(p, 0);492 gi = __builtin_object_size(p, 0);493}494