diff options
author | George Burgess IV <george.burgess.iv@gmail.com> | 2015-10-16 01:49:01 +0000 |
---|---|---|
committer | George Burgess IV <george.burgess.iv@gmail.com> | 2015-10-16 01:49:01 +0000 |
commit | a51c4077c553c8703832e56ba763428334af8150 (patch) | |
tree | e29ca4feada7bfa4fc0a294638f304b3f3c74903 /clang/test/CodeGen/object-size.c | |
parent | 59e847f997a4494c695c89068c4db34fb36de3ab (diff) | |
download | bcm5719-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.c | 150 |
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); +} |