Skip to content

Commit 8207a00

Browse files
committed
Refs #14859: Fix sizeof calculation for std::array
1 parent 49f7cd2 commit 8207a00

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
@@ -8478,7 +8478,7 @@ namespace {
84788478
}
84798479

84808480
template<class F>
8481-
static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accuracy accuracy)
8481+
static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accuracy accuracy, const Settings& settings)
84828482
{
84838483
size_t total = 0;
84848484
std::set<const Scope*> anonScopes;
@@ -8497,6 +8497,10 @@ static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accura
84978497
if (ret.second)
84988498
total = f(total, *vt, dim, bits);
84998499
}
8500+
else if (vt->container && vt->container->startPattern == "std :: array <") {
8501+
const ValueType vtElement = ValueType::parseDecl(vt->containerTypeToken, settings);
8502+
total = f(total, vtElement, dim, bits);
8503+
}
85008504
else
85018505
total = f(total, *vt, dim, bits);
85028506
}
@@ -8536,12 +8540,12 @@ static size_t getAlignOf(const ValueType& vt, const Settings& settings, ValueTyp
85368540
size_t a = getAlignOf(vt2, settings, accuracy, ValueType::SizeOf::Pointer, ++maxRecursion);
85378541
return std::max(max, a);
85388542
};
8539-
Result result = accumulateStructMembers(vt.typeScope, accHelper, accuracy);
8543+
Result result = accumulateStructMembers(vt.typeScope, accHelper, accuracy, settings);
85408544
size_t total = result.total;
85418545
if (const Type* dt = vt.typeScope->definedType) {
85428546
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const Type::BaseInfo& bi) {
85438547
if (bi.type && bi.type->classScope)
8544-
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy).total;
8548+
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy, settings).total;
85458549
return v;
85468550
});
85478551
}
@@ -8629,14 +8633,14 @@ size_t ValueType::getSizeOf( const Settings& settings, Accuracy accuracy, SizeOf
86298633
}
86308634
return typeScope->type == ScopeType::eUnion ? std::max(total, n) : total + padding + n;
86318635
};
8632-
Result result = accumulateStructMembers(typeScope, accHelper, accuracy);
8636+
Result result = accumulateStructMembers(typeScope, accHelper, accuracy, settings);
86338637
size_t total = result.total;
86348638
if (currentBitCount > 0)
86358639
total += currentBitfieldAlloc;
86368640
if (const ::Type* dt = typeScope->definedType) {
86378641
total = std::accumulate(dt->derivedFrom.begin(), dt->derivedFrom.end(), total, [&](size_t v, const ::Type::BaseInfo& bi) {
86388642
if (bi.type && bi.type->classScope)
8639-
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy).total;
8643+
v += accumulateStructMembers(bi.type->classScope, accHelper, accuracy, settings).total;
86408644
return v;
86418645
});
86428646
}

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() &&
169+
!(obj->valueType()->container && obj->valueType()->container->startPattern == "std :: array <")) { // <- TODO this is a bailout, handle enum with non-int types
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)