diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index c12efa50b..1a633aeaa 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -118,12 +118,27 @@ static bool variableIsUsedInScope(const Token* start, unsigned int varId, const return false; } +void CheckAutoVariables::assignFunctionArg() +{ + if (!_settings->isEnabled("warning")) + return; + const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); + const std::size_t functions = symbolDatabase->functionScopes.size(); + for (std::size_t i = 0; i < functions; ++i) { + const Scope * scope = symbolDatabase->functionScopes[i]; + for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { + if (Token::Match(tok, "[;{}] %var% =") && + isNonReferenceArg(tok->next()) && + !variableIsUsedInScope(Token::findsimplematch(tok->tokAt(2), ";"), tok->next()->varId(), scope)) { + errorUselessAssignmentPtrArg(tok->next()); + } + } + } +} + void CheckAutoVariables::autoVariables() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); - - const bool reportWarnings(_settings->isEnabled("warning")); - const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { const Scope * scope = symbolDatabase->functionScopes[i]; @@ -135,11 +150,6 @@ void CheckAutoVariables::autoVariables() } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) { if (checkRvalueExpression(tok->tokAt(5))) errorAutoVariableAssignment(tok->next(), false); - } else if (reportWarnings && - Token::Match(tok, "[;{}] %var% =") && - isNonReferenceArg(tok->next()) && - !variableIsUsedInScope(Token::findsimplematch(tok->tokAt(2), ";"), tok->next()->varId(), 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) { diff --git a/lib/checkautovariables.h b/lib/checkautovariables.h index cafe97dda..a2624c463 100644 --- a/lib/checkautovariables.h +++ b/lib/checkautovariables.h @@ -44,6 +44,7 @@ public: /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) { CheckAutoVariables checkAutoVariables(tokenizer, settings, errorLogger); + checkAutoVariables.assignFunctionArg(); checkAutoVariables.returnReference(); } @@ -53,6 +54,9 @@ public: checkAutoVariables.returnPointerToLocalArray(); } + /** assign function argument */ + void assignFunctionArg(); + /** Check auto variables */ void autoVariables(); diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 07b5a5879..778a7b1f8 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -49,6 +49,7 @@ private: CheckAutoVariables checkAutoVariables(&tokenizer, &settings, this); checkAutoVariables.returnReference(); + checkAutoVariables.assignFunctionArg(); if (runSimpleChecks) { const std::string str1(tokenizer.tokens()->stringifyList(0,true)); @@ -305,6 +306,13 @@ private: " p = 0;\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("double foo(double d) {\n" // #5005 + " int i = d;\n" + " d = i;\n" + " return d;" + "}",false,false); + ASSERT_EQUALS("", errout.str()); } void testautovar11() { // #4641 - fp, assign local struct member address to function parameter