summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGen/object-size.c
diff options
context:
space:
mode:
authorGeorge Burgess IV <george.burgess.iv@gmail.com>2015-10-16 01:49:01 +0000
committerGeorge Burgess IV <george.burgess.iv@gmail.com>2015-10-16 01:49:01 +0000
commita51c4077c553c8703832e56ba763428334af8150 (patch)
treee29ca4feada7bfa4fc0a294638f304b3f3c74903 /clang/test/CodeGen/object-size.c
parent59e847f997a4494c695c89068c4db34fb36de3ab (diff)
downloadbcm5719-llvm-a51c4077c553c8703832e56ba763428334af8150.tar.gz
bcm5719-llvm-a51c4077c553c8703832e56ba763428334af8150.zip
Make __builtin_object_size more conservative
r246877 made __builtin_object_size substantially more aggressive with unknown bases if Type=1 or Type=3, which causes issues when we encounter code like this: struct Foo { int a; char str[1]; }; const char str[] = "Hello, World!"; struct Foo *f = (struct Foo *)malloc(sizeof(*f) + strlen(str)); strcpy(&f->str, str); __builtin_object_size(&f->str, 1) would hand back 1, which is technically correct given the type of Foo, but the type of Foo lies to us about how many bytes are available in this case. This patch adds support for this "writing off the end" idiom -- we now answer conservatively when we're given the address of the very last member in a struct. Differential Revision: http://reviews.llvm.org/D12169 llvm-svn: 250488
Diffstat (limited to 'clang/test/CodeGen/object-size.c')
-rw-r--r--clang/test/CodeGen/object-size.c150
1 files changed, 138 insertions, 12 deletions
diff --git a/clang/test/CodeGen/object-size.c b/clang/test/CodeGen/object-size.c
index e69764087e9..610e54150d8 100644
--- a/clang/test/CodeGen/object-size.c
+++ b/clang/test/CodeGen/object-size.c
@@ -127,7 +127,7 @@ void test16() {
strcpy(gp += 1, "Hi there");
}
-// CHECK: @test17
+// CHECK-LABEL: @test17
void test17() {
// CHECK: store i32 -1
gi = __builtin_object_size(gp++, 0);
@@ -139,7 +139,7 @@ void test17() {
gi = __builtin_object_size(gp++, 3);
}
-// CHECK: @test18
+// CHECK-LABEL: @test18
unsigned test18(int cond) {
int a[4], b[4];
// CHECK: phi i32*
@@ -147,7 +147,7 @@ unsigned test18(int cond) {
return __builtin_object_size(cond ? a : b, 0);
}
-// CHECK: @test19
+// CHECK-LABEL: @test19
void test19() {
struct {
int a, b;
@@ -172,7 +172,7 @@ void test19() {
gi = __builtin_object_size(&foo.b, 3);
}
-// CHECK: @test20
+// CHECK-LABEL: @test20
void test20() {
struct { int t[10]; } t[10];
@@ -186,7 +186,7 @@ void test20() {
gi = __builtin_object_size(&t[0].t[5], 3);
}
-// CHECK: @test21
+// CHECK-LABEL: @test21
void test21() {
struct { int t; } t;
@@ -209,7 +209,7 @@ void test21() {
gi = __builtin_object_size(&t.t + 1, 3);
}
-// CHECK: @test22
+// CHECK-LABEL: @test22
void test22() {
struct { int t[10]; } t[10];
@@ -252,7 +252,7 @@ void test22() {
struct Test23Ty { int a; int t[10]; };
-// CHECK: @test23
+// CHECK-LABEL: @test23
void test23(struct Test23Ty *p) {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(p, 0);
@@ -285,7 +285,7 @@ void test23(struct Test23Ty *p) {
}
// PR24493 -- ICE if __builtin_object_size called with NULL and (Type & 1) != 0
-// CHECK: @test24
+// CHECK-LABEL: @test24
void test24() {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false)
gi = __builtin_object_size((void*)0, 0);
@@ -299,7 +299,7 @@ void test24() {
gi = __builtin_object_size((void*)0, 3);
}
-// CHECK: @test25
+// CHECK-LABEL: @test25
void test25() {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false)
gi = __builtin_object_size((void*)0x1000, 0);
@@ -324,7 +324,7 @@ void test25() {
gi = __builtin_object_size((void*)0 + 0x1000, 3);
}
-// CHECK: @test26
+// CHECK-LABEL: @test26
void test26() {
struct { int v[10]; } t[10];
@@ -340,7 +340,7 @@ void test26() {
struct Test27IncompleteTy;
-// CHECK: @test27
+// CHECK-LABEL: @test27
void test27(struct Test27IncompleteTy *t) {
// CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
gi = __builtin_object_size(t, 0);
@@ -367,7 +367,7 @@ void test27(struct Test27IncompleteTy *t) {
// The intent of this test is to ensure that __builtin_object_size treats `&foo`
// and `(T*)&foo` identically, when used as the pointer argument.
-// CHECK: @test28
+// CHECK-LABEL: @test28
void test28() {
struct { int v[10]; } t[10];
@@ -391,3 +391,129 @@ void test28() {
gi = __builtin_object_size(addCasts(&t[1].v[1]), 3);
#undef addCasts
}
+
+struct DynStructVar {
+ char fst[16];
+ char snd[];
+};
+
+struct DynStruct0 {
+ char fst[16];
+ char snd[0];
+};
+
+struct DynStruct1 {
+ char fst[16];
+ char snd[1];
+};
+
+struct StaticStruct {
+ char fst[16];
+ char snd[2];
+};
+
+// CHECK-LABEL: @test29
+void test29(struct DynStructVar *dv, struct DynStruct0 *d0,
+ struct DynStruct1 *d1, struct StaticStruct *ss) {
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(dv->snd, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(dv->snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(dv->snd, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(dv->snd, 3);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(d0->snd, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(d0->snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(d0->snd, 2);
+ // CHECK: store i32 0
+ gi = __builtin_object_size(d0->snd, 3);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(d1->snd, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(d1->snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(d1->snd, 2);
+ // CHECK: store i32 1
+ gi = __builtin_object_size(d1->snd, 3);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(ss->snd, 0);
+ // CHECK: store i32 2
+ gi = __builtin_object_size(ss->snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(ss->snd, 2);
+ // CHECK: store i32 2
+ gi = __builtin_object_size(ss->snd, 3);
+}
+
+// CHECK-LABEL: @test30
+void test30() {
+ struct { struct DynStruct1 fst, snd; } *nested;
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(nested->fst.snd, 0);
+ // CHECK: store i32 1
+ gi = __builtin_object_size(nested->fst.snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(nested->fst.snd, 2);
+ // CHECK: store i32 1
+ gi = __builtin_object_size(nested->fst.snd, 3);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(nested->snd.snd, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(nested->snd.snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(nested->snd.snd, 2);
+ // CHECK: store i32 1
+ gi = __builtin_object_size(nested->snd.snd, 3);
+
+ union { struct DynStruct1 d1; char c[1]; } *u;
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(u->c, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(u->c, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(u->c, 2);
+ // CHECK: store i32 1
+ gi = __builtin_object_size(u->c, 3);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(u->d1.snd, 0);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(u->d1.snd, 1);
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 true)
+ gi = __builtin_object_size(u->d1.snd, 2);
+ // CHECK: store i32 1
+ gi = __builtin_object_size(u->d1.snd, 3);
+}
+
+// CHECK-LABEL: @test31
+void test31() {
+ // Miscellaneous 'writing off the end' detection tests
+ struct DynStructVar *dsv;
+ struct DynStruct0 *ds0;
+ struct DynStruct1 *ds1;
+ struct StaticStruct *ss;
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(ds1[9].snd, 1);
+
+ // CHECH: store i32 2
+ gi = __builtin_object_size(&ss[9].snd[0], 1);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(&ds1[9].snd[0], 1);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(&ds0[9].snd[0], 1);
+
+ // CHECK: call i64 @llvm.objectsize.i64.p0i8(i8* %{{.*}}, i1 false)
+ gi = __builtin_object_size(&dsv[9].snd[0], 1);
+}
OpenPOWER on IntegriCloud