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: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize 63 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 [[VAR]]) 64 gi = ObjectSize1(&t->t[1]); 65 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36) 66 gi = ObjectSize3(&t->t[1]); 67 } 68 69 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv 70 int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) { 71 // CHECK: @llvm.objectsize 72 return __builtin_object_size(p, 0); 73 } 74 75 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize1Pv 76 int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) { 77 // CHECK: @llvm.objectsize 78 return __builtin_object_size(p, 1); 79 } 80 81 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize2Pv 82 int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) { 83 // CHECK: @llvm.objectsize 84 return __builtin_object_size(p, 2); 85 } 86 87 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize3Pv 88 int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) { 89 // CHECK-NOT: @llvm.objectsize 90 return __builtin_object_size(p, 3); 91 } 92 93 // CHECK-LABEL: define i32 @_Z27NoViableOverloadObjectSize0Pv 94 // CHECK-NOT: @llvm.objectsize 95 int NoViableOverloadObjectSize0(void *const p PS(0)) 96 __attribute__((overloadable)) { 97 return __builtin_object_size(p, 0); 98 } 99 100 int NoViableOverloadObjectSize1(void *const p PS(1)) 101 __attribute__((overloadable)) { 102 return __builtin_object_size(p, 1); 103 } 104 105 int NoViableOverloadObjectSize2(void *const p PS(2)) 106 __attribute__((overloadable)) { 107 return __builtin_object_size(p, 2); 108 } 109 110 int NoViableOverloadObjectSize3(void *const p PS(3)) 111 __attribute__((overloadable)) { 112 return __builtin_object_size(p, 3); 113 } 114 115 const static int SHOULDNT_BE_CALLED = -100; 116 int NoViableOverloadObjectSize0(void *const p PS(0)) 117 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 118 return SHOULDNT_BE_CALLED; 119 } 120 121 int NoViableOverloadObjectSize1(void *const p PS(1)) 122 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 123 return SHOULDNT_BE_CALLED; 124 } 125 126 int NoViableOverloadObjectSize2(void *const p PS(2)) 127 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 128 return SHOULDNT_BE_CALLED; 129 } 130 131 int NoViableOverloadObjectSize3(void *const p PS(3)) 132 __attribute__((overloadable, enable_if(p == 0, "never selected"))) { 133 return SHOULDNT_BE_CALLED; 134 } 135 136 // CHECK-LABEL: define void @test3 137 void test3() { 138 struct Foo t[10]; 139 140 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360) 141 gi = NoViableOverloadObjectSize0(&t[1]); 142 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360) 143 gi = NoViableOverloadObjectSize1(&t[1]); 144 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360) 145 gi = NoViableOverloadObjectSize2(&t[1]); 146 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360) 147 gi = NoViableOverloadObjectSize3(&t[1]); 148 149 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356) 150 gi = NoViableOverloadObjectSize0(&t[1].t[1]); 151 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36) 152 gi = NoViableOverloadObjectSize1(&t[1].t[1]); 153 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356) 154 gi = NoViableOverloadObjectSize2(&t[1].t[1]); 155 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36) 156 gi = NoViableOverloadObjectSize3(&t[1].t[1]); 157 } 158 159 // CHECK-LABEL: define void @test4 160 void test4(struct Foo *t) { 161 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}}) 162 gi = NoViableOverloadObjectSize0(&t[1]); 163 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}}) 164 gi = NoViableOverloadObjectSize1(&t[1]); 165 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}}) 166 gi = NoViableOverloadObjectSize2(&t[1]); 167 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0) 168 gi = NoViableOverloadObjectSize3(&t[1]); 169 170 // CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}}) 171 gi = NoViableOverloadObjectSize0(&t[1].t[1]); 172 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize 173 // CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 [[VAR]]) 174 gi = NoViableOverloadObjectSize1(&t[1].t[1]); 175 // CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}}) 176 gi = NoViableOverloadObjectSize2(&t[1].t[1]); 177 // CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36) 178 gi = NoViableOverloadObjectSize3(&t[1].t[1]); 179 } 180 181 void test5() { 182 struct Foo t[10]; 183 184 int (*f)(void *) = &NoViableOverloadObjectSize0; 185 gi = f(&t[1]); 186 } 187 188 // CHECK-LABEL: define i32 @IndirectObjectSize0 189 int IndirectObjectSize0(void *const p PS(0)) { 190 // CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}}) 191 // CHECK-NOT: @llvm.objectsize 192 return ObjectSize0(p); 193 } 194 195 // CHECK-LABEL: define i32 @IndirectObjectSize1 196 int IndirectObjectSize1(void *const p PS(1)) { 197 // CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}}) 198 // CHECK-NOT: @llvm.objectsize 199 return ObjectSize1(p); 200 } 201 202 // CHECK-LABEL: define i32 @IndirectObjectSize2 203 int IndirectObjectSize2(void *const p PS(2)) { 204 // CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}}) 205 // CHECK-NOT: @llvm.objectsize 206 return ObjectSize2(p); 207 } 208 209 // CHECK-LABEL: define i32 @IndirectObjectSize3 210 int IndirectObjectSize3(void *const p PS(3)) { 211 // CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}}) 212 // CHECK-NOT: @llvm.objectsize 213 return ObjectSize3(p); 214 } 215 216 int Overload0(void *, size_t, void *, size_t); 217 int OverloadNoSize(void *, void *); 218 219 int OverloadedObjectSize(void *const p PS(0), 220 void *const c PS(0)) 221 __attribute__((overloadable)) __asm__("Overload0"); 222 223 int OverloadedObjectSize(void *const p, void *const c) 224 __attribute__((overloadable)) __asm__("OverloadNoSize"); 225 226 // CHECK-LABEL: define void @test6 227 void test6() { 228 int known[10], *opaque; 229 230 // CHECK: call i32 @"\01Overload0" 231 gi = OverloadedObjectSize(&known[0], &known[0]); 232 233 // CHECK: call i32 @"\01Overload0" 234 gi = OverloadedObjectSize(&known[0], opaque); 235 236 // CHECK: call i32 @"\01Overload0" 237 gi = OverloadedObjectSize(opaque, &known[0]); 238 239 // CHECK: call i32 @"\01Overload0" 240 gi = OverloadedObjectSize(opaque, opaque); 241 } 242 243 int Identity(void *p, size_t i) { return i; } 244 245 // CHECK-NOT: define void @AsmObjectSize 246 int AsmObjectSize0(void *const p PS(0)) __asm__("Identity"); 247 248 int AsmObjectSize1(void *const p PS(1)) __asm__("Identity"); 249 250 int AsmObjectSize2(void *const p PS(2)) __asm__("Identity"); 251 252 int AsmObjectSize3(void *const p PS(3)) __asm__("Identity"); 253 254 // CHECK-LABEL: define void @test7 255 void test7() { 256 struct Foo t[10]; 257 258 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 259 gi = AsmObjectSize0(&t[1]); 260 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 261 gi = AsmObjectSize1(&t[1]); 262 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 263 gi = AsmObjectSize2(&t[1]); 264 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360) 265 gi = AsmObjectSize3(&t[1]); 266 267 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356) 268 gi = AsmObjectSize0(&t[1].t[1]); 269 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 270 gi = AsmObjectSize1(&t[1].t[1]); 271 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356) 272 gi = AsmObjectSize2(&t[1].t[1]); 273 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 274 gi = AsmObjectSize3(&t[1].t[1]); 275 } 276 277 // CHECK-LABEL: define void @test8 278 void test8(struct Foo *t) { 279 // CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize 280 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 [[VAR]]) 281 gi = AsmObjectSize1(&t[1].t[1]); 282 // CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36) 283 gi = AsmObjectSize3(&t[1].t[1]); 284 } 285 286 void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0)))); 287 void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1)))); 288 void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2)))); 289 void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3)))); 290 291 // CHECK-LABEL: define void @test9 292 void test9(void *const p __attribute__((pass_object_size(0)))) { 293 // CHECK: @llvm.objectsize 294 DifferingObjectSize2(p); 295 296 // CHECK-NOT: @llvm.objectsize 297 DifferingObjectSize0(p); 298 DifferingObjectSize1(p); 299 300 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0) 301 DifferingObjectSize3(p); 302 } 303 304 // CHECK-LABEL: define void @test10 305 void test10(void *const p __attribute__((pass_object_size(1)))) { 306 // CHECK: @llvm.objectsize 307 DifferingObjectSize2(p); 308 // CHECK: @llvm.objectsize 309 DifferingObjectSize0(p); 310 311 // CHECK-NOT: @llvm.objectsize 312 DifferingObjectSize1(p); 313 314 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0) 315 DifferingObjectSize3(p); 316 } 317 318 // CHECK-LABEL: define void @test11 319 void test11(void *const p __attribute__((pass_object_size(2)))) { 320 // CHECK: @llvm.objectsize 321 DifferingObjectSize0(p); 322 // CHECK: @llvm.objectsize 323 DifferingObjectSize1(p); 324 325 // CHECK-NOT: @llvm.objectsize 326 DifferingObjectSize2(p); 327 328 // CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0) 329 DifferingObjectSize3(p); 330 } 331 332 // CHECK-LABEL: define void @test12 333 void test12(void *const p __attribute__((pass_object_size(3)))) { 334 // CHECK: @llvm.objectsize 335 DifferingObjectSize0(p); 336 // CHECK: @llvm.objectsize 337 DifferingObjectSize1(p); 338 339 // CHECK-NOT: @llvm.objectsize 340 DifferingObjectSize2(p); 341 DifferingObjectSize3(p); 342 } 343 344 // CHECK-LABEL: define void @test13 345 void test13() { 346 // Ensuring that we don't lower objectsize if the expression has side-effects 347 char c[10]; 348 char *p = c; 349 350 // CHECK: @llvm.objectsize 351 ObjectSize0(p); 352 353 // CHECK-NOT: @llvm.objectsize 354 ObjectSize0(++p); 355 ObjectSize0(p++); 356 } 357 358 // There was a bug where variadic functions with pass_object_size would cause 359 // problems in the form of failed assertions. 360 void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {} 361 362 // CHECK-LABEL: define void @test14 363 void test14(char *c) { 364 // CHECK: @llvm.objectsize 365 // CHECK: call void (i8*, i64, ...) @my_sprintf 366 my_sprintf(c); 367 368 // CHECK: @llvm.objectsize 369 // CHECK: call void (i8*, i64, ...) @my_sprintf 370 my_sprintf(c, 1, 2, 3); 371 } 372