parent
bbaa7be901
commit
c2d5aef435
|
@ -1227,104 +1227,6 @@ static int estimateSize(const Type* type, const Settings* settings, const Symbol
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isConstRangeBasedFor(const Token* tok) {
|
|
||||||
if (astIsRangeBasedForDecl(tok)) {
|
|
||||||
const Variable* loopVar = tok->astParent()->astOperand1()->variable();
|
|
||||||
return loopVar && (!loopVar->isReference() || loopVar->isConst());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool canBeConst(const Variable *var, const Settings* settings)
|
|
||||||
{
|
|
||||||
if (!var->scope())
|
|
||||||
return false;
|
|
||||||
{
|
|
||||||
// check initializer list. If variable is moved from it can't be const.
|
|
||||||
const Function* func_scope = var->scope()->function;
|
|
||||||
if (func_scope && func_scope->type == Function::Type::eConstructor) {
|
|
||||||
//could be initialized in initializer list
|
|
||||||
const Token* init = func_scope->arg->link()->next();
|
|
||||||
if (init->str() == "noexcept") {
|
|
||||||
init = init->next();
|
|
||||||
if (init->link())
|
|
||||||
init = init->link()->next();
|
|
||||||
}
|
|
||||||
if (init->str() == ":") {
|
|
||||||
for (const Token* tok2 = func_scope->arg->link()->next()->next(); tok2 != var->scope()->bodyStart; tok2 = tok2->next()) {
|
|
||||||
if (tok2->varId() != var->declarationId())
|
|
||||||
continue;
|
|
||||||
const Token* parent = tok2->astParent();
|
|
||||||
if (parent && Token::simpleMatch(parent->previous(), "move ("))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const Token* tok2 = var->scope()->bodyStart; tok2 != var->scope()->bodyEnd; tok2 = tok2->next()) {
|
|
||||||
if (tok2->varId() != var->declarationId())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const Token* parent = tok2->astParent();
|
|
||||||
while (Token::simpleMatch(parent, "["))
|
|
||||||
parent = parent->astParent();
|
|
||||||
if (!parent)
|
|
||||||
continue;
|
|
||||||
if (Token::simpleMatch(tok2->next(), ";") && tok2->next()->isSplittedVarDeclEq()) {
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
tok2 = Token::findsimplematch(tok2, ";");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parent->str() == "<<" || isLikelyStreamRead(true, parent)) {
|
|
||||||
if (parent->str() == "<<" && parent->astOperand1() == tok2)
|
|
||||||
return false;
|
|
||||||
if (parent->str() == ">>" && parent->astOperand2() == tok2)
|
|
||||||
return false;
|
|
||||||
} else if (parent->str() == "," || parent->str() == "(") { // function argument
|
|
||||||
int argNr = -1;
|
|
||||||
const Token* functionTok = getTokenArgumentFunction(tok2, argNr);
|
|
||||||
if (!functionTok)
|
|
||||||
return false;
|
|
||||||
const Function* tokFunction = functionTok->function();
|
|
||||||
if (tokFunction) {
|
|
||||||
const Variable* argVar = tokFunction->getArgumentVar(argNr);
|
|
||||||
if (!argVar || (!argVar->isConst() && argVar->isReference()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (!settings->library.isFunctionConst(functionTok))
|
|
||||||
return false;
|
|
||||||
} else if (parent->isUnaryOp("&")) {
|
|
||||||
// TODO: check how pointer is used
|
|
||||||
return false;
|
|
||||||
} else if (parent->isConstOp() ||
|
|
||||||
(parent->astOperand2() && settings->library.isFunctionConst(parent->astOperand2())))
|
|
||||||
continue;
|
|
||||||
else if (parent->isAssignmentOp()) {
|
|
||||||
const Token* assignee = parent->astOperand1();
|
|
||||||
while (Token::simpleMatch(assignee, "["))
|
|
||||||
assignee = assignee->astOperand1();
|
|
||||||
if (assignee == tok2)
|
|
||||||
return false;
|
|
||||||
const Variable* assignedVar = assignee ? assignee->variable() : nullptr;
|
|
||||||
if (assignedVar &&
|
|
||||||
!assignedVar->isConst() &&
|
|
||||||
assignedVar->isReference() &&
|
|
||||||
assignedVar->nameToken() == parent->astOperand1())
|
|
||||||
return false;
|
|
||||||
} else if (Token::Match(tok2, "%var% . %name% (")) {
|
|
||||||
const Function* func = tok2->tokAt(2)->function();
|
|
||||||
if (func && (func->isConst() || func->isStatic()))
|
|
||||||
continue;
|
|
||||||
return false;
|
|
||||||
} else if (isConstRangeBasedFor(tok2))
|
|
||||||
continue;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::checkPassByReference()
|
void CheckOther::checkPassByReference()
|
||||||
{
|
{
|
||||||
if (!mSettings->severity.isEnabled(Severity::performance) || mTokenizer->isC())
|
if (!mSettings->severity.isEnabled(Severity::performance) || mTokenizer->isC())
|
||||||
|
@ -1374,7 +1276,7 @@ void CheckOther::checkPassByReference()
|
||||||
if (!var->scope() || var->scope()->function->isImplicitlyVirtual())
|
if (!var->scope() || var->scope()->function->isImplicitlyVirtual())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (canBeConst(var, mSettings)) {
|
if (!isVariableChanged(var, mSettings, mTokenizer->isCPP())) {
|
||||||
passedByValueError(var, inconclusive);
|
passedByValueError(var, inconclusive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2939,7 +2841,9 @@ void CheckOther::checkRedundantCopy()
|
||||||
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
||||||
|
|
||||||
for (const Variable* var : symbolDatabase->variableList()) {
|
for (const Variable* var : symbolDatabase->variableList()) {
|
||||||
if (!var || var->isReference() || (!var->isConst() && !canBeConst(var, mSettings)) || var->isPointer() || (!var->type() && !var->isStlType())) // bailout if var is of standard type, if it is a pointer or non-const
|
if (!var || var->isReference() || var->isPointer() ||
|
||||||
|
(!var->type() && !var->isStlType()) || // bailout if var is of standard type, if it is a pointer or non-const
|
||||||
|
(!var->isConst() && isVariableChanged(var, mSettings, mTokenizer->isCPP())))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token* startTok = var->nameToken();
|
const Token* startTok = var->nameToken();
|
||||||
|
|
|
@ -284,7 +284,7 @@ bool Path::isDirectory(const std::string &path)
|
||||||
return file_type(path) == S_IFDIR;
|
return file_type(path) == S_IFDIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Path::join(std::string path1, std::string path2) {
|
std::string Path::join(const std::string& path1, const std::string& path2) {
|
||||||
if (path1.empty() || path2.empty())
|
if (path1.empty() || path2.empty())
|
||||||
return path1 + path2;
|
return path1 + path2;
|
||||||
if (path2.front() == '/')
|
if (path2.front() == '/')
|
||||||
|
|
|
@ -197,7 +197,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* join 2 paths with '/' separators
|
* join 2 paths with '/' separators
|
||||||
*/
|
*/
|
||||||
static std::string join(std::string path1, std::string path2);
|
static std::string join(const std::string& path1, const std::string& path2);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -4497,7 +4497,7 @@ void getline()
|
||||||
in.close();
|
in.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO cppcheck-suppress passedByValue
|
// cppcheck-suppress passedByValue
|
||||||
void stream_write(std::ofstream& s, std::vector<char> v) {
|
void stream_write(std::ofstream& s, std::vector<char> v) {
|
||||||
if (v.empty()) {}
|
if (v.empty()) {}
|
||||||
s.write(v.data(), v.size());
|
s.write(v.data(), v.size());
|
||||||
|
|
|
@ -2167,6 +2167,11 @@ private:
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (performance) Function parameter 'v' should be passed by const reference.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (performance) Function parameter 'v' should be passed by const reference.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f(const std::string& s, std::string t) {\n" // #12083
|
||||||
|
" const std::string& v = !s.empty() ? s : t;\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 't' should be passed by const reference.\n", errout.str());
|
||||||
|
|
||||||
Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build();
|
Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build();
|
||||||
check("using ui64 = unsigned __int64;\n"
|
check("using ui64 = unsigned __int64;\n"
|
||||||
"ui64 Test(ui64 one, ui64 two) { return one + two; }\n",
|
"ui64 Test(ui64 one, ui64 two) { return one + two; }\n",
|
||||||
|
@ -2201,7 +2206,9 @@ private:
|
||||||
check("void f(std::string str) {\n"
|
check("void f(std::string str) {\n"
|
||||||
" std::string& s2 = str;\n"
|
" std::string& s2 = str;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 's2' can be declared as reference to const\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'str' should be passed by const reference.\n"
|
||||||
|
"[test.cpp:2]: (style) Variable 's2' can be declared as reference to const\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
check("void f(std::string str) {\n"
|
check("void f(std::string str) {\n"
|
||||||
" const std::string& s2 = str;\n"
|
" const std::string& s2 = str;\n"
|
||||||
|
@ -2354,7 +2361,9 @@ private:
|
||||||
" int& i = x[0];\n"
|
" int& i = x[0];\n"
|
||||||
" return i;\n"
|
" return i;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Variable 'i' can be declared as reference to const\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'x' should be passed by const reference.\n"
|
||||||
|
"[test.cpp:2]: (style) Variable 'i' can be declared as reference to const\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
check("int f(std::vector<int>& x) {\n"
|
check("int f(std::vector<int>& x) {\n"
|
||||||
" return x[0];\n"
|
" return x[0];\n"
|
||||||
|
@ -2371,7 +2380,7 @@ private:
|
||||||
" static int& i = x[0];\n"
|
" static int& i = x[0];\n"
|
||||||
" return i;\n"
|
" return i;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("[test.cpp:1]: (performance) Function parameter 'x' should be passed by const reference.\n", errout.str());
|
||||||
|
|
||||||
check("int f(std::vector<int> x) {\n"
|
check("int f(std::vector<int> x) {\n"
|
||||||
" int& i = x[0];\n"
|
" int& i = x[0];\n"
|
||||||
|
|
Loading…
Reference in New Issue