diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5171615ad6e..6e3d316318d 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1116,11 +1116,10 @@ static size_t accumulateStructMembers(const Scope* scope, F f) if (const ValueType* vt = var.valueType()) { if (vt->type == ValueType::Type::RECORD && vt->typeScope == scope) return 0; - total = f(total, *vt); const MathLib::bigint dim = std::accumulate(var.dimensions().cbegin(), var.dimensions().cend(), 1LL, [](MathLib::bigint i1, const Dimension& dim) { return i1 * dim.num; }); - total *= dim; + total = f(total, *vt, dim); } if (total == 0) return 0; @@ -1149,7 +1148,7 @@ static size_t getAlignOf(const ValueType& vt, const Settings& settings) return align == 0 ? 0 : bitCeil(align); } if (vt.type == ValueType::Type::RECORD && vt.typeScope) { - return accumulateStructMembers(vt.typeScope, [&](size_t max, const ValueType& vt2) { + return accumulateStructMembers(vt.typeScope, [&](size_t max, const ValueType& vt2, size_t /*dim*/) { size_t a = getAlignOf(vt2, settings); return std::max(max, a); }); @@ -1187,11 +1186,12 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings &settings) if (vt.type == ValueType::Type::LONGDOUBLE) return settings.platform.sizeof_long_double; if (vt.type == ValueType::Type::RECORD && vt.typeScope) { - size_t total = accumulateStructMembers(vt.typeScope, [&](size_t total, const ValueType& vt2) -> size_t { + size_t total = accumulateStructMembers(vt.typeScope, [&](size_t total, const ValueType& vt2, size_t dim) -> size_t { size_t n = ValueFlow::getSizeOf(vt2, settings); size_t a = getAlignOf(vt2, settings); if (n == 0 || a == 0) return 0; + n *= dim; size_t padding = (a - (total % a)) % a; return total + padding + n; }); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index ccad5a93a17..b42b05f8f7b 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1466,6 +1466,29 @@ class TestValueFlow : public TestFixture { values = tokenValues(code, "="); ASSERT_EQUALS(1U, values.size()); ASSERT_EQUALS(4LL * 2 * 10, values.back().intvalue); + + code = "struct S {\n" + " int a[10];\n" + " int b[20];\n" + " int c[30];\n" + "};\n" + "void f() {\n" + " x = sizeof(S);\n" + "}\n"; + values = tokenValues(code, "="); + ASSERT_EQUALS(1U, values.size()); + ASSERT_EQUALS(4LL * (10 + 20 + 30), values.back().intvalue); + + code = "struct S {\n" + " char c;\n" + " int a[4];\n" + "};\n" + "void f() {\n" + " x = sizeof(S);\n" + "}\n"; + values = tokenValues(code, "="); + ASSERT_EQUALS(1U, values.size()); + ASSERT_EQUALS(4LL * 5, values.back().intvalue); } void valueFlowComma()