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:
parent
c185a8aae9
commit
ff38cc5c13
|
@ -1344,7 +1344,7 @@ static std::size_t estimateSize(const Type* type, const Settings* settings, cons
|
||||||
else if (i->type() && i->type()->classScope)
|
else if (i->type() && i->type()->classScope)
|
||||||
size = estimateSize(i->type(), settings, symbolDatabase, recursionDepth+1);
|
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), "> ::")))
|
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
|
else
|
||||||
size = symbolDatabase->sizeOfType(i->typeStartToken());
|
size = symbolDatabase->sizeOfType(i->typeStartToken());
|
||||||
|
|
||||||
|
@ -1385,7 +1385,7 @@ void CheckOther::checkPassByReference()
|
||||||
// Ensure that it is a large object.
|
// Ensure that it is a large object.
|
||||||
if (!var->type()->classScope)
|
if (!var->type()->classScope)
|
||||||
inconclusive = true;
|
inconclusive = true;
|
||||||
else if (estimateSize(var->type(), _settings, symbolDatabase) <= 8)
|
else if (estimateSize(var->type(), _settings, symbolDatabase) <= 2 * _settings->sizeof_pointer)
|
||||||
continue;
|
continue;
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1551,14 +1551,49 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("class X {\n"
|
check("class X {\n"
|
||||||
" uint64_t i;\n"
|
" char a[1024];\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"class Y : X {\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"
|
"};\n"
|
||||||
"void f(X x, Y y) {\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() {
|
void switchRedundantAssignmentTest() {
|
||||||
|
|
Loading…
Reference in New Issue