Skip to content

Commit 94993fe

Browse files
committed
account for bitfields when computing struct size
1 parent e006e02 commit 94993fe

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
@@ -433,6 +433,7 @@ static size_t accumulateStructMembers(const Scope* scope, F f)
433433
for (const Variable& var : scope->varlist) {
434434
if (var.isStatic())
435435
continue;
436+
const size_t bits = var.nameToken()->bits();
436437
if (const ValueType* vt = var.valueType()) {
437438
if (vt->type == ValueType::Type::RECORD && vt->typeScope == scope)
438439
return 0;
@@ -442,12 +443,12 @@ static size_t accumulateStructMembers(const Scope* scope, F f)
442443
if (var.nameToken()->scope() != scope && var.nameToken()->scope()->definedType) { // anonymous union
443444
const auto ret = anonScopes.insert(var.nameToken()->scope());
444445
if (ret.second)
445-
total = f(total, *vt, dim);
446+
total = f(total, *vt, dim, bits);
446447
}
447448
else
448-
total = f(total, *vt, dim);
449+
total = f(total, *vt, dim, bits);
449450
}
450-
if (total == 0)
451+
if (total == 0 && bits == 0)
451452
return 0;
452453
}
453454
return total;
@@ -478,7 +479,7 @@ static size_t getAlignOf(const ValueType& vt, const Settings& settings, int maxR
478479
return align == 0 ? 0 : bitCeil(align);
479480
}
480481
if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
481-
auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/) {
482+
auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/, size_t /*bits*/) {
482483
size_t a = getAlignOf(vt2, settings, ++maxRecursion);
483484
return std::max(max, a);
484485
};
@@ -526,16 +527,38 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int m
526527
if (vt.type == ValueType::Type::CONTAINER)
527528
return 3 * settings.platform.sizeof_pointer; // Just guess
528529
if (vt.type == ValueType::Type::RECORD && vt.typeScope) {
529-
auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim) -> size_t {
530+
size_t currentBitCount = 0;
531+
size_t currentBitfieldAlloc = 0;
532+
auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim, size_t bits) -> size_t {
530533
size_t n = ValueFlow::getSizeOf(vt2, settings, ++maxRecursion);
531534
size_t a = getAlignOf(vt2, settings);
535+
if (bits > 0) {
536+
size_t ret = total;
537+
if (currentBitfieldAlloc == 0) {
538+
currentBitfieldAlloc = n;
539+
currentBitCount = 0;
540+
} else if (currentBitCount + bits > 8 * currentBitfieldAlloc) {
541+
ret += currentBitfieldAlloc;
542+
currentBitfieldAlloc = n;
543+
currentBitCount = 0;
544+
}
545+
currentBitCount += bits;
546+
return ret;
547+
}
532548
if (n == 0 || a == 0)
533549
return 0;
534550
n *= dim;
535551
size_t padding = (a - (total % a)) % a;
552+
if (currentBitCount > 0) {
553+
n += currentBitfieldAlloc;
554+
currentBitfieldAlloc = 0;
555+
currentBitCount = 0;
556+
}
536557
return vt.typeScope->type == ScopeType::eUnion ? std::max(total, n) : total + padding + n;
537558
};
538559
size_t total = accumulateStructMembers(vt.typeScope, accHelper);
560+
if (currentBitCount > 0)
561+
total += currentBitfieldAlloc;
539562
if (const Type* dt = vt.typeScope->definedType) {
540563
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
541564
if (bi.type && bi.type->classScope)

0 commit comments

Comments
 (0)