diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 540ec5ca5da..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; @@ -8701,12 +8700,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 +8834,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; diff --git a/test/testother.cpp b/test/testother.cpp index e285d8d8bd0..32905364a06 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", 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()