Skip to content

Commit 7a4b6df

Browse files
committed
account for bitfields when computing struct size
1 parent 3181f13 commit 7a4b6df

1 file changed

Lines changed: 35 additions & 5 deletions

File tree

lib/valueflow.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ static Result accumulateStructMembers(const Scope* scope, F f, ValueFlow::Accura
440440
for (const Variable& var : scope->varlist) {
441441
if (var.isStatic())
442442
continue;
443+
const size_t bits = var.nameToken()->bits();
443444
if (const ValueType* vt = var.valueType()) {
444445
if (vt->type == ValueType::Type::RECORD && vt->typeScope == scope)
445446
return {0, false};
@@ -449,12 +450,12 @@ static Result accumulateStructMembers(const Scope* scope, F f, ValueFlow::Accura
449450
if (var.nameToken()->scope() != scope && var.nameToken()->scope()->definedType) { // anonymous union
450451
const auto ret = anonScopes.insert(var.nameToken()->scope());
451452
if (ret.second)
452-
total = f(total, *vt, dim);
453+
total = f(total, *vt, dim, bits);
453454
}
454455
else
455-
total = f(total, *vt, dim);
456+
total = f(total, *vt, dim, bits);
456457
}
457-
if (accuracy == ValueFlow::Accuracy::ExactOrZero && total == 0)
458+
if (accuracy == ValueFlow::Accuracy::ExactOrZero && total == 0 && bits == 0)
458459
return {0, false};
459460
}
460461
return {total, true};
@@ -485,7 +486,7 @@ static size_t getAlignOf(const ValueType& vt, const Settings& settings, ValueFlo
485486
return align == 0 ? 0 : bitCeil(align);
486487
}
487488
if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
488-
auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/) {
489+
auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/, size_t /*bits*/) {
489490
size_t a = getAlignOf(vt2, settings, accuracy, ++maxRecursion);
490491
return std::max(max, a);
491492
};
@@ -534,17 +535,46 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, Accur
534535
if (vt.type == ValueType::Type::CONTAINER)
535536
return 3 * settings.platform.sizeof_pointer; // Just guess
536537
if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
537-
auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim) -> size_t {
538+
size_t currentBitCount = 0;
539+
size_t currentBitfieldAlloc = 0;
540+
auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim, size_t bits) -> size_t {
541+
const size_t charBit = settings.platform.char_bit;
538542
size_t n = ValueFlow::getSizeOf(vt2, settings,accuracy, ++maxRecursion);
539543
size_t a = getAlignOf(vt2, settings, accuracy);
544+
if (bits > 0) {
545+
size_t ret = total;
546+
if (currentBitfieldAlloc == 0) {
547+
currentBitfieldAlloc = n;
548+
currentBitCount = 0;
549+
} else if (currentBitCount + bits > charBit * currentBitfieldAlloc) {
550+
ret += currentBitfieldAlloc;
551+
currentBitfieldAlloc = n;
552+
currentBitCount = 0;
553+
}
554+
currentBitCount += bits;
555+
return ret;
556+
}
540557
if (n == 0 || a == 0)
541558
return accuracy == Accuracy::ExactOrZero ? 0 : total;
542559
n *= dim;
543560
size_t padding = (a - (total % a)) % a;
561+
if (currentBitCount > 0) {
562+
bool fitsInBitfield = currentBitCount + n * charBit <= currentBitfieldAlloc * charBit;
563+
bool isAligned = currentBitCount % (charBit * a) == 0;
564+
if (vt2.isIntegral() && fitsInBitfield && isAligned) {
565+
currentBitCount += charBit * n;
566+
return total;
567+
}
568+
n += currentBitfieldAlloc;
569+
currentBitfieldAlloc = 0;
570+
currentBitCount = 0;
571+
}
544572
return vt.typeScope->type == ScopeType::eUnion ? std::max(total, n) : total + padding + n;
545573
};
546574
Result result = accumulateStructMembers(vt.typeScope, accHelper, accuracy);
547575
size_t total = result.total;
576+
if (currentBitCount > 0)
577+
total += currentBitfieldAlloc;
548578
if (const Type* dt = vt.typeScope->definedType) {
549579
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
550580
if (bi.type && bi.type->classScope)

0 commit comments

Comments
 (0)