From 8e67edd215c2130860336e3f4cb41b14c688e86c Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 26 Oct 2026 11:04:26 +0100 Subject: [PATCH 1/7] Update symboldatabase.cpp --- lib/symboldatabase.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 540ec5ca5da..6af6e6f4d93 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -8701,12 +8701,7 @@ static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accura const MathLib::bigint dim = std::accumulate(var.dimensions().cbegin(), var.dimensions().cend(), MathLib::bigint(1), [](MathLib::bigint i1, const Dimension& dim) { return i1 * dim.num; }); - if (var.nameToken()->scope() != scope && var.nameToken()->scope()->definedType) { // anonymous union - const auto ret = anonScopes.insert(var.nameToken()->scope()); - if (ret.second) - total = f(total, *vt, dim, bits); - } - else if (vt->container && vt->container->startPattern == "std :: array <") { + if (vt->container && vt->container->startPattern == "std :: array <") { const ValueType vtElement = ValueType::parseDecl(vt->containerTypeToken, settings); total = f(total, vtElement, dim, bits); } @@ -8840,7 +8835,8 @@ size_t ValueType::getSizeOf( const Settings& settings, Accuracy accuracy, SizeOf currentBitfieldAlloc = 0; currentBitCount = 0; } - return typeScope->type == ScopeType::eUnion ? std::max(total, n) : total + padding + n; + const bool isUnion = typeScope->type == ScopeType::eUnion || (vt2.typeScope && vt2.typeScope->nestedIn->type == ScopeType::eUnion && vt2.typeScope->nestedIn->className.empty()); + return isUnion ? std::max(total, n) : total + padding + n; }; Result result = accumulateStructMembers(typeScope, accHelper, accuracy, settings); size_t total = result.total; From 183fa191a74b0e03e01f453d7a327a6e124dc0e2 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 26 Oct 2026 11:05:17 +0100 Subject: [PATCH 2/7] Update testvalueflow.cpp --- test/testvalueflow.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 3609bf2aee2..e8b55bf6aae 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1862,6 +1862,20 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS(1U, values.size()); ASSERT_EQUALS(settings.platform.sizeof_int, values.back().intvalue); ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind); + + code = "struct S {\n" + " union {\n" + " int i;\n" + " struct {\n" + " char a[24];\n" + " } x;\n" + " };\n" + "};\n" + "int f() { return sizeof(S); }\n"; + values = tokenValues(code, "( S"); + ASSERT_EQUALS(1U, values.size()); + ASSERT_EQUALS(24, values.back().intvalue); + ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind); } void valueFlowComma() From 918547b7102eac9de92ffa17c5fdcc8df9c067a9 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 26 Oct 2026 11:06:07 +0100 Subject: [PATCH 3/7] Update testother.cpp --- test/testother.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/testother.cpp b/test/testother.cpp index e285d8d8bd0..beadd9a7189 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2787,6 +2787,17 @@ class TestOther : public TestFixture { "}\n"); ASSERT_EQUALS("", errout_str()); + check("struct S {\n" // #15130 + " union {\n" + " int i;\n" + " struct {\n" + " char a[24];\n" + " } x;\n" + " };\n" + "};\n" + "int f(S s) { return s.i; }\n"); + ASSERT_EQUALS("[test.cpp:9:9]: (performance) Function parameter 's' should be passed by const reference. [passedByValue]\n", errout_str()); + /*const*/ Settings settingsWin64 = settingsBuilder().platform(Platform::Type::Win64).build(); check("using ui64 = unsigned __int64;\n" "ui64 Test(ui64 one, ui64 two) { return one + two; }\n", From 26381dffa3d8d8ed2a46e580afde8c659e182a9c Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 26 Oct 2026 11:39:31 +0100 Subject: [PATCH 4/7] Update testother.cpp --- test/testother.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/testother.cpp b/test/testother.cpp index beadd9a7189..32905364a06 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2788,14 +2788,14 @@ class TestOther : public TestFixture { ASSERT_EQUALS("", errout_str()); check("struct S {\n" // #15130 - " union {\n" - " int i;\n" - " struct {\n" - " char a[24];\n" - " } x;\n" - " };\n" - "};\n" - "int f(S s) { return s.i; }\n"); + " union {\n" + " int i;\n" + " struct {\n" + " char a[24];\n" + " } x;\n" + " };\n" + "};\n" + "int f(S s) { return s.i; }\n"); ASSERT_EQUALS("[test.cpp:9:9]: (performance) Function parameter 's' should be passed by const reference. [passedByValue]\n", errout_str()); /*const*/ Settings settingsWin64 = settingsBuilder().platform(Platform::Type::Win64).build(); From c594e9b063e0545d0ac200335d72f33d8d16dcb4 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 26 Oct 2026 13:34:58 +0100 Subject: [PATCH 5/7] Update symboldatabase.cpp --- lib/symboldatabase.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 6af6e6f4d93..3a4b12c24e0 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -8690,7 +8690,6 @@ template static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accuracy accuracy, const Settings& settings) { size_t total = 0; - std::set anonScopes; for (const Variable& var : scope->varlist) { if (var.isStatic()) continue; From 15045b27e5a20a607207c81389b605297a3165b9 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 4 Nov 2026 14:58:38 +0100 Subject: [PATCH 6/7] Update symboldatabase.cpp [skip ci] --- lib/symboldatabase.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3a4b12c24e0..8413d824e29 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -8702,10 +8702,10 @@ static Result accumulateStructMembers(const Scope* scope, F f, ValueType::Accura }); if (vt->container && vt->container->startPattern == "std :: array <") { const ValueType vtElement = ValueType::parseDecl(vt->containerTypeToken, settings); - total = f(total, vtElement, dim, bits); + total = f(total, vtElement, dim, bits, /*isAnonUnion*/ false); } else - total = f(total, *vt, dim, bits); + total = f(total, *vt, dim, bits, var.nameToken()->scope() != scope); } if (accuracy == ValueType::Accuracy::ExactOrZero && total == 0 && bits == -1) return {0, false}; @@ -8739,7 +8739,7 @@ static size_t getAlignOf(const ValueType& vt, const Settings& settings, ValueTyp return align == 0 ? 0 : bitCeil(align); } if (vt.type == ValueType::Type::RECORD && vt.typeScope) { - auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/, MathLib::bigint /*bits*/) { + auto accHelper = [&](size_t max, const ValueType& vt2, size_t /*dim*/, MathLib::bigint /*bits*/, bool /*isAnonUnion*/) { size_t a = getAlignOf(vt2, settings, accuracy, ValueType::SizeOf::Pointer, ++maxRecursion); return std::max(max, a); }; @@ -8791,7 +8791,7 @@ size_t ValueType::getSizeOf( const Settings& settings, Accuracy accuracy, SizeOf if (type == ValueType::Type::RECORD && typeScope) { size_t currentBitCount = 0; size_t currentBitfieldAlloc = 0; - auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim, MathLib::bigint nBits) -> size_t { + auto accHelper = [&](size_t total, const ValueType& vt2, size_t dim, MathLib::bigint nBits, bool isAnonUnion) -> size_t { const size_t charBit = settings.platform.char_bit; size_t n = vt2.getSizeOf(settings, accuracy, SizeOf::Pointer, ++maxRecursion); size_t a = getAlignOf(vt2, settings, accuracy, SizeOf::Pointer); @@ -8834,7 +8834,7 @@ size_t ValueType::getSizeOf( const Settings& settings, Accuracy accuracy, SizeOf currentBitfieldAlloc = 0; currentBitCount = 0; } - const bool isUnion = typeScope->type == ScopeType::eUnion || (vt2.typeScope && vt2.typeScope->nestedIn->type == ScopeType::eUnion && vt2.typeScope->nestedIn->className.empty()); + const bool isUnion = isAnonUnion || typeScope->type == ScopeType::eUnion; return isUnion ? std::max(total, n) : total + padding + n; }; Result result = accumulateStructMembers(typeScope, accHelper, accuracy, settings); From bcaca69c7c8b91f44274e8076b086648d633f8bd Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 4 Nov 2026 14:59:28 +0100 Subject: [PATCH 7/7] Update testvalueflow.cpp --- test/testvalueflow.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index e8b55bf6aae..7a18f7cd3e5 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1876,6 +1876,18 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS(1U, values.size()); ASSERT_EQUALS(24, values.back().intvalue); ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind); + + code = "struct S {\n" + " union {\n" + " int i;\n" + " double d;\n" + " };\n" + "};\n" + "int f() { return sizeof(S); }\n"; + values = tokenValues(code, "( S"); + ASSERT_EQUALS(1U, values.size()); + ASSERT_EQUALS(settings.platform.sizeof_double, values.back().intvalue); + ASSERT_EQUALS_ENUM(ValueFlow::Value::ValueKind::Known, values.back().valueKind); } void valueFlowComma()