Set struct size cutoff in passedByValue check to 2*sizeof_pointer

Struct arguments are either pushed to the stack or passed in the
registers. Since both methods operate on machine words it is logical to
tie the maximum size of a struct argument that doesn't trigger
passedByValue diagnostic to the size of the machine word.

Also guessed size of STL classes is set to 3*sizeof_pointer, this better
represents reality and ensures that structs containing them will still
trigger passedByValue.
This commit is contained in:
Stas Cymbalov 2017-06-06 08:48:11 +02:00 committed by Daniel Marjamäki
parent c185a8aae9
commit ff38cc5c13
2 changed files with 40 additions and 5 deletions

View File

@ -1344,7 +1344,7 @@ static std::size_t estimateSize(const Type* type, const Settings* settings, cons
else if (i->type() && i->type()->classScope)
size = estimateSize(i->type(), settings, symbolDatabase, recursionDepth+1);
else if (i->isStlStringType() || (i->isStlType() && Token::Match(i->typeStartToken(), "std :: %type% <") && !Token::simpleMatch(i->typeStartToken()->linkAt(3), "> ::")))
size = 16; // Just guess
size = 3 * settings->sizeof_pointer; // Just guess
else
size = symbolDatabase->sizeOfType(i->typeStartToken());
@ -1385,7 +1385,7 @@ void CheckOther::checkPassByReference()
// Ensure that it is a large object.
if (!var->type()->classScope)
inconclusive = true;
else if (estimateSize(var->type(), _settings, symbolDatabase) <= 8)
else if (estimateSize(var->type(), _settings, symbolDatabase) <= 2 * _settings->sizeof_pointer)
continue;
} else
continue;

View File

@ -1551,14 +1551,49 @@ private:
ASSERT_EQUALS("", errout.str());
check("class X {\n"
" uint64_t i;\n"
" char a[1024];\n"
"};\n"
"class Y : X {\n"
" uint64_t j;\n"
" char b;\n"
"};\n"
"void f(Y y) {\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (performance) Function parameter 'y' should be passed by reference.\n", errout.str());
check("class X {\n"
" void* a;\n"
" void* b;\n"
"};\n"
"class Y {\n"
" void* a;\n"
" void* b;\n"
" char c;\n"
"};\n"
"void f(X x, Y y) {\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (performance) Function parameter 'y' should be passed by reference.\n", errout.str());
ASSERT_EQUALS("[test.cpp:10]: (performance) Function parameter 'y' should be passed by reference.\n", errout.str());
const auto originalPlatform = _settings.platformType;
_settings.platform(cppcheck::Platform::Unix32);
check("class X {\n"
" uint64_t a;\n"
" uint64_t b;\n"
"};\n"
"void f(X x) {\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (performance) Function parameter 'x' should be passed by reference.\n", errout.str());
_settings.platform(cppcheck::Platform::Unix64);
check("class X {\n"
" uint64_t a;\n"
" uint64_t b;\n"
"};\n"
"void f(X x) {\n"
"}");
ASSERT_EQUALS("", errout.str());
_settings.platform(originalPlatform);
}
void switchRedundantAssignmentTest() {