From 789c032e422ba8dc51c2c28b6b5dc23d8d24f9c1 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Sat, 4 Nov 2023 13:34:08 +0100 Subject: [PATCH] Fix #12138 FP passedByValue with anonymous union (#5611) --- lib/checkother.cpp | 10 ++++++++-- test/testother.cpp | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 87867bc77..a8adb6154 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1200,16 +1200,22 @@ static int estimateSize(const Type* type, const Settings* settings, const Symbol else cumulatedSize += size; }; - for (const Variable&var : type->classScope->varlist) { + std::set anonScopes; + for (const Variable& var : type->classScope->varlist) { int size = 0; if (var.isStatic()) continue; if (var.isPointer() || var.isReference()) size = settings->platform.sizeof_pointer; else if (var.type() && var.type()->classScope) - size = estimateSize(var.type(), settings, symbolDatabase, recursionDepth+1); + size = estimateSize(var.type(), settings, symbolDatabase, recursionDepth + 1); else if (var.valueType() && var.valueType()->type == ValueType::Type::CONTAINER) size = 3 * settings->platform.sizeof_pointer; // Just guess + else if (var.nameToken()->scope() != type->classScope && var.nameToken()->scope()->definedType) { // anonymous union + const auto ret = anonScopes.insert(var.nameToken()->scope()); + if (ret.second) + size = estimateSize(var.nameToken()->scope()->definedType, settings, symbolDatabase, recursionDepth + 1); + } else size = symbolDatabase->sizeOfType(var.typeStartToken()); diff --git a/test/testother.cpp b/test/testother.cpp index 0f20e0304..4358a5287 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2172,6 +2172,25 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 't' should be passed by const reference.\n", errout.str()); + check("struct S {\n" // #12138 + " union {\n" + " int a = 0;\n" + " int x;\n" + " };\n" + " union {\n" + " int b = 0;\n" + " int y;\n" + " };\n" + " union {\n" + " int c = 0;\n" + " int z;\n" + " };\n" + "};\n" + "void f(S s) {\n" + " if (s.x > s.y) {}\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build(); check("using ui64 = unsigned __int64;\n" "ui64 Test(ui64 one, ui64 two) { return one + two; }\n",