-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Description
The following example results in a return value of 0, but it should be possible to figure out that there's at minimum 10 bytes left in the object:
int cond;
long long bos() {
char arr[20];
void *p = cond ? &arr[0] : &arr[10];
return __builtin_object_size(p, 2);
}
See Godbolt: https://godbolt.org/z/vhfWv69Tv
Looking at ObjectSizeOffsetVisitor shows two things that seem odd.
The first is that it will give up on visiting instructions that have already been visited:
if (Instruction *I = dyn_cast<Instruction>(V)) {
// If we have already seen this instruction, bail out. Cycles can happen in
// unreachable code after constant propagation.
if (!SeenInsts.insert(I).second)
return unknown();
return visit(*I);
}
So it won't end up visiting the alloca
again, and just considers it to have unknown size on the second visit.
Even without this, the analysis still fails. If MustSucceed
is false, it resorts to finding an exact size instead of a reasonable conservative estimate:
// Unless we have to fold this to something, try to be as accurate as
// possible.
if (MustSucceed)
EvalOptions.EvalMode =
MaxVal ? ObjectSizeOpts::Mode::Max : ObjectSizeOpts::Mode::Min;
else
EvalOptions.EvalMode = ObjectSizeOpts::Mode::ExactSizeFromOffset;
But the result then is that it cannot find an exact size (because it doesn't know if it's 10 or 20), so it produces the most conservative estimate 0 instead.