494 lines
16 KiB
C
494 lines
16 KiB
C
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -O0 %s -o - 2>&1 | FileCheck %s
|
||
|
|
||
|
typedef unsigned long size_t;
|
||
|
|
||
|
struct Foo {
|
||
|
int t[10];
|
||
|
};
|
||
|
|
||
|
#define PS(N) __attribute__((pass_object_size(N)))
|
||
|
#define PDS(N) __attribute__((pass_dynamic_object_size(N)))
|
||
|
|
||
|
int gi = 0;
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @ObjectSize0(i8* %{{.*}}, i64 %0)
|
||
|
int ObjectSize0(void *const p PS(0)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 0);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize0(i8* %{{.*}}, i64 %0)
|
||
|
int DynamicObjectSize0(void *const p PDS(0)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_dynamic_object_size(p, 0);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @ObjectSize1(i8* %{{.*}}, i64 %0)
|
||
|
int ObjectSize1(void *const p PS(1)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 1);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize1(i8* %{{.*}}, i64 %0)
|
||
|
int DynamicObjectSize1(void *const p PDS(1)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_dynamic_object_size(p, 1);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @ObjectSize2(i8* %{{.*}}, i64 %0)
|
||
|
int ObjectSize2(void *const p PS(2)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 2);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize2(i8* %{{.*}}, i64 %0)
|
||
|
int DynamicObjectSize2(void *const p PDS(2)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 2);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @ObjectSize3(i8* %{{.*}}, i64 %0)
|
||
|
int ObjectSize3(void *const p PS(3)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 3);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @DynamicObjectSize3(i8* %{{.*}}, i64 %0)
|
||
|
int DynamicObjectSize3(void *const p PDS(3)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 3);
|
||
|
}
|
||
|
|
||
|
void *malloc(unsigned long) __attribute__((alloc_size(1)));
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test1
|
||
|
void test1(unsigned long sz) {
|
||
|
struct Foo t[10];
|
||
|
|
||
|
// CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 360)
|
||
|
gi = ObjectSize0(&t[1]);
|
||
|
// CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 360)
|
||
|
gi = ObjectSize1(&t[1]);
|
||
|
// CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 360)
|
||
|
gi = ObjectSize2(&t[1]);
|
||
|
// CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 360)
|
||
|
gi = ObjectSize3(&t[1]);
|
||
|
|
||
|
// CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 356)
|
||
|
gi = ObjectSize0(&t[1].t[1]);
|
||
|
// CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 36)
|
||
|
gi = ObjectSize1(&t[1].t[1]);
|
||
|
// CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 356)
|
||
|
gi = ObjectSize2(&t[1].t[1]);
|
||
|
// CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
|
||
|
gi = ObjectSize3(&t[1].t[1]);
|
||
|
|
||
|
char *ptr = (char *)malloc(sz);
|
||
|
|
||
|
// CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0i8({{.*}}, i1 false, i1 true, i1 true)
|
||
|
// CHECK: call i32 @DynamicObjectSize0(i8* %{{.*}}, i64 [[REG]])
|
||
|
gi = DynamicObjectSize0(ptr);
|
||
|
|
||
|
// CHECK: [[WITH_OFFSET:%.*]] = getelementptr
|
||
|
// CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* [[WITH_OFFSET]], i1 false, i1 true, i1 true)
|
||
|
// CHECK: call i32 @DynamicObjectSize0(i8* {{.*}}, i64 [[REG]])
|
||
|
gi = DynamicObjectSize0(ptr+10);
|
||
|
|
||
|
// CHECK: [[REG:%.*]] = call i64 @llvm.objectsize.i64.p0i8({{.*}}, i1 true, i1 true, i1 true)
|
||
|
// CHECK: call i32 @DynamicObjectSize2(i8* {{.*}}, i64 [[REG]])
|
||
|
gi = DynamicObjectSize2(ptr);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test2
|
||
|
void test2(struct Foo *t) {
|
||
|
// CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
|
||
|
// CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 [[VAR]])
|
||
|
gi = ObjectSize1(&t->t[1]);
|
||
|
// CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 36)
|
||
|
gi = ObjectSize3(&t->t[1]);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv
|
||
|
int NoViableOverloadObjectSize0(void *const p) __attribute__((overloadable)) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 0);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @_Z34NoViableOverloadDynamicObjectSize0Pv
|
||
|
int NoViableOverloadDynamicObjectSize0(void *const p)
|
||
|
__attribute__((overloadable)) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 0);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize1Pv
|
||
|
int NoViableOverloadObjectSize1(void *const p) __attribute__((overloadable)) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 1);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize2Pv
|
||
|
int NoViableOverloadObjectSize2(void *const p) __attribute__((overloadable)) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 2);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize3Pv
|
||
|
int NoViableOverloadObjectSize3(void *const p) __attribute__((overloadable)) {
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return __builtin_object_size(p, 3);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @_Z27NoViableOverloadObjectSize0Pv
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
int NoViableOverloadObjectSize0(void *const p PS(0))
|
||
|
__attribute__((overloadable)) {
|
||
|
return __builtin_object_size(p, 0);
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadDynamicObjectSize0(void *const p PDS(0))
|
||
|
__attribute__((overloadable)) {
|
||
|
return __builtin_dynamic_object_size(p, 0);
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadObjectSize1(void *const p PS(1))
|
||
|
__attribute__((overloadable)) {
|
||
|
return __builtin_object_size(p, 1);
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadObjectSize2(void *const p PS(2))
|
||
|
__attribute__((overloadable)) {
|
||
|
return __builtin_object_size(p, 2);
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadObjectSize3(void *const p PS(3))
|
||
|
__attribute__((overloadable)) {
|
||
|
return __builtin_object_size(p, 3);
|
||
|
}
|
||
|
|
||
|
const static int SHOULDNT_BE_CALLED = -100;
|
||
|
int NoViableOverloadObjectSize0(void *const p PS(0))
|
||
|
__attribute__((overloadable, enable_if(p == 0, "never selected"))) {
|
||
|
return SHOULDNT_BE_CALLED;
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadObjectSize1(void *const p PS(1))
|
||
|
__attribute__((overloadable, enable_if(p == 0, "never selected"))) {
|
||
|
return SHOULDNT_BE_CALLED;
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadObjectSize2(void *const p PS(2))
|
||
|
__attribute__((overloadable, enable_if(p == 0, "never selected"))) {
|
||
|
return SHOULDNT_BE_CALLED;
|
||
|
}
|
||
|
|
||
|
int NoViableOverloadObjectSize3(void *const p PS(3))
|
||
|
__attribute__((overloadable, enable_if(p == 0, "never selected"))) {
|
||
|
return SHOULDNT_BE_CALLED;
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test3
|
||
|
void test3() {
|
||
|
struct Foo t[10];
|
||
|
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 360)
|
||
|
gi = NoViableOverloadObjectSize0(&t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 360)
|
||
|
gi = NoViableOverloadObjectSize1(&t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 360)
|
||
|
gi = NoViableOverloadObjectSize2(&t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 360)
|
||
|
gi = NoViableOverloadObjectSize3(&t[1]);
|
||
|
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 356)
|
||
|
gi = NoViableOverloadObjectSize0(&t[1].t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 36)
|
||
|
gi = NoViableOverloadObjectSize1(&t[1].t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 356)
|
||
|
gi = NoViableOverloadObjectSize2(&t[1].t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
|
||
|
gi = NoViableOverloadObjectSize3(&t[1].t[1]);
|
||
|
|
||
|
// CHECK: call i32 @_Z34NoViableOverloadDynamicObjectSize0PvU25pass_dynamic_object_size0(i8* %{{.*}}, i64 360)
|
||
|
gi = NoViableOverloadDynamicObjectSize0(&t[1]);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test4
|
||
|
void test4(struct Foo *t) {
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
|
||
|
gi = NoViableOverloadObjectSize0(&t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 %{{.*}})
|
||
|
gi = NoViableOverloadObjectSize1(&t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
|
||
|
gi = NoViableOverloadObjectSize2(&t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 0)
|
||
|
gi = NoViableOverloadObjectSize3(&t[1]);
|
||
|
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize0PvU17pass_object_size0(i8* %{{.*}}, i64 %{{.*}})
|
||
|
gi = NoViableOverloadObjectSize0(&t[1].t[1]);
|
||
|
// CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize1PvU17pass_object_size1(i8* %{{.*}}, i64 [[VAR]])
|
||
|
gi = NoViableOverloadObjectSize1(&t[1].t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize2PvU17pass_object_size2(i8* %{{.*}}, i64 %{{.*}})
|
||
|
gi = NoViableOverloadObjectSize2(&t[1].t[1]);
|
||
|
// CHECK: call i32 @_Z27NoViableOverloadObjectSize3PvU17pass_object_size3(i8* %{{.*}}, i64 36)
|
||
|
gi = NoViableOverloadObjectSize3(&t[1].t[1]);
|
||
|
}
|
||
|
|
||
|
void test5() {
|
||
|
struct Foo t[10];
|
||
|
|
||
|
int (*f)(void *) = &NoViableOverloadObjectSize0;
|
||
|
gi = f(&t[1]);
|
||
|
|
||
|
int (*g)(void *) = &NoViableOverloadDynamicObjectSize0;
|
||
|
gi = g(&t[1]);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize0
|
||
|
int IndirectObjectSize0(void *const p PS(0)) {
|
||
|
// CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return ObjectSize0(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize1
|
||
|
int IndirectObjectSize1(void *const p PS(1)) {
|
||
|
// CHECK: call i32 @ObjectSize1(i8* %{{.*}}, i64 %{{.*}})
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return ObjectSize1(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize2
|
||
|
int IndirectObjectSize2(void *const p PS(2)) {
|
||
|
// CHECK: call i32 @ObjectSize2(i8* %{{.*}}, i64 %{{.*}})
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return ObjectSize2(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} i32 @IndirectObjectSize3
|
||
|
int IndirectObjectSize3(void *const p PS(3)) {
|
||
|
// CHECK: call i32 @ObjectSize3(i8* %{{.*}}, i64 %{{.*}})
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return ObjectSize3(p);
|
||
|
}
|
||
|
|
||
|
int IndirectDynamicObjectSize0(void *const p PDS(0)) {
|
||
|
// CHECK: call i32 @ObjectSize0(i8* %{{.*}}, i64 %{{.*}})
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
return ObjectSize0(p);
|
||
|
}
|
||
|
|
||
|
int Overload0(void *, size_t, void *, size_t);
|
||
|
int OverloadNoSize(void *, void *);
|
||
|
|
||
|
int OverloadedObjectSize(void *const p PS(0),
|
||
|
void *const c PS(0))
|
||
|
__attribute__((overloadable)) __asm__("Overload0");
|
||
|
|
||
|
int OverloadedObjectSize(void *const p, void *const c)
|
||
|
__attribute__((overloadable)) __asm__("OverloadNoSize");
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test6
|
||
|
void test6() {
|
||
|
int known[10], *opaque;
|
||
|
|
||
|
// CHECK: call i32 @"\01Overload0"
|
||
|
gi = OverloadedObjectSize(&known[0], &known[0]);
|
||
|
|
||
|
// CHECK: call i32 @"\01Overload0"
|
||
|
gi = OverloadedObjectSize(&known[0], opaque);
|
||
|
|
||
|
// CHECK: call i32 @"\01Overload0"
|
||
|
gi = OverloadedObjectSize(opaque, &known[0]);
|
||
|
|
||
|
// CHECK: call i32 @"\01Overload0"
|
||
|
gi = OverloadedObjectSize(opaque, opaque);
|
||
|
}
|
||
|
|
||
|
int Identity(void *p, size_t i) { return i; }
|
||
|
|
||
|
// CHECK-NOT: define{{.*}} void @AsmObjectSize
|
||
|
int AsmObjectSize0(void *const p PS(0)) __asm__("Identity");
|
||
|
|
||
|
int AsmObjectSize1(void *const p PS(1)) __asm__("Identity");
|
||
|
|
||
|
int AsmObjectSize2(void *const p PS(2)) __asm__("Identity");
|
||
|
|
||
|
int AsmObjectSize3(void *const p PS(3)) __asm__("Identity");
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test7
|
||
|
void test7() {
|
||
|
struct Foo t[10];
|
||
|
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
|
||
|
gi = AsmObjectSize0(&t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
|
||
|
gi = AsmObjectSize1(&t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
|
||
|
gi = AsmObjectSize2(&t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 360)
|
||
|
gi = AsmObjectSize3(&t[1]);
|
||
|
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
|
||
|
gi = AsmObjectSize0(&t[1].t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
|
||
|
gi = AsmObjectSize1(&t[1].t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 356)
|
||
|
gi = AsmObjectSize2(&t[1].t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
|
||
|
gi = AsmObjectSize3(&t[1].t[1]);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test8
|
||
|
void test8(struct Foo *t) {
|
||
|
// CHECK: [[VAR:%[0-9]+]] = call i64 @llvm.objectsize
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 [[VAR]])
|
||
|
gi = AsmObjectSize1(&t[1].t[1]);
|
||
|
// CHECK: call i32 @"\01Identity"(i8* %{{.*}}, i64 36)
|
||
|
gi = AsmObjectSize3(&t[1].t[1]);
|
||
|
}
|
||
|
|
||
|
void DifferingObjectSize0(void *const p __attribute__((pass_object_size(0))));
|
||
|
void DifferingObjectSize1(void *const p __attribute__((pass_object_size(1))));
|
||
|
void DifferingObjectSize2(void *const p __attribute__((pass_object_size(2))));
|
||
|
void DifferingObjectSize3(void *const p __attribute__((pass_object_size(3))));
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test9
|
||
|
void test9(void *const p __attribute__((pass_object_size(0)))) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize2(p);
|
||
|
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
DifferingObjectSize0(p);
|
||
|
DifferingObjectSize1(p);
|
||
|
|
||
|
// CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
|
||
|
DifferingObjectSize3(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test10
|
||
|
void test10(void *const p __attribute__((pass_object_size(1)))) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize2(p);
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize0(p);
|
||
|
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
DifferingObjectSize1(p);
|
||
|
|
||
|
// CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
|
||
|
DifferingObjectSize3(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test11
|
||
|
void test11(void *const p __attribute__((pass_object_size(2)))) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize0(p);
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize1(p);
|
||
|
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
DifferingObjectSize2(p);
|
||
|
|
||
|
// CHECK: call void @DifferingObjectSize3(i8* %{{.*}}, i64 0)
|
||
|
DifferingObjectSize3(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test12
|
||
|
void test12(void *const p __attribute__((pass_object_size(3)))) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize0(p);
|
||
|
// CHECK: @llvm.objectsize
|
||
|
DifferingObjectSize1(p);
|
||
|
|
||
|
// CHECK-NOT: @llvm.objectsize
|
||
|
DifferingObjectSize2(p);
|
||
|
DifferingObjectSize3(p);
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test13
|
||
|
void test13() {
|
||
|
char c[10];
|
||
|
unsigned i = 0;
|
||
|
char *p = c;
|
||
|
|
||
|
// CHECK: @llvm.objectsize
|
||
|
ObjectSize0(p);
|
||
|
|
||
|
// Allow side-effects, since they always need to happen anyway. Just make sure
|
||
|
// we don't perform them twice.
|
||
|
// CHECK: = add
|
||
|
// CHECK-NOT: = add
|
||
|
// CHECK: @llvm.objectsize
|
||
|
// CHECK: call i32 @ObjectSize0
|
||
|
ObjectSize0(p + ++i);
|
||
|
|
||
|
// CHECK: = add
|
||
|
// CHECK: @llvm.objectsize
|
||
|
// CHECK-NOT: = add
|
||
|
// CHECK: call i32 @ObjectSize0
|
||
|
ObjectSize0(p + i++);
|
||
|
}
|
||
|
|
||
|
// There was a bug where variadic functions with pass_object_size would cause
|
||
|
// problems in the form of failed assertions.
|
||
|
void my_sprintf(char *const c __attribute__((pass_object_size(0))), ...) {}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test14
|
||
|
void test14(char *c) {
|
||
|
// CHECK: @llvm.objectsize
|
||
|
// CHECK: call void (i8*, i64, ...) @my_sprintf
|
||
|
my_sprintf(c);
|
||
|
|
||
|
// CHECK: @llvm.objectsize
|
||
|
// CHECK: call void (i8*, i64, ...) @my_sprintf
|
||
|
my_sprintf(c, 1, 2, 3);
|
||
|
}
|
||
|
|
||
|
void pass_size_unsigned(unsigned *const PS(0));
|
||
|
|
||
|
// Bug: we weren't lowering to the proper @llvm.objectsize for pointers that
|
||
|
// don't turn into i8*s, which caused crashes.
|
||
|
// CHECK-LABEL: define{{.*}} void @test15
|
||
|
void test15(unsigned *I) {
|
||
|
// CHECK: @llvm.objectsize.i64.p0i32
|
||
|
// CHECK: call void @pass_size_unsigned
|
||
|
pass_size_unsigned(I);
|
||
|
}
|
||
|
|
||
|
void pass_size_as1(__attribute__((address_space(1))) void *const PS(0));
|
||
|
|
||
|
void pass_size_unsigned_as1(
|
||
|
__attribute__((address_space(1))) unsigned *const PS(0));
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test16
|
||
|
void test16(__attribute__((address_space(1))) unsigned *I) {
|
||
|
// CHECK: call i64 @llvm.objectsize.i64.p1i8
|
||
|
// CHECK: call void @pass_size_as1
|
||
|
pass_size_as1(I);
|
||
|
// CHECK: call i64 @llvm.objectsize.i64.p1i32
|
||
|
// CHECK: call void @pass_size_unsigned_as1
|
||
|
pass_size_unsigned_as1(I);
|
||
|
}
|
||
|
|
||
|
// This used to cause assertion failures, since we'd try to emit the statement
|
||
|
// expression (and definitions for `a`) twice.
|
||
|
// CHECK-LABEL: define{{.*}} void @test17
|
||
|
void test17(char *C) {
|
||
|
// Check for 65535 to see if we're emitting this pointer twice.
|
||
|
// CHECK: 65535
|
||
|
// CHECK-NOT: 65535
|
||
|
// CHECK: @llvm.objectsize.i64.p0i8(i8* [[PTR:%[^,]+]],
|
||
|
// CHECK-NOT: 65535
|
||
|
// CHECK: call i32 @ObjectSize0(i8* [[PTR]]
|
||
|
ObjectSize0(C + ({ int a = 65535; a; }));
|
||
|
}
|
||
|
|
||
|
// CHECK-LABEL: define{{.*}} void @test18
|
||
|
void test18(char *const p PDS(0)) {
|
||
|
// CHECK-NOT: llvm.objectsize
|
||
|
gi = __builtin_dynamic_object_size(p, 0);
|
||
|
gi = __builtin_object_size(p, 0);
|
||
|
}
|