Skip to content

Commit 56a055d

Browse files
Refs #14859: Fix sizeof calculation for std::array (#8671)
Co-authored-by: chrchr-github <noreply@github.com>
1 parent 47d4f68 commit 56a055d

3 files changed

Lines changed: 31 additions & 7 deletions

File tree

lib/symboldatabase.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8476,7 +8476,7 @@ namespace {
84768476
}
84778477

84788478
template<class F>
8479-
static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accuracy accuracy)
8479+
static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accuracy accuracy, const Settings& settings)
84808480
{
84818481
size_t total = 0;
84828482
std::set<const Scope*> anonScopes;
@@ -8495,6 +8495,10 @@ static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accura
84958495
if (ret.second)
84968496
total = f(total, *vt, dim, bits);
84978497
}
8498+
else if (vt->container && vt->container->startPattern == "std :: array <") {
8499+
const ValueType vtElement = ValueType::parseDecl(vt->containerTypeToken, settings);
8500+
total = f(total, vtElement, dim, bits);
8501+
}
84988502
else
84998503
total = f(total, *vt, dim, bits);
85008504
}
@@ -8534,12 +8538,12 @@ static size_t getAlignOf(const ValueType& vt, const Settings& settings, ValueTyp
85348538
size_t a = getAlignOf(vt2, settings, accuracy, ValueType::SizeOf::Pointer, ++maxRecursion);
85358539
return std::max(max, a);
85368540
};
8537-
Result result = accumulateStructMembers(vt.typeScope, accHelper, accuracy);
8541+
Result result = accumulateStructMembers(vt.typeScope, accHelper, accuracy, settings);
85388542
size_t total = result.total;
85398543
if (const Type* dt = vt.typeScope->definedType) {
85408544
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
85418545
if (bi.type && bi.type->classScope)
8542-
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy).total;
8546+
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy, settings).total;
85438547
return v;
85448548
});
85458549
}
@@ -8627,14 +8631,14 @@ size_t ValueType::getSizeOf( const Settings& settings, Accuracy accuracy, SizeOf
86278631
}
86288632
return typeScope->type == ScopeType::eUnion ? std::max(total, n) : total + padding + n;
86298633
};
8630-
Result result = accumulateStructMembers(typeScope, accHelper, accuracy);
8634+
Result result = accumulateStructMembers(typeScope, accHelper, accuracy, settings);
86318635
size_t total = result.total;
86328636
if (currentBitCount > 0)
86338637
total += currentBitfieldAlloc;
86348638
if (const ::Type* dt = typeScope->definedType) {
86358639
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const ::Type::BaseInfo& bi) {
86368640
if (bi.type && bi.type->classScope)
8637-
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy).total;
8641+
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy, settings).total;
86388642
return v;
86398643
});
86408644
}

lib/vf_common.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,8 @@ namespace ValueFlow
165165
if (obj && !obj->isLiteral() && obj->valueType() &&
166166
(obj->valueType()->pointer == 0 || // <- TODO this is a bailout, abort when there are array->pointer conversions
167167
(obj->variable() && !obj->variable()->isArray())) &&
168-
!obj->valueType()->isEnum()) { // <- TODO this is a bailout, handle enum with non-int types
168+
!obj->valueType()->isEnum() && // <- TODO this is a bailout, handle enum with non-int types
169+
!(obj->valueType()->container && obj->valueType()->container->startPattern == "std :: array <")) {
169170
const auto ptrPointee = obj->valueType()->pointer > 0 ? ValueType::SizeOf::Pointer : ValueType::SizeOf::Pointee;
170171
const size_t sz = obj->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ptrPointee);
171172
if (sz) {
@@ -246,7 +247,12 @@ namespace ValueFlow
246247
if (var->type()->classScope && var->type()->classScope->enumType)
247248
size = getSizeOfType(var->type()->classScope->enumType, settings);
248249
} else if (var->valueType()) {
249-
size = var->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer);
250+
if (var->valueType()->container && var->valueType()->container->startPattern == "std :: array <") {
251+
const ValueType vtElement = ValueType::parseDecl(var->valueType()->containerTypeToken, settings);
252+
size = vtElement.getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer);
253+
}
254+
else
255+
size = var->valueType()->getSizeOf(settings, ValueType::Accuracy::ExactOrZero, ValueType::SizeOf::Pointer);
250256
} else if (!var->type()) {
251257
size = getSizeOfType(var->typeStartToken(), settings);
252258
}

test/testvalueflow.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,20 @@ class TestValueFlow : public TestFixture {
18121812
ASSERT_EQUALS(1U, values.size());
18131813
ASSERT_EQUALS(2 * settings.platform.sizeof_pointer, values.back().intvalue);
18141814
ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind);
1815+
1816+
code = "struct S { std::array<int, 3> a; };\n"
1817+
"x = sizeof(S);\n";
1818+
values = tokenValues(code, "( S");
1819+
ASSERT_EQUALS(1U, values.size());
1820+
ASSERT_EQUALS(3 * settings.platform.sizeof_int, values.back().intvalue);
1821+
ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind);
1822+
1823+
code = "std::array<int, 3> a;\n"
1824+
"x = sizeof(a);\n";
1825+
values = tokenValues(code, "( a");
1826+
ASSERT_EQUALS(1U, values.size());
1827+
ASSERT_EQUALS(3 * settings.platform.sizeof_int, values.back().intvalue);
1828+
ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind);
18151829
}
18161830

18171831
void valueFlowComma()

0 commit comments

Comments
 (0)