Fixed #2930 (new check: redundant assignment of pointer function parameter)
This commit is contained in:
parent
a04f7b1a94
commit
cbbb582fc9
|
@ -22,6 +22,7 @@
|
|||
|
||||
#include "checkautovariables.h"
|
||||
#include "symboldatabase.h"
|
||||
#include "checknullpointer.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
@ -79,6 +80,16 @@ static bool checkRvalueExpression(const Variable* var, const Token* next)
|
|||
return((next->str() != "." || (!var->isPointer() && (!var->isClass() || var->type()))) && next->strAt(2) != ".");
|
||||
}
|
||||
|
||||
static bool pointerIsDereferencedInScope(const Variable *var, const Scope *scope)
|
||||
{
|
||||
bool unknown = false;
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||
if (tok->varId() == var->varId() && CheckNullPointer::isPointerDeRef(tok, unknown))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CheckAutoVariables::autoVariables()
|
||||
{
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
@ -96,6 +107,11 @@ void CheckAutoVariables::autoVariables()
|
|||
const Variable * var = tok->tokAt(5)->variable();
|
||||
if (checkRvalueExpression(var, tok->tokAt(6)))
|
||||
errorAutoVariableAssignment(tok->next(), false);
|
||||
} else if (Token::Match(tok, "[;{}] %var% =") &&
|
||||
isPtrArg(tok->next()) &&
|
||||
Token::Match(tok->next()->variable()->typeStartToken(), "struct| %type% * %var% [,)]") &&
|
||||
!pointerIsDereferencedInScope(tok->next()->variable(), scope)) {
|
||||
errorUselessAssignmentPtrArg(tok->next());
|
||||
} else if (Token::Match(tok, "[;{}] %var% . %var% = & %var%")) {
|
||||
// TODO: check if the parameter is only changed temporarily (#2969)
|
||||
if (_settings->inconclusive) {
|
||||
|
@ -218,6 +234,14 @@ void CheckAutoVariables::errorReturnAddressOfFunctionParameter(const Token *tok,
|
|||
"value is invalid.");
|
||||
}
|
||||
|
||||
void CheckAutoVariables::errorUselessAssignmentPtrArg(const Token *tok)
|
||||
{
|
||||
reportError(tok,
|
||||
Severity::warning,
|
||||
"uselessAssignmentPtrArg",
|
||||
"Assignment of function parameter has no effect outside the function.");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// return temporary?
|
||||
|
|
|
@ -82,6 +82,7 @@ private:
|
|||
void errorReturnTempReference(const Token *tok);
|
||||
void errorInvalidDeallocation(const Token *tok);
|
||||
void errorReturnAddressOfFunctionParameter(const Token *tok, const std::string &varname);
|
||||
void errorUselessAssignmentPtrArg(const Token *tok);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
|
||||
CheckAutoVariables c(0,settings,errorLogger);
|
||||
|
@ -92,6 +93,7 @@ private:
|
|||
c.errorReturnTempReference(0);
|
||||
c.errorInvalidDeallocation(0);
|
||||
c.errorReturnAddressOfFunctionParameter(0, "parameter");
|
||||
c.errorUselessAssignmentPtrArg(0);
|
||||
}
|
||||
|
||||
static std::string myName() {
|
||||
|
@ -104,7 +106,8 @@ private:
|
|||
"* returning a pointer to auto or temporary variable\n"
|
||||
"* assigning address of an variable to an effective parameter of a function\n"
|
||||
"* returning reference to local/temporary variable\n"
|
||||
"* returning address of function parameter\n";
|
||||
"* returning address of function parameter\n"
|
||||
"* useless assignment of pointer parameter\n";
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
|
|
|
@ -66,6 +66,7 @@ private:
|
|||
TEST_CASE(testautovar7); // ticket #3066
|
||||
TEST_CASE(testautovar8);
|
||||
TEST_CASE(testautovar9);
|
||||
TEST_CASE(testautovar10); // ticket #2930 - void f(char *p) { p = '\0'; }
|
||||
TEST_CASE(testautovar_array1);
|
||||
TEST_CASE(testautovar_array2);
|
||||
TEST_CASE(testautovar_return1);
|
||||
|
@ -239,6 +240,19 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:6]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str());
|
||||
}
|
||||
|
||||
void testautovar10() { // #2930 - assignment of function parameter
|
||||
check("void foo(char* p) {\n"
|
||||
" p = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Assignment of function parameter has no effect outside the function.\n", errout.str());
|
||||
|
||||
check("void foo(char* p) {\n"
|
||||
" if (!p) p = buf;\n"
|
||||
" *p = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void testautovar_array1() {
|
||||
check("void func1(int* arr[2])\n"
|
||||
"{\n"
|
||||
|
|
Loading…
Reference in New Issue