1 // RUN: %clang_cc1 -no-enable-noundef-analysis -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s 2 // RUN: %clang_cc1 -no-enable-noundef-analysis -DDYNAMIC -triple x86_64-apple-darwin -emit-llvm %s -o - 2>&1 | FileCheck %s 3 4 #ifndef DYNAMIC 5 #define OBJECT_SIZE_BUILTIN __builtin_object_size 6 #else 7 #define OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size 8 #endif 9 10 #define strcpy(dest, src) \ 11 ((OBJECT_SIZE_BUILTIN(dest, 0) != -1ULL) \ 12 ? __builtin___strcpy_chk (dest, src, OBJECT_SIZE_BUILTIN(dest, 1)) \ 13 : __inline_strcpy_chk(dest, src)) 14 15 static char *__inline_strcpy_chk (char *dest, const char *src) { 16 return __builtin___strcpy_chk(dest, src, OBJECT_SIZE_BUILTIN(dest, 1)); 17 } 18 19 char gbuf[63]; 20 char *gp; 21 int gi, gj; 22 23 // CHECK-LABEL: define{{.*}} void @test1 24 void test1(void) { 25 // CHECK: = call ptr @__strcpy_chk(ptr getelementptr inbounds ([63 x i8], ptr @gbuf, i64 0, i64 4), ptr @.str, i64 59) 26 strcpy(&gbuf[4], "Hi there"); 27 } 28 29 // CHECK-LABEL: define{{.*}} void @test2 30 void test2(void) { 31 // CHECK: = call ptr @__strcpy_chk(ptr @gbuf, ptr @.str, i64 63) 32 strcpy(gbuf, "Hi there"); 33 } 34 35 // CHECK-LABEL: define{{.*}} void @test3 36 void test3(void) { 37 // CHECK: = call ptr @__strcpy_chk(ptr getelementptr inbounds ([63 x i8], ptr @gbuf, i64 0, i64 100), ptr @.str, i64 0) 38 strcpy(&gbuf[100], "Hi there"); 39 } 40 41 // CHECK-LABEL: define{{.*}} void @test4 42 void test4(void) { 43 // CHECK: = call ptr @__strcpy_chk(ptr getelementptr inbounds ([63 x i8], ptr @gbuf, i64 0, i64 -1), ptr @.str, i64 0) 44 strcpy((char*)(void*)&gbuf[-1], "Hi there"); 45 } 46 47 // CHECK-LABEL: define{{.*}} void @test5 48 void test5(void) { 49 // CHECK: = load ptr, ptr @gp 50 // CHECK-NEXT:= call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 51 strcpy(gp, "Hi there"); 52 } 53 54 // CHECK-LABEL: define{{.*}} void @test6 55 void test6(void) { 56 char buf[57]; 57 58 // CHECK: = call ptr @__strcpy_chk(ptr %{{.*}}, ptr @.str, i64 53) 59 strcpy(&buf[4], "Hi there"); 60 } 61 62 // CHECK-LABEL: define{{.*}} void @test7 63 void test7(void) { 64 int i; 65 // Ensure we only evaluate the side-effect once. 66 // CHECK: = add 67 // CHECK-NOT: = add 68 // CHECK: = call ptr @__strcpy_chk(ptr @gbuf, ptr @.str, i64 63) 69 strcpy((++i, gbuf), "Hi there"); 70 } 71 72 // CHECK-LABEL: define{{.*}} void @test8 73 void test8(void) { 74 char *buf[50]; 75 // CHECK-NOT: __strcpy_chk 76 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 77 strcpy(buf[++gi], "Hi there"); 78 } 79 80 // CHECK-LABEL: define{{.*}} void @test9 81 void test9(void) { 82 // CHECK-NOT: __strcpy_chk 83 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 84 strcpy((char *)((++gi) + gj), "Hi there"); 85 } 86 87 // CHECK-LABEL: define{{.*}} void @test10 88 char **p; 89 void test10(void) { 90 // CHECK-NOT: __strcpy_chk 91 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 92 strcpy(*(++p), "Hi there"); 93 } 94 95 // CHECK-LABEL: define{{.*}} void @test11 96 void test11(void) { 97 // CHECK-NOT: __strcpy_chk 98 // CHECK: = call ptr @__inline_strcpy_chk(ptr @gbuf, ptr @.str) 99 strcpy(gp = gbuf, "Hi there"); 100 } 101 102 // CHECK-LABEL: define{{.*}} void @test12 103 void test12(void) { 104 // CHECK-NOT: __strcpy_chk 105 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 106 strcpy(++gp, "Hi there"); 107 } 108 109 // CHECK-LABEL: define{{.*}} void @test13 110 void test13(void) { 111 // CHECK-NOT: __strcpy_chk 112 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 113 strcpy(gp++, "Hi there"); 114 } 115 116 // CHECK-LABEL: define{{.*}} void @test14 117 void test14(void) { 118 // CHECK-NOT: __strcpy_chk 119 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 120 strcpy(--gp, "Hi there"); 121 } 122 123 // CHECK-LABEL: define{{.*}} void @test15 124 void test15(void) { 125 // CHECK-NOT: __strcpy_chk 126 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{..*}}, ptr @.str) 127 strcpy(gp--, "Hi there"); 128 } 129 130 // CHECK-LABEL: define{{.*}} void @test16 131 void test16(void) { 132 // CHECK-NOT: __strcpy_chk 133 // CHECK: = call ptr @__inline_strcpy_chk(ptr %{{.*}}, ptr @.str) 134 strcpy(gp += 1, "Hi there"); 135 } 136 137 // CHECK-LABEL: @test17 138 void test17(void) { 139 // CHECK: store i32 -1 140 gi = OBJECT_SIZE_BUILTIN(gp++, 0); 141 // CHECK: store i32 -1 142 gi = OBJECT_SIZE_BUILTIN(gp++, 1); 143 // CHECK: store i32 0 144 gi = OBJECT_SIZE_BUILTIN(gp++, 2); 145 // CHECK: store i32 0 146 gi = OBJECT_SIZE_BUILTIN(gp++, 3); 147 } 148 149 // CHECK-LABEL: @test18 150 unsigned test18(int cond) { 151 int a[4], b[4]; 152 // CHECK: phi ptr 153 // CHECK: call i64 @llvm.objectsize.i64 154 return OBJECT_SIZE_BUILTIN(cond ? a : b, 0); 155 } 156 157 // CHECK-LABEL: @test19 158 void test19(void) { 159 struct { 160 int a, b; 161 } foo; 162 163 // CHECK: store i32 8 164 gi = OBJECT_SIZE_BUILTIN(&foo.a, 0); 165 // CHECK: store i32 4 166 gi = OBJECT_SIZE_BUILTIN(&foo.a, 1); 167 // CHECK: store i32 8 168 gi = OBJECT_SIZE_BUILTIN(&foo.a, 2); 169 // CHECK: store i32 4 170 gi = OBJECT_SIZE_BUILTIN(&foo.a, 3); 171 172 // CHECK: store i32 4 173 gi = OBJECT_SIZE_BUILTIN(&foo.b, 0); 174 // CHECK: store i32 4 175 gi = OBJECT_SIZE_BUILTIN(&foo.b, 1); 176 // CHECK: store i32 4 177 gi = OBJECT_SIZE_BUILTIN(&foo.b, 2); 178 // CHECK: store i32 4 179 gi = OBJECT_SIZE_BUILTIN(&foo.b, 3); 180 } 181 182 // CHECK-LABEL: @test20 183 void test20(void) { 184 struct { int t[10]; } t[10]; 185 186 // CHECK: store i32 380 187 gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 0); 188 // CHECK: store i32 20 189 gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 1); 190 // CHECK: store i32 380 191 gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 2); 192 // CHECK: store i32 20 193 gi = OBJECT_SIZE_BUILTIN(&t[0].t[5], 3); 194 } 195 196 // CHECK-LABEL: @test21 197 void test21(void) { 198 struct { int t; } t; 199 200 // CHECK: store i32 0 201 gi = OBJECT_SIZE_BUILTIN(&t + 1, 0); 202 // CHECK: store i32 0 203 gi = OBJECT_SIZE_BUILTIN(&t + 1, 1); 204 // CHECK: store i32 0 205 gi = OBJECT_SIZE_BUILTIN(&t + 1, 2); 206 // CHECK: store i32 0 207 gi = OBJECT_SIZE_BUILTIN(&t + 1, 3); 208 209 // CHECK: store i32 0 210 gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 0); 211 // CHECK: store i32 0 212 gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 1); 213 // CHECK: store i32 0 214 gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 2); 215 // CHECK: store i32 0 216 gi = OBJECT_SIZE_BUILTIN(&t.t + 1, 3); 217 } 218 219 // CHECK-LABEL: @test22 220 void test22(void) { 221 struct { int t[10]; } t[10]; 222 223 // CHECK: store i32 0 224 gi = OBJECT_SIZE_BUILTIN(&t[10], 0); 225 // CHECK: store i32 0 226 gi = OBJECT_SIZE_BUILTIN(&t[10], 1); 227 // CHECK: store i32 0 228 gi = OBJECT_SIZE_BUILTIN(&t[10], 2); 229 // CHECK: store i32 0 230 gi = OBJECT_SIZE_BUILTIN(&t[10], 3); 231 232 // CHECK: store i32 0 233 gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 0); 234 // CHECK: store i32 0 235 gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 1); 236 // CHECK: store i32 0 237 gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 2); 238 // CHECK: store i32 0 239 gi = OBJECT_SIZE_BUILTIN(&t[9].t[10], 3); 240 241 // CHECK: store i32 0 242 gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 0); 243 // CHECK: store i32 0 244 gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 1); 245 // CHECK: store i32 0 246 gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 2); 247 // CHECK: store i32 0 248 gi = OBJECT_SIZE_BUILTIN((char*)&t[0] + sizeof(t), 3); 249 250 // CHECK: store i32 0 251 gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0); 252 // CHECK: store i32 0 253 gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1); 254 // CHECK: store i32 0 255 gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2); 256 // CHECK: store i32 0 257 gi = OBJECT_SIZE_BUILTIN((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3); 258 } 259 260 struct Test23Ty { int a; int t[10]; }; 261 262 // CHECK-LABEL: @test23 263 void test23(struct Test23Ty *p) { 264 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 265 gi = OBJECT_SIZE_BUILTIN(p, 0); 266 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 267 gi = OBJECT_SIZE_BUILTIN(p, 1); 268 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 269 gi = OBJECT_SIZE_BUILTIN(p, 2); 270 // Note: this is currently fixed at 0 because LLVM doesn't have sufficient 271 // data to correctly handle type=3 272 // CHECK: store i32 0 273 gi = OBJECT_SIZE_BUILTIN(p, 3); 274 275 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 276 gi = OBJECT_SIZE_BUILTIN(&p->a, 0); 277 // CHECK: store i32 4 278 gi = OBJECT_SIZE_BUILTIN(&p->a, 1); 279 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 280 gi = OBJECT_SIZE_BUILTIN(&p->a, 2); 281 // CHECK: store i32 4 282 gi = OBJECT_SIZE_BUILTIN(&p->a, 3); 283 284 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 285 gi = OBJECT_SIZE_BUILTIN(&p->t[5], 0); 286 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 287 gi = OBJECT_SIZE_BUILTIN(&p->t[5], 1); 288 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 289 gi = OBJECT_SIZE_BUILTIN(&p->t[5], 2); 290 // CHECK: store i32 20 291 gi = OBJECT_SIZE_BUILTIN(&p->t[5], 3); 292 } 293 294 // PR24493 -- ICE if OBJECT_SIZE_BUILTIN called with NULL and (Type & 1) != 0 295 // CHECK-LABEL: @test24 296 void test24(void) { 297 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 298 gi = OBJECT_SIZE_BUILTIN((void*)0, 0); 299 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 300 gi = OBJECT_SIZE_BUILTIN((void*)0, 1); 301 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 302 gi = OBJECT_SIZE_BUILTIN((void*)0, 2); 303 // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. 304 // Hopefully will be lowered properly in the future. 305 // CHECK: store i32 0 306 gi = OBJECT_SIZE_BUILTIN((void*)0, 3); 307 } 308 309 // CHECK-LABEL: @test25 310 void test25(void) { 311 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 312 gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 0); 313 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 314 gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 1); 315 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 316 gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 2); 317 // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. 318 // Hopefully will be lowered properly in the future. 319 // CHECK: store i32 0 320 gi = OBJECT_SIZE_BUILTIN((void*)0x1000, 3); 321 322 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 323 gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 0); 324 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 325 gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 1); 326 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 327 gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 2); 328 // Note: Currently fixed at zero because LLVM can't handle type=3 correctly. 329 // Hopefully will be lowered properly in the future. 330 // CHECK: store i32 0 331 gi = OBJECT_SIZE_BUILTIN((void*)0 + 0x1000, 3); 332 } 333 334 // CHECK-LABEL: @test26 335 void test26(void) { 336 struct { int v[10]; } t[10]; 337 338 // CHECK: store i32 316 339 gi = OBJECT_SIZE_BUILTIN(&t[1].v[11], 0); 340 // CHECK: store i32 312 341 gi = OBJECT_SIZE_BUILTIN(&t[1].v[12], 1); 342 // CHECK: store i32 308 343 gi = OBJECT_SIZE_BUILTIN(&t[1].v[13], 2); 344 // CHECK: store i32 0 345 gi = OBJECT_SIZE_BUILTIN(&t[1].v[14], 3); 346 } 347 348 struct Test27IncompleteTy; 349 350 // CHECK-LABEL: @test27 351 void test27(struct Test27IncompleteTy *t) { 352 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 353 gi = OBJECT_SIZE_BUILTIN(t, 0); 354 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 355 gi = OBJECT_SIZE_BUILTIN(t, 1); 356 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 357 gi = OBJECT_SIZE_BUILTIN(t, 2); 358 // Note: this is currently fixed at 0 because LLVM doesn't have sufficient 359 // data to correctly handle type=3 360 // CHECK: store i32 0 361 gi = OBJECT_SIZE_BUILTIN(t, 3); 362 363 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 364 gi = OBJECT_SIZE_BUILTIN(&test27, 0); 365 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 366 gi = OBJECT_SIZE_BUILTIN(&test27, 1); 367 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1 368 gi = OBJECT_SIZE_BUILTIN(&test27, 2); 369 // Note: this is currently fixed at 0 because LLVM doesn't have sufficient 370 // data to correctly handle type=3 371 // CHECK: store i32 0 372 gi = OBJECT_SIZE_BUILTIN(&test27, 3); 373 } 374 375 // The intent of this test is to ensure that OBJECT_SIZE_BUILTIN treats `&foo` 376 // and `(T*)&foo` identically, when used as the pointer argument. 377 // CHECK-LABEL: @test28 378 void test28(void) { 379 struct { int v[10]; } t[10]; 380 381 #define addCasts(s) ((char*)((short*)(s))) 382 // CHECK: store i32 360 383 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 0); 384 // CHECK: store i32 360 385 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 1); 386 // CHECK: store i32 360 387 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 2); 388 // CHECK: store i32 360 389 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1]), 3); 390 391 // CHECK: store i32 356 392 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 0); 393 // CHECK: store i32 36 394 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 1); 395 // CHECK: store i32 356 396 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 2); 397 // CHECK: store i32 36 398 gi = OBJECT_SIZE_BUILTIN(addCasts(&t[1].v[1]), 3); 399 #undef addCasts 400 } 401 402 struct DynStructVar { 403 char fst[16]; 404 char snd[]; 405 }; 406 407 struct DynStruct0 { 408 char fst[16]; 409 char snd[0]; 410 }; 411 412 struct DynStruct1 { 413 char fst[16]; 414 char snd[1]; 415 }; 416 417 struct StaticStruct { 418 char fst[16]; 419 char snd[2]; 420 }; 421 422 // CHECK-LABEL: @test29 423 void test29(struct DynStructVar *dv, struct DynStruct0 *d0, 424 struct DynStruct1 *d1, struct StaticStruct *ss) { 425 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 426 gi = OBJECT_SIZE_BUILTIN(dv->snd, 0); 427 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 428 gi = OBJECT_SIZE_BUILTIN(dv->snd, 1); 429 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 430 gi = OBJECT_SIZE_BUILTIN(dv->snd, 2); 431 // CHECK: store i32 0 432 gi = OBJECT_SIZE_BUILTIN(dv->snd, 3); 433 434 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 435 gi = OBJECT_SIZE_BUILTIN(d0->snd, 0); 436 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 437 gi = OBJECT_SIZE_BUILTIN(d0->snd, 1); 438 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 439 gi = OBJECT_SIZE_BUILTIN(d0->snd, 2); 440 // CHECK: store i32 0 441 gi = OBJECT_SIZE_BUILTIN(d0->snd, 3); 442 443 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 444 gi = OBJECT_SIZE_BUILTIN(d1->snd, 0); 445 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 446 gi = OBJECT_SIZE_BUILTIN(d1->snd, 1); 447 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 448 gi = OBJECT_SIZE_BUILTIN(d1->snd, 2); 449 // CHECK: store i32 1 450 gi = OBJECT_SIZE_BUILTIN(d1->snd, 3); 451 452 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 453 gi = OBJECT_SIZE_BUILTIN(ss->snd, 0); 454 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 455 gi = OBJECT_SIZE_BUILTIN(ss->snd, 1); 456 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 457 gi = OBJECT_SIZE_BUILTIN(ss->snd, 2); 458 // CHECK: store i32 2 459 gi = OBJECT_SIZE_BUILTIN(ss->snd, 3); 460 } 461 462 // CHECK-LABEL: @test30 463 void test30(void) { 464 struct { struct DynStruct1 fst, snd; } *nested; 465 466 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 467 gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 0); 468 // CHECK: store i32 1 469 gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 1); 470 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 471 gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 2); 472 // CHECK: store i32 1 473 gi = OBJECT_SIZE_BUILTIN(nested->fst.snd, 3); 474 475 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 476 gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 0); 477 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 478 gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 1); 479 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 480 gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 2); 481 // CHECK: store i32 1 482 gi = OBJECT_SIZE_BUILTIN(nested->snd.snd, 3); 483 484 union { struct DynStruct1 d1; char c[1]; } *u; 485 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 486 gi = OBJECT_SIZE_BUILTIN(u->c, 0); 487 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 488 gi = OBJECT_SIZE_BUILTIN(u->c, 1); 489 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 490 gi = OBJECT_SIZE_BUILTIN(u->c, 2); 491 // CHECK: store i32 1 492 gi = OBJECT_SIZE_BUILTIN(u->c, 3); 493 494 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 495 gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 0); 496 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 497 gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 1); 498 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 499 gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 2); 500 // CHECK: store i32 1 501 gi = OBJECT_SIZE_BUILTIN(u->d1.snd, 3); 502 } 503 504 // CHECK-LABEL: @test31 505 void test31(void) { 506 // Miscellaneous 'writing off the end' detection tests 507 struct DynStructVar *dsv; 508 struct DynStruct0 *ds0; 509 struct DynStruct1 *ds1; 510 struct StaticStruct *ss; 511 512 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 513 gi = OBJECT_SIZE_BUILTIN(ds1[9].snd, 1); 514 515 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 516 gi = OBJECT_SIZE_BUILTIN(&ss[9].snd[0], 1); 517 518 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 519 gi = OBJECT_SIZE_BUILTIN(&ds1[9].snd[0], 1); 520 521 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 522 gi = OBJECT_SIZE_BUILTIN(&ds0[9].snd[0], 1); 523 524 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 525 gi = OBJECT_SIZE_BUILTIN(&dsv[9].snd[0], 1); 526 } 527 528 // CHECK-LABEL: @test32 529 static struct DynStructVar D32 = { 530 .fst = {}, 531 .snd = { 0, 1, 2, }, 532 }; 533 unsigned long test32(void) { 534 // CHECK: ret i64 19 535 return OBJECT_SIZE_BUILTIN(&D32, 1); 536 } 537 // CHECK-LABEL: @test33 538 static struct DynStructVar D33 = { 539 .fst = {}, 540 .snd = {}, 541 }; 542 unsigned long test33(void) { 543 // CHECK: ret i64 16 544 return OBJECT_SIZE_BUILTIN(&D33, 1); 545 } 546 // CHECK-LABEL: @test34 547 static struct DynStructVar D34 = { 548 .fst = {}, 549 }; 550 unsigned long test34(void) { 551 // CHECK: ret i64 16 552 return OBJECT_SIZE_BUILTIN(&D34, 1); 553 } 554 // CHECK-LABEL: @test35 555 unsigned long test35(void) { 556 // CHECK: ret i64 16 557 return OBJECT_SIZE_BUILTIN(&(struct DynStructVar){}, 1); 558 } 559 extern void *memset (void *s, int c, unsigned long n); 560 void test36(void) { 561 struct DynStructVar D; 562 // FORTIFY will check the object size of D. Test this doesn't assert when 563 // given a struct with a flexible array member that lacks an initializer. 564 memset(&D, 0, sizeof(D)); 565 } 566 // CHECK-LABEL: @test37 567 struct Z { struct A { int x, y[]; } z; int a; int b[]; }; 568 static struct Z my_z = { .b = {1,2,3} }; 569 unsigned long test37 (void) { 570 // CHECK: ret i64 4 571 return OBJECT_SIZE_BUILTIN(&my_z.z, 1); 572 } 573 574 // CHECK-LABEL: @PR30346 575 void PR30346(void) { 576 struct sa_family_t {}; 577 struct sockaddr { 578 struct sa_family_t sa_family; 579 char sa_data[14]; 580 }; 581 582 struct sockaddr *sa; 583 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 584 gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 0); 585 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 586 gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 1); 587 // CHECK: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 588 gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 2); 589 // CHECK: store i32 14 590 gi = OBJECT_SIZE_BUILTIN(sa->sa_data, 3); 591 } 592 593 extern char incomplete_char_array[]; 594 // CHECK-LABEL: @incomplete_and_function_types 595 void incomplete_and_function_types(void) { 596 // CHECK: call i64 @llvm.objectsize.i64.p0 597 gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 0); 598 // CHECK: call i64 @llvm.objectsize.i64.p0 599 gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 1); 600 // CHECK: call i64 @llvm.objectsize.i64.p0 601 gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 2); 602 // CHECK: store i32 0 603 gi = OBJECT_SIZE_BUILTIN(incomplete_char_array, 3); 604 } 605 606 // Flips between the pointer and lvalue evaluator a lot. 607 void deeply_nested(void) { 608 struct { 609 struct { 610 struct { 611 struct { 612 int e[2]; 613 char f; // Inhibit our writing-off-the-end check 614 } d[2]; 615 } c[2]; 616 } b[2]; 617 } *a; 618 619 // CHECK: store i32 4 620 gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 1); 621 // CHECK: store i32 4 622 gi = OBJECT_SIZE_BUILTIN(&a->b[1].c[1].d[1].e[1], 3); 623 } 624