void CheckAutoVariables::assignFunctionArg() { const bool printStyle = _settings->isEnabled("style"); const bool printWarning = _settings->isEnabled("warning"); if (!printStyle && !printWarning) 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()) && !Token::Match(tok->tokAt(2), "= %varid% ;", tok->next()->varId()) && !variableIsUsedInScope(Token::findsimplematch(tok->tokAt(2), ";"), tok->next()->varId(), scope) && !Token::findsimplematch(tok, "goto", scope->classEnd)) { if (tok->next()->variable()->isPointer() && printWarning) errorUselessAssignmentPtrArg(tok->next()); else if (printStyle) errorUselessAssignmentArg(tok->next()); } } } }
void CheckAutoVariables::assignFunctionArg() { const bool printStyle = _settings->isEnabled("style"); const bool printWarning = _settings->isEnabled("warning"); if (!printStyle && !printWarning) 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()) { // TODO: What happens if this is removed? if (tok->astParent()) continue; if (!Token::Match(tok, "=|++|--") || !Token::Match(tok->astOperand1(), "%var%")) continue; const Token* const vartok = tok->astOperand1(); if (isNonReferenceArg(vartok) && !Token::Match(vartok->next(), "= %varid% ;", vartok->varId()) && !variableIsUsedInScope(Token::findsimplematch(vartok->next(), ";"), vartok->varId(), scope) && !Token::findsimplematch(vartok, "goto", scope->classEnd)) { if (vartok->variable()->isPointer() && printWarning) errorUselessAssignmentPtrArg(vartok); else if (printStyle) errorUselessAssignmentArg(vartok); } } } }
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]; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { // Critical assignment if (Token::Match(tok, "[;{}] %var% = & %var%") && isRefPtrArg(tok->next()) && isAutoVar(tok->tokAt(4))) { if (checkRvalueExpression(tok->tokAt(4))) errorAutoVariableAssignment(tok->next(), false); } 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) { const Variable * var1 = tok->next()->variable(); if (var1 && var1->isArgument() && var1->isPointer()) { const Token * const var2tok = tok->tokAt(6); if (isAutoVar(var2tok) && checkRvalueExpression(var2tok)) errorAutoVariableAssignment(tok->next(), true); } } tok = tok->tokAt(6); } else if (Token::Match(tok, "[;{}] %var% . %var% = %var% ;")) { // TODO: check if the parameter is only changed temporarily (#2969) if (_settings->inconclusive) { const Variable * var1 = tok->next()->variable(); if (var1 && var1->isArgument() && var1->isPointer()) { if (isAutoVarArray(tok->tokAt(5))) errorAutoVariableAssignment(tok->next(), true); } } tok = tok->tokAt(5); } else if (Token::Match(tok, "[;{}] * %var% = %var% ;")) { const Variable * var1 = tok->tokAt(2)->variable(); if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-3), "%type% * *")) { if (isAutoVarArray(tok->tokAt(4))) errorAutoVariableAssignment(tok->next(), false); } tok = tok->tokAt(4); } else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()) && isAutoVar(tok->linkAt(2)->tokAt(3))) { const Token* const varTok = tok->linkAt(2)->tokAt(3); if (checkRvalueExpression(varTok)) errorAutoVariableAssignment(tok->next(), false); } // Critical return else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2))) { errorReturnAddressToAutoVariable(tok); } else if (Token::Match(tok, "return & %var% [") && Token::simpleMatch(tok->linkAt(3), "] ;") && isAutoVarArray(tok->tokAt(2))) { errorReturnAddressToAutoVariable(tok); } else if (Token::Match(tok, "return & %var% ;") && tok->tokAt(2)->varId()) { const Variable * var1 = tok->tokAt(2)->variable(); if (var1 && var1->isArgument() && var1->typeEndToken()->str() != "&") errorReturnAddressOfFunctionParameter(tok, tok->strAt(2)); } // Invalid pointer deallocation else if (Token::Match(tok, "free ( %var% ) ;") || Token::Match(tok, "delete [| ]| (| %var% !![")) { tok = Token::findmatch(tok->next(), "%var%"); if (isAutoVarArray(tok)) errorInvalidDeallocation(tok); } } } }