Skip to content

Commit 2bd0440

Browse files
committed
account for bitfields when computing struct size
1 parent 3181f13 commit 2bd0440

1 file changed

Lines changed: 28 additions & 5 deletions

File tree

lib/valueflow.cpp

Lines changed: 28 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,39 @@ 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 {
538541
size_t n = ValueFlow::getSizeOf(vt2, settings,accuracy, ++maxRecursion);
539542
size_t a = getAlignOf(vt2, settings, accuracy);
543+
if (bits > 0) {
544+
size_t ret = total;
545+
if (currentBitfieldAlloc == 0) {
546+
currentBitfieldAlloc = n;
547+
currentBitCount = 0;
548+
} else if (currentBitCount + bits > settings.platform.char_bit * currentBitfieldAlloc) {
549+
ret += currentBitfieldAlloc;
550+
currentBitfieldAlloc = n;
551+
currentBitCount = 0;
552+
}
553+
currentBitCount += bits;
554+
return ret;
555+
}
540556
if (n == 0 || a == 0)
541557
return accuracy == Accuracy::ExactOrZero ? 0 : total;
542558
n *= dim;
543559
size_t padding = (a - (total % a)) % a;
560+
if (currentBitCount > 0) {
561+
n += currentBitfieldAlloc;
562+
currentBitfieldAlloc = 0;
563+
currentBitCount = 0;
564+
}
544565
return vt.typeScope->type == ScopeType::eUnion ? std::max(total, n) : total + padding + n;
545566
};
546567
Result result = accumulateStructMembers(vt.typeScope, accHelper, accuracy);
547568
size_t total = result.total;
569+
if (currentBitCount > 0)
570+
total += currentBitfieldAlloc;
548571
if (const Type* dt = vt.typeScope->definedType) {
549572
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
550573
if (bi.type && bi.type->classScope)

0 commit comments

Comments
 (0)