@@ -424,9 +424,16 @@ void ValueFlow::combineValueProperties(const ValueFlow::Value &value1, const Val
424424 result.path = value1.path ;
425425}
426426
427+ namespace {
428+ struct Result
429+ {
430+ size_t total;
431+ bool success;
432+ };
433+ }
427434
428435template <class F >
429- static size_t accumulateStructMembers (const Scope* scope, F f)
436+ static Result accumulateStructMembers (const Scope* scope, F f, ValueFlow::Accuracy accuracy )
430437{
431438 size_t total = 0 ;
432439 std::set<const Scope*> anonScopes;
@@ -435,7 +442,7 @@ static size_t accumulateStructMembers(const Scope* scope, F f)
435442 continue ;
436443 if (const ValueType* vt = var.valueType ()) {
437444 if (vt->type == ValueType::Type::RECORD && vt->typeScope == scope)
438- return 0 ;
445+ return { 0 , false } ;
439446 const MathLib::bigint dim = std::accumulate (var.dimensions ().cbegin (), var.dimensions ().cend (), 1LL , [](MathLib::bigint i1, const Dimension& dim) {
440447 return i1 * dim.num ;
441448 });
@@ -447,10 +454,10 @@ static size_t accumulateStructMembers(const Scope* scope, F f)
447454 else
448455 total = f (total, *vt, dim);
449456 }
450- if (total == 0 )
451- return 0 ;
457+ if (accuracy == ValueFlow::Accuracy::ExactOrZero && total == 0 )
458+ return { 0 , false } ;
452459 }
453- return total;
460+ return { total, true } ;
454461}
455462
456463static size_t bitCeil (size_t x)
@@ -467,37 +474,38 @@ static size_t bitCeil(size_t x)
467474 return x + 1 ;
468475}
469476
470- static size_t getAlignOf (const ValueType& vt, const Settings& settings, int maxRecursion = 0 )
477+ static size_t getAlignOf (const ValueType& vt, const Settings& settings, ValueFlow::Accuracy accuracy, int maxRecursion = 0 )
471478{
472479 if (maxRecursion == settings.vfOptions .maxAlignOfRecursion ) {
473480 // TODO: add bailout message
474481 return 0 ;
475482 }
476483 if (vt.pointer || vt.reference != Reference::None || vt.isPrimitive ()) {
477- auto align = ValueFlow::getSizeOf (vt, settings);
484+ auto align = ValueFlow::getSizeOf (vt, settings, accuracy );
478485 return align == 0 ? 0 : bitCeil (align);
479486 }
480487 if (vt.type == ValueType::Type::RECORD && vt.typeScope ) {
481488 auto accHelper = [&](size_t max, const ValueType& vt2, size_t /* dim*/ ) {
482- size_t a = getAlignOf (vt2, settings, ++maxRecursion);
489+ size_t a = getAlignOf (vt2, settings, accuracy, ++maxRecursion);
483490 return std::max (max, a);
484491 };
485- size_t total = 0 ;
492+ Result result = accumulateStructMembers (vt.typeScope , accHelper, accuracy);
493+ size_t total = result.total ;
486494 if (const Type* dt = vt.typeScope ->definedType ) {
487495 total = std::accumulate (dt->derivedFrom .begin (), dt->derivedFrom .end (), total, [&](size_t v, const Type::BaseInfo& bi) {
488496 if (bi.type && bi.type ->classScope )
489- v += accumulateStructMembers (bi.type ->classScope , accHelper) ;
497+ v += accumulateStructMembers (bi.type ->classScope , accHelper, accuracy). total ;
490498 return v;
491499 });
492500 }
493- return total + accumulateStructMembers (vt. typeScope , accHelper) ;
501+ return result. success ? std::max< size_t >( 1 , total) : total ;
494502 }
495503 if (vt.type == ValueType::Type::CONTAINER)
496504 return settings.platform .sizeof_pointer ; // Just guess
497505 return 0 ;
498506}
499507
500- size_t ValueFlow::getSizeOf (const ValueType &vt, const Settings &settings, int maxRecursion)
508+ size_t ValueFlow::getSizeOf (const ValueType &vt, const Settings &settings, Accuracy accuracy, int maxRecursion)
501509{
502510 if (maxRecursion == settings.vfOptions .maxSizeOfRecursion ) {
503511 // TODO: add bailout message
@@ -527,27 +535,29 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings, int m
527535 return 3 * settings.platform .sizeof_pointer ; // Just guess
528536 if (vt.type == ValueType::Type::RECORD && vt.typeScope ) {
529537 auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim) -> size_t {
530- size_t n = ValueFlow::getSizeOf (vt2, settings, ++maxRecursion);
531- size_t a = getAlignOf (vt2, settings);
538+ size_t n = ValueFlow::getSizeOf (vt2, settings,accuracy, ++maxRecursion);
539+ size_t a = getAlignOf (vt2, settings, accuracy );
532540 if (n == 0 || a == 0 )
533- return 0 ;
541+ return accuracy == Accuracy::ExactOrZero ? 0 : total ;
534542 n *= dim;
535543 size_t padding = (a - (total % a)) % a;
536544 return vt.typeScope ->type == ScopeType::eUnion ? std::max (total, n) : total + padding + n;
537545 };
538- size_t total = accumulateStructMembers (vt.typeScope , accHelper);
546+ Result result = accumulateStructMembers (vt.typeScope , accHelper, accuracy);
547+ size_t total = result.total ;
539548 if (const Type* dt = vt.typeScope ->definedType ) {
540549 total = std::accumulate (dt->derivedFrom .begin (), dt->derivedFrom .end (), total, [&](size_t v, const Type::BaseInfo& bi) {
541550 if (bi.type && bi.type ->classScope )
542- v += accumulateStructMembers (bi.type ->classScope , accHelper) ;
551+ v += accumulateStructMembers (bi.type ->classScope , accHelper, accuracy). total ;
543552 return v;
544553 });
545554 }
546- if (total == 0 )
555+ if (accuracy == Accuracy::ExactOrZero && total == 0 && !result. success )
547556 return 0 ;
548- size_t align = getAlignOf (vt, settings);
557+ total = std::max (size_t {1 }, total);
558+ size_t align = getAlignOf (vt, settings, accuracy);
549559 if (align == 0 )
550- return 0 ;
560+ return accuracy == Accuracy::ExactOrZero ? 0 : total ;
551561 total += (align - (total % align)) % align;
552562 return total;
553563 }
@@ -3610,8 +3620,8 @@ static bool isTruncated(const ValueType* src, const ValueType* dst, const Settin
36103620 if (src->smartPointer && dst->smartPointer )
36113621 return false ;
36123622 if ((src->isIntegral () && dst->isIntegral ()) || (src->isFloat () && dst->isFloat ())) {
3613- const size_t srcSize = ValueFlow::getSizeOf (*src, settings);
3614- const size_t dstSize = ValueFlow::getSizeOf (*dst, settings);
3623+ const size_t srcSize = ValueFlow::getSizeOf (*src, settings, ValueFlow::Accuracy::LowerBound );
3624+ const size_t dstSize = ValueFlow::getSizeOf (*dst, settings, ValueFlow::Accuracy::LowerBound );
36153625 if (srcSize > dstSize)
36163626 return true ;
36173627 if (srcSize == dstSize && src->sign != dst->sign )
@@ -4134,10 +4144,10 @@ static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> va
41344144 if (!dst || !dst->isIntegral ())
41354145 return values;
41364146
4137- const size_t sz = ValueFlow::getSizeOf (*dst, settings);
4147+ const size_t sz = ValueFlow::getSizeOf (*dst, settings, ValueFlow::Accuracy::ExactOrZero );
41384148
41394149 if (src) {
4140- const size_t osz = ValueFlow::getSizeOf (*src, settings);
4150+ const size_t osz = ValueFlow::getSizeOf (*src, settings, ValueFlow::Accuracy::ExactOrZero );
41414151 if (osz >= sz && dst->sign == ValueType::Sign::SIGNED && src->sign == ValueType::Sign::UNSIGNED) {
41424152 values.remove_if ([&](const ValueFlow::Value& value) {
41434153 if (!value.isIntValue ())
0 commit comments