* Fix remainig example from #11599 * Fix FP, new warnings * More warnings * Use getTokenArgumentFunction() * Fix crash * Fix #11646 constParameter not reported with "const * const" parameter * Fix test * Fix new warnings * Add suppression * Add const, fix suppression
This commit is contained in:
parent
8043930a0f
commit
ab24e3a3c8
|
@ -2409,9 +2409,6 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti
|
||||||
if (indirect > 0) {
|
if (indirect > 0) {
|
||||||
if (arg->isPointer() && !(arg->valueType() && arg->valueType()->isConst(indirect)))
|
if (arg->isPointer() && !(arg->valueType() && arg->valueType()->isConst(indirect)))
|
||||||
return true;
|
return true;
|
||||||
// If const is applied to the pointer, then the value can still be modified
|
|
||||||
if (Token::simpleMatch(arg->typeEndToken(), "* const"))
|
|
||||||
return true;
|
|
||||||
if (arg->isArray() || (!arg->isPointer() && (!arg->valueType() || arg->valueType()->type == ValueType::UNKNOWN_TYPE)))
|
if (arg->isArray() || (!arg->isPointer() && (!arg->valueType() || arg->valueType()->type == ValueType::UNKNOWN_TYPE)))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1391,14 +1391,6 @@ static bool isVariableMutableInInitializer(const Token* start, const Token * end
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Token* isFuncArg(const Token* tok) {
|
|
||||||
while (Token::simpleMatch(tok, ","))
|
|
||||||
tok = tok->astParent();
|
|
||||||
if (Token::simpleMatch(tok, "(") && Token::Match(tok->astOperand1(), "%name% ("))
|
|
||||||
return tok->astOperand1();
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckOther::checkConstVariable()
|
void CheckOther::checkConstVariable()
|
||||||
{
|
{
|
||||||
if (!mSettings->severity.isEnabled(Severity::style) || mTokenizer->isC())
|
if (!mSettings->severity.isEnabled(Severity::style) || mTokenizer->isC())
|
||||||
|
@ -1481,7 +1473,8 @@ void CheckOther::checkConstVariable()
|
||||||
}
|
}
|
||||||
if (tok->isUnaryOp("&") && Token::Match(tok, "& %varid%", var->declarationId())) {
|
if (tok->isUnaryOp("&") && Token::Match(tok, "& %varid%", var->declarationId())) {
|
||||||
const Token* opTok = tok->astParent();
|
const Token* opTok = tok->astParent();
|
||||||
if (opTok->isComparisonOp() || opTok->isAssignmentOp() || opTok->isCalculation()) {
|
int argn = -1;
|
||||||
|
if (opTok && (opTok->isComparisonOp() || opTok->isAssignmentOp() || opTok->isCalculation())) {
|
||||||
if (opTok->isComparisonOp() || opTok->isCalculation()) {
|
if (opTok->isComparisonOp() || opTok->isCalculation()) {
|
||||||
if (opTok->astOperand1() != tok)
|
if (opTok->astOperand1() != tok)
|
||||||
opTok = opTok->astOperand1();
|
opTok = opTok->astOperand1();
|
||||||
|
@ -1490,7 +1483,7 @@ void CheckOther::checkConstVariable()
|
||||||
}
|
}
|
||||||
if (opTok->valueType() && var->valueType() && opTok->valueType()->isConst(var->valueType()->pointer))
|
if (opTok->valueType() && var->valueType() && opTok->valueType()->isConst(var->valueType()->pointer))
|
||||||
continue;
|
continue;
|
||||||
} else if (const Token* ftok = isFuncArg(opTok)) {
|
} else if (const Token* ftok = getTokenArgumentFunction(tok, argn)) {
|
||||||
bool inconclusive{};
|
bool inconclusive{};
|
||||||
if (var->valueType() && !isVariableChangedByFunctionCall(ftok, var->valueType()->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive)
|
if (var->valueType() && !isVariableChangedByFunctionCall(ftok, var->valueType()->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1572,6 +1565,7 @@ void CheckOther::checkConstPointer()
|
||||||
const Token* const gparent = parent->astParent();
|
const Token* const gparent = parent->astParent();
|
||||||
if (Token::Match(gparent, "%cop%") && !gparent->isUnaryOp("&") && !gparent->isUnaryOp("*"))
|
if (Token::Match(gparent, "%cop%") && !gparent->isUnaryOp("&") && !gparent->isUnaryOp("*"))
|
||||||
continue;
|
continue;
|
||||||
|
int argn = -1;
|
||||||
if (Token::simpleMatch(gparent, "return")) {
|
if (Token::simpleMatch(gparent, "return")) {
|
||||||
const Function* function = gparent->scope()->function;
|
const Function* function = gparent->scope()->function;
|
||||||
if (function && (!Function::returnsReference(function) || Function::returnsConst(function)))
|
if (function && (!Function::returnsReference(function) || Function::returnsConst(function)))
|
||||||
|
@ -1589,16 +1583,27 @@ void CheckOther::checkConstPointer()
|
||||||
continue;
|
continue;
|
||||||
} else if (Token::simpleMatch(gparent, "[") && gparent->astOperand2() == parent)
|
} else if (Token::simpleMatch(gparent, "[") && gparent->astOperand2() == parent)
|
||||||
continue;
|
continue;
|
||||||
else if (const Token* ftok = isFuncArg(gparent)) {
|
else if (const Token* ftok = getTokenArgumentFunction(parent, argn)) {
|
||||||
bool inconclusive{};
|
bool inconclusive{};
|
||||||
if (!isVariableChangedByFunctionCall(ftok, vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive)
|
if (!isVariableChangedByFunctionCall(ftok, vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
int argn = -1;
|
||||||
if (Token::Match(parent, "%oror%|%comp%|&&|?|!|-"))
|
if (Token::Match(parent, "%oror%|%comp%|&&|?|!|-"))
|
||||||
continue;
|
continue;
|
||||||
else if (Token::simpleMatch(parent, "(") && Token::Match(parent->astOperand1(), "if|while"))
|
else if (Token::simpleMatch(parent, "(") && Token::Match(parent->astOperand1(), "if|while"))
|
||||||
continue;
|
continue;
|
||||||
|
else if (const Token* ftok = getTokenArgumentFunction(tok, argn)) {
|
||||||
|
if (ftok->function() && !parent->isCast()) {
|
||||||
|
const Variable* argVar = ftok->function()->getArgumentVar(argn);
|
||||||
|
if (argVar && argVar->valueType() && argVar->valueType()->isConst(vt->pointer)) {
|
||||||
|
bool inconclusive{};
|
||||||
|
if (!isVariableChangedByFunctionCall(ftok, vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
nonConstPointers.emplace_back(var);
|
nonConstPointers.emplace_back(var);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2409,7 +2409,7 @@ static Token *skipTernaryOp(Token *tok, const Token *backToken)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateSimplifier::simplifyTemplateArgs(Token *start, Token *end)
|
void TemplateSimplifier::simplifyTemplateArgs(Token *start, const Token *end)
|
||||||
{
|
{
|
||||||
// start could be erased so use the token before start if available
|
// start could be erased so use the token before start if available
|
||||||
Token * first = (start && start->previous()) ? start->previous() : mTokenList.front();
|
Token * first = (start && start->previous()) ? start->previous() : mTokenList.front();
|
||||||
|
@ -2599,7 +2599,7 @@ static bool validTokenEnd(bool bounded, const Token *tok, const Token *backToken
|
||||||
|
|
||||||
// TODO: This is not the correct class for simplifyCalculations(), so it
|
// TODO: This is not the correct class for simplifyCalculations(), so it
|
||||||
// should be moved away.
|
// should be moved away.
|
||||||
bool TemplateSimplifier::simplifyCalculations(Token* frontToken, Token *backToken, bool isTemplate)
|
bool TemplateSimplifier::simplifyCalculations(Token* frontToken, const Token *backToken, bool isTemplate)
|
||||||
{
|
{
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
const bool bounded = frontToken || backToken;
|
const bool bounded = frontToken || backToken;
|
||||||
|
|
|
@ -327,13 +327,13 @@ public:
|
||||||
* @return true if modifications to token-list are done.
|
* @return true if modifications to token-list are done.
|
||||||
* false if no modifications are done.
|
* false if no modifications are done.
|
||||||
*/
|
*/
|
||||||
bool simplifyCalculations(Token* frontToken = nullptr, Token *backToken = nullptr, bool isTemplate = true);
|
bool simplifyCalculations(Token* frontToken = nullptr, const Token *backToken = nullptr, bool isTemplate = true);
|
||||||
|
|
||||||
/** Simplify template instantiation arguments.
|
/** Simplify template instantiation arguments.
|
||||||
* @param start first token of arguments
|
* @param start first token of arguments
|
||||||
* @param end token following last argument token
|
* @param end token following last argument token
|
||||||
*/
|
*/
|
||||||
void simplifyTemplateArgs(Token *start, Token *end);
|
void simplifyTemplateArgs(Token *start, const Token *end);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2028,7 +2028,7 @@ static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
const Token* endToken,
|
const Token* endToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
ValueFlow::Value value,
|
ValueFlow::Value value,
|
||||||
TokenList* const tokenlist,
|
const TokenList* const tokenlist,
|
||||||
const Settings* settings,
|
const Settings* settings,
|
||||||
SourceLocation loc = SourceLocation::current())
|
SourceLocation loc = SourceLocation::current())
|
||||||
{
|
{
|
||||||
|
@ -2044,7 +2044,7 @@ static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
const Token* endToken,
|
const Token* endToken,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
std::list<ValueFlow::Value> values,
|
std::list<ValueFlow::Value> values,
|
||||||
TokenList* const tokenlist,
|
const TokenList* const tokenlist,
|
||||||
const Settings* settings,
|
const Settings* settings,
|
||||||
SourceLocation loc = SourceLocation::current())
|
SourceLocation loc = SourceLocation::current())
|
||||||
{
|
{
|
||||||
|
@ -2073,7 +2073,7 @@ static Analyzer::Result valueFlowForward(Token* startToken,
|
||||||
static Analyzer::Result valueFlowForwardRecursive(Token* top,
|
static Analyzer::Result valueFlowForwardRecursive(Token* top,
|
||||||
const Token* exprTok,
|
const Token* exprTok,
|
||||||
std::list<ValueFlow::Value> values,
|
std::list<ValueFlow::Value> values,
|
||||||
TokenList* const tokenlist,
|
const TokenList* const tokenlist,
|
||||||
const Settings* settings,
|
const Settings* settings,
|
||||||
SourceLocation loc = SourceLocation::current())
|
SourceLocation loc = SourceLocation::current())
|
||||||
{
|
{
|
||||||
|
@ -2091,7 +2091,7 @@ static void valueFlowReverse(Token* tok,
|
||||||
const Token* const endToken,
|
const Token* const endToken,
|
||||||
const Token* const varToken,
|
const Token* const varToken,
|
||||||
std::list<ValueFlow::Value> values,
|
std::list<ValueFlow::Value> values,
|
||||||
TokenList* tokenlist,
|
const TokenList* tokenlist,
|
||||||
const Settings* settings,
|
const Settings* settings,
|
||||||
SourceLocation loc = SourceLocation::current())
|
SourceLocation loc = SourceLocation::current())
|
||||||
{
|
{
|
||||||
|
@ -2103,7 +2103,7 @@ static void valueFlowReverse(Token* tok,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated
|
// Deprecated
|
||||||
static void valueFlowReverse(TokenList* tokenlist,
|
static void valueFlowReverse(const TokenList* tokenlist,
|
||||||
Token* tok,
|
Token* tok,
|
||||||
const Token* const varToken,
|
const Token* const varToken,
|
||||||
ValueFlow::Value val,
|
ValueFlow::Value val,
|
||||||
|
@ -6999,7 +6999,7 @@ static void valueFlowForLoopSimplify(Token* const bodyStart,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, TokenList* tokenlist, const Settings* settings)
|
static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const MathLib::bigint num, const TokenList* tokenlist, const Settings* settings)
|
||||||
{
|
{
|
||||||
const Token *vartok = nullptr;
|
const Token *vartok = nullptr;
|
||||||
for (const Token *tok = fortok; tok; tok = tok->next()) {
|
for (const Token *tok = fortok; tok; tok = tok->next()) {
|
||||||
|
@ -7316,7 +7316,7 @@ static void valueFlowInjectParameter(TokenList* tokenlist,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowInjectParameter(TokenList* tokenlist,
|
static void valueFlowInjectParameter(const TokenList* tokenlist,
|
||||||
const Settings* settings,
|
const Settings* settings,
|
||||||
const Variable* arg,
|
const Variable* arg,
|
||||||
const Scope* functionScope,
|
const Scope* functionScope,
|
||||||
|
@ -7727,7 +7727,7 @@ static void addToErrorPath(ValueFlow::Value& value, const ValueFlow::Value& from
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<Token*> findAllUsages(const Variable* var, Token* start)
|
static std::vector<Token*> findAllUsages(const Variable* var, Token* start) // cppcheck-suppress constParameter // FP
|
||||||
{
|
{
|
||||||
std::vector<Token*> result;
|
std::vector<Token*> result;
|
||||||
const Scope* scope = var->scope();
|
const Scope* scope = var->scope();
|
||||||
|
@ -8713,7 +8713,7 @@ struct ContainerConditionHandler : ConditionHandler {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void valueFlowDynamicBufferSize(TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings)
|
static void valueFlowDynamicBufferSize(const TokenList* tokenlist, SymbolDatabase* symboldatabase, const Settings* settings)
|
||||||
{
|
{
|
||||||
auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint {
|
auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint {
|
||||||
MathLib::bigint sizeValue = -1;
|
MathLib::bigint sizeValue = -1;
|
||||||
|
|
|
@ -3455,6 +3455,21 @@ private:
|
||||||
"[test.cpp:14]: (style) Parameter 's' can be declared as pointer to const\n",
|
"[test.cpp:14]: (style) Parameter 's' can be declared as pointer to const\n",
|
||||||
errout.str());
|
errout.str());
|
||||||
|
|
||||||
|
check("void g(int, const int*);\n"
|
||||||
|
"void h(const int*);\n"
|
||||||
|
"void f(int* p) {\n"
|
||||||
|
" g(1, p);\n"
|
||||||
|
" h(p);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Parameter 'p' can be declared as pointer to const\n",
|
||||||
|
errout.str());
|
||||||
|
|
||||||
|
check("void f(int, const int*);\n"
|
||||||
|
"void f(int i, int* p) {\n"
|
||||||
|
" f(i, const_cast<const int*>(p));\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("struct S { int a; };\n"
|
check("struct S { int a; };\n"
|
||||||
"void f(std::vector<S>& v, int b) {\n"
|
"void f(std::vector<S>& v, int b) {\n"
|
||||||
" size_t n = v.size();\n"
|
" size_t n = v.size();\n"
|
||||||
|
@ -3465,6 +3480,18 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (style) Variable 's' can be declared as reference to const\n", errout.str()); // don't crash
|
ASSERT_EQUALS("[test.cpp:5]: (style) Variable 's' can be declared as reference to const\n", errout.str()); // don't crash
|
||||||
|
|
||||||
|
check("void f(int& i) {\n"
|
||||||
|
" new (&i) int();\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("", errout.str()); // don't crash
|
||||||
|
|
||||||
|
check("class C;\n" // #11646
|
||||||
|
"void g(const C* const p);\n"
|
||||||
|
"void f(C* c) {\n"
|
||||||
|
" g(c);\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) Parameter 'c' can be declared as pointer to const\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void switchRedundantAssignmentTest() {
|
void switchRedundantAssignmentTest() {
|
||||||
|
|
|
@ -5241,8 +5241,7 @@ private:
|
||||||
" s.x = 42;\n"
|
" s.x = 42;\n"
|
||||||
" bar(&s);\n"
|
" bar(&s);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:18] -> [test.cpp:12] -> [test.cpp:8]: (warning) Uninitialized variable: s->flag\n",
|
ASSERT_EQUALS("[test.cpp:18]: (error) Uninitialized variable: &s.flag\n", errout.str());
|
||||||
errout.str());
|
|
||||||
|
|
||||||
// Ticket #2207 - False negative
|
// Ticket #2207 - False negative
|
||||||
valueFlowUninit("void foo() {\n"
|
valueFlowUninit("void foo() {\n"
|
||||||
|
@ -6020,7 +6019,7 @@ private:
|
||||||
" someType_t gVar;\n"
|
" someType_t gVar;\n"
|
||||||
" bar(&gVar);\n"
|
" bar(&gVar);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:5]: (warning) Uninitialized variable: p->flags\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:9]: (error) Uninitialized variable: &gVar\n", errout.str());
|
||||||
|
|
||||||
valueFlowUninit("typedef struct\n"
|
valueFlowUninit("typedef struct\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -6783,10 +6782,7 @@ private:
|
||||||
" abc.a = 1;\n"
|
" abc.a = 1;\n"
|
||||||
" setabc(123, &abc);\n"
|
" setabc(123, &abc);\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
TODO_ASSERT_EQUALS("[test.cpp:8] -> [test.cpp:3]: (error) Uninitialized variable: abc->b\n"
|
ASSERT_EQUALS("[test.cpp:8]: (error) Uninitialized variables: &abc.b, &abc.c\n", errout.str());
|
||||||
"[test.cpp:8] -> [test.cpp:3]: (error) Uninitialized variable: abc->c\n",
|
|
||||||
"[test.cpp:8] -> [test.cpp:3]: (warning) Uninitialized variable: abc->b\n",
|
|
||||||
errout.str());
|
|
||||||
|
|
||||||
valueFlowUninit("struct S { int* p; };\n" // #10463
|
valueFlowUninit("struct S { int* p; };\n" // #10463
|
||||||
"void f(S* in) {\n"
|
"void f(S* in) {\n"
|
||||||
|
|
Loading…
Reference in New Issue