speed up checks by caching commonly looked up stuff in the symbol database (CheckOther). Ticket #4266
This commit is contained in:
parent
6578b78077
commit
04d04c33c2
|
@ -40,14 +40,17 @@ void CheckOther::checkIncrementBoolean()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
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->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "%var% ++")) {
|
||||||
|
if (tok->varId()) {
|
||||||
|
const Variable *var = symbolDatabase->getVariableFromVarId(tok->varId());
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
if (var && var->typeEndToken()->str() == "bool")
|
||||||
if (Token::Match(tok, "%var% ++")) {
|
incrementBooleanError(tok);
|
||||||
if (tok->varId()) {
|
}
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(tok->varId());
|
|
||||||
|
|
||||||
if (var && var->typeEndToken()->str() == "bool")
|
|
||||||
incrementBooleanError(tok);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,49 +74,54 @@ void CheckOther::clarifyCalculation()
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
if (tok->str() == "?" && tok->previous()) {
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
// condition
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Token *cond = tok->previous();
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
if (cond->isName() || cond->isNumber())
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
cond = cond->previous();
|
if (tok->str() == "?") {
|
||||||
else if (cond->str() == ")")
|
// condition
|
||||||
cond = cond->link()->previous();
|
const Token *cond = tok->previous();
|
||||||
else
|
if (cond->isName() || cond->isNumber())
|
||||||
continue;
|
cond = cond->previous();
|
||||||
|
|
||||||
if (cond && cond->str() == "!")
|
|
||||||
cond = cond->previous();
|
|
||||||
|
|
||||||
if (!cond)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// calculation
|
|
||||||
if (!cond->isArithmeticalOp())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const std::string &op = cond->str();
|
|
||||||
cond = cond->previous();
|
|
||||||
|
|
||||||
// skip previous multiplications..
|
|
||||||
while (cond && cond->previous()) {
|
|
||||||
if ((cond->isName() || cond->isNumber()) && cond->previous()->str() == "*")
|
|
||||||
cond = cond->tokAt(-2);
|
|
||||||
else if (cond->str() == ")")
|
else if (cond->str() == ")")
|
||||||
cond = cond->link()->previous();
|
cond = cond->link()->previous();
|
||||||
else
|
else
|
||||||
break;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (!cond)
|
if (cond && cond->str() == "!")
|
||||||
continue;
|
cond = cond->previous();
|
||||||
|
|
||||||
// first multiplication operand
|
if (!cond)
|
||||||
if (cond->str() == ")") {
|
continue;
|
||||||
clarifyCalculationError(cond, op);
|
|
||||||
} else if (cond->isName() || cond->isNumber()) {
|
// calculation
|
||||||
if (Token::Match(cond->previous(),"return|=|+|-|,|(") || cond->strAt(-1) == op)
|
if (!cond->isArithmeticalOp())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const std::string &op = cond->str();
|
||||||
|
cond = cond->previous();
|
||||||
|
|
||||||
|
// skip previous multiplications..
|
||||||
|
while (cond && cond->previous()) {
|
||||||
|
if ((cond->isName() || cond->isNumber()) && cond->previous()->str() == "*")
|
||||||
|
cond = cond->tokAt(-2);
|
||||||
|
else if (cond->str() == ")")
|
||||||
|
cond = cond->link()->previous();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cond)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// first multiplication operand
|
||||||
|
if (cond->str() == ")") {
|
||||||
clarifyCalculationError(cond, op);
|
clarifyCalculationError(cond, op);
|
||||||
|
} else if (cond->isName() || cond->isNumber()) {
|
||||||
|
if (Token::Match(cond->previous(),"return|=|+|-|,|(") || cond->strAt(-1) == op)
|
||||||
|
clarifyCalculationError(cond, op);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,59 +157,67 @@ void CheckOther::clarifyCondition()
|
||||||
|
|
||||||
const bool isC = _tokenizer->isC();
|
const bool isC = _tokenizer->isC();
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
if (Token::Match(tok, "( %var% [=&|^]")) {
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
for (const Token *tok2 = tok->tokAt(3); tok2; tok2 = tok2->next()) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
if (tok2->str() == "(" || tok2->str() == "[")
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
tok2 = tok2->link();
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
else if (tok2->type() == Token::eComparisonOp) {
|
if (Token::Match(tok, "( %var% [=&|^]")) {
|
||||||
// This might be a template
|
for (const Token *tok2 = tok->tokAt(3); tok2; tok2 = tok2->next()) {
|
||||||
if (!isC && tok2->link())
|
if (tok2->str() == "(" || tok2->str() == "[")
|
||||||
break;
|
tok2 = tok2->link();
|
||||||
|
else if (tok2->type() == Token::eComparisonOp) {
|
||||||
|
// This might be a template
|
||||||
|
if (!isC && tok2->link())
|
||||||
|
break;
|
||||||
|
|
||||||
clarifyConditionError(tok, tok->strAt(2) == "=", false);
|
clarifyConditionError(tok, tok->strAt(2) == "=", false);
|
||||||
break;
|
break;
|
||||||
} else if (!tok2->isName() && !tok2->isNumber() && tok2->str() != ".")
|
} else if (!tok2->isName() && !tok2->isNumber() && tok2->str() != ".")
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// using boolean result in bitwise operation ! x [&|^]
|
// using boolean result in bitwise operation ! x [&|^]
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
if (Token::Match(tok, "!|<|<=|==|!=|>|>=")) {
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
if (tok->link()) // don't write false positives when templates are used
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
continue;
|
if (Token::Match(tok, "!|<|<=|==|!=|>|>=")) {
|
||||||
|
if (tok->link()) // don't write false positives when templates are used
|
||||||
const Token *tok2 = tok->next();
|
|
||||||
|
|
||||||
// Todo: There are false positives if '(' if encountered. It
|
|
||||||
// is assumed there is something like '(char *)&..' and therefore
|
|
||||||
// it bails out.
|
|
||||||
if (Token::Match(tok2, "(|&"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
while (tok2 && (tok2->isName() || tok2->isNumber() || Token::Match(tok2,".|(|["))) {
|
|
||||||
if (Token::Match(tok2, "(|["))
|
|
||||||
tok2 = tok2->link();
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Token::Match(tok2, "[&|^]")) {
|
|
||||||
// don't write false positives when templates are used
|
|
||||||
if (Token::Match(tok2, "&|* ,|>") || Token::simpleMatch(tok2->previous(), "const &"))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// #3609 - CWinTraits<WS_CHILD|WS_VISIBLE>::..
|
const Token *tok2 = tok->next();
|
||||||
if (!isC && Token::Match(tok->previous(), "%var% <")) {
|
|
||||||
const Token *tok3 = tok2;
|
// Todo: There are false positives if '(' if encountered. It
|
||||||
while (Token::Match(tok3, "[&|^] %var%"))
|
// is assumed there is something like '(char *)&..' and therefore
|
||||||
tok3 = tok3->tokAt(2);
|
// it bails out.
|
||||||
if (Token::Match(tok3, ",|>"))
|
if (Token::Match(tok2, "(|&"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
while (tok2 && (tok2->isName() || tok2->isNumber() || Token::Match(tok2,".|(|["))) {
|
||||||
|
if (Token::Match(tok2, "(|["))
|
||||||
|
tok2 = tok2->link();
|
||||||
|
tok2 = tok2->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
clarifyConditionError(tok,false,true);
|
if (Token::Match(tok2, "[&|^]")) {
|
||||||
|
// don't write false positives when templates are used
|
||||||
|
if (Token::Match(tok2, "&|* ,|>") || Token::simpleMatch(tok2->previous(), "const &"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// #3609 - CWinTraits<WS_CHILD|WS_VISIBLE>::..
|
||||||
|
if (!isC && Token::Match(tok->previous(), "%var% <")) {
|
||||||
|
const Token *tok3 = tok2;
|
||||||
|
while (Token::Match(tok3, "[&|^] %var%"))
|
||||||
|
tok3 = tok3->tokAt(2);
|
||||||
|
if (Token::Match(tok3, ",|>"))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
clarifyConditionError(tok,false,true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,29 +253,34 @@ void CheckOther::clarifyStatement()
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
if (Token::Match(tok, "* %var%")) {
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
const Token *tok2=tok->previous();
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "* %var%")) {
|
||||||
|
const Token *tok2=tok->previous();
|
||||||
|
|
||||||
while (tok2 && tok2->str() == "*")
|
while (tok2 && tok2->str() == "*")
|
||||||
tok2=tok2->previous();
|
tok2=tok2->previous();
|
||||||
|
|
||||||
if (Token::Match(tok2, "[{};]")) {
|
if (Token::Match(tok2, "[{};]")) {
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (tok->str() == "[")
|
if (tok->str() == "[")
|
||||||
tok = tok->link()->next();
|
tok = tok->link()->next();
|
||||||
|
|
||||||
if (Token::Match(tok, ".|:: %var%")) {
|
if (Token::Match(tok, ".|:: %var%")) {
|
||||||
if (tok->strAt(2) == "(")
|
if (tok->strAt(2) == "(")
|
||||||
tok = tok->linkAt(2)->next();
|
tok = tok->linkAt(2)->next();
|
||||||
else
|
else
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
if (Token::Match(tok, "++|-- [;,]"))
|
||||||
|
clarifyStatementError(tok);
|
||||||
}
|
}
|
||||||
if (Token::Match(tok, "++|-- [;,]"))
|
|
||||||
clarifyStatementError(tok);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,18 +307,23 @@ void CheckOther::checkBitwiseOnBoolean()
|
||||||
if (!_settings->inconclusive)
|
if (!_settings->inconclusive)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId());
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
if (var && var->typeEndToken()->str() == "bool") {
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
tok = tok->tokAt(2);
|
if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
|
||||||
}
|
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId());
|
||||||
} else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")")) {
|
if (var && var->typeEndToken()->str() == "bool") {
|
||||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId());
|
bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
|
||||||
if (var && var->typeEndToken()->str() == "bool") {
|
tok = tok->tokAt(2);
|
||||||
bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
|
}
|
||||||
tok = tok->tokAt(2);
|
} else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")")) {
|
||||||
|
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId());
|
||||||
|
if (var && var->typeEndToken()->str() == "bool") {
|
||||||
|
bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
|
||||||
|
tok = tok->tokAt(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,63 +419,68 @@ void CheckOther::invalidPointerCast()
|
||||||
if (!_settings->isEnabled("style") && !_settings->isEnabled("portability"))
|
if (!_settings->isEnabled("style") && !_settings->isEnabled("portability"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Token* toTok = 0;
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
const Token* nextTok = 0;
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
// Find cast
|
const Token* toTok = 0;
|
||||||
if (Token::Match(tok, "( const| %type% const| * )") || Token::Match(tok, "( const| %type% %type% const| * )")) {
|
const Token* nextTok = 0;
|
||||||
toTok = tok->next();
|
// Find cast
|
||||||
nextTok = tok->link()->next();
|
if (Token::Match(tok, "( const| %type% const| * )") ||
|
||||||
if (nextTok && nextTok->str() == "(")
|
Token::Match(tok, "( const| %type% %type% const| * )")) {
|
||||||
|
toTok = tok->next();
|
||||||
|
nextTok = tok->link()->next();
|
||||||
|
if (nextTok && nextTok->str() == "(")
|
||||||
|
nextTok = nextTok->next();
|
||||||
|
} else if (Token::Match(tok, "reinterpret_cast < const| %type% const| * > (") ||
|
||||||
|
Token::Match(tok, "reinterpret_cast < const| %type% %type% const| * > (")) {
|
||||||
|
nextTok = tok->tokAt(5);
|
||||||
|
while (nextTok->str() != "(")
|
||||||
|
nextTok = nextTok->next();
|
||||||
nextTok = nextTok->next();
|
nextTok = nextTok->next();
|
||||||
} else if (Token::Match(tok, "reinterpret_cast < const| %type% const| * > (") || Token::Match(tok, "reinterpret_cast < const| %type% %type% const| * > (")) {
|
toTok = tok->tokAt(2);
|
||||||
nextTok = tok->tokAt(5);
|
}
|
||||||
while (nextTok->str() != "(")
|
if (toTok && toTok->str() == "const")
|
||||||
nextTok = nextTok->next();
|
toTok = toTok->next();
|
||||||
nextTok = nextTok->next();
|
|
||||||
toTok = tok->tokAt(2);
|
|
||||||
}
|
|
||||||
if (toTok && toTok->str() == "const")
|
|
||||||
toTok = toTok->next();
|
|
||||||
|
|
||||||
if (!nextTok || !toTok || !toTok->isStandardType())
|
if (!nextTok || !toTok || !toTok->isStandardType())
|
||||||
continue;
|
|
||||||
|
|
||||||
// Find casted variable
|
|
||||||
unsigned int varid = 0;
|
|
||||||
bool allocation = false;
|
|
||||||
bool ref = false;
|
|
||||||
if (Token::Match(nextTok, "new %type%"))
|
|
||||||
allocation = true;
|
|
||||||
else if (Token::Match(nextTok, "%var% !!["))
|
|
||||||
varid = nextTok->varId();
|
|
||||||
else if (Token::Match(nextTok, "& %var%") && !Token::Match(nextTok->tokAt(2), "(|[")) {
|
|
||||||
varid = nextTok->next()->varId();
|
|
||||||
ref = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Token* fromTok = 0;
|
|
||||||
|
|
||||||
if (allocation) {
|
|
||||||
fromTok = nextTok->next();
|
|
||||||
} else {
|
|
||||||
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
|
||||||
if (!var || (!ref && !var->isPointer() && !var->isArray()) || (ref && (var->isPointer() || var->isArray())))
|
|
||||||
continue;
|
continue;
|
||||||
fromTok = var->typeStartToken();
|
|
||||||
|
// Find casted variable
|
||||||
|
unsigned int varid = 0;
|
||||||
|
bool allocation = false;
|
||||||
|
bool ref = false;
|
||||||
|
if (Token::Match(nextTok, "new %type%"))
|
||||||
|
allocation = true;
|
||||||
|
else if (Token::Match(nextTok, "%var% !!["))
|
||||||
|
varid = nextTok->varId();
|
||||||
|
else if (Token::Match(nextTok, "& %var%") && !Token::Match(nextTok->tokAt(2), "(|[")) {
|
||||||
|
varid = nextTok->next()->varId();
|
||||||
|
ref = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Token* fromTok = 0;
|
||||||
|
|
||||||
|
if (allocation) {
|
||||||
|
fromTok = nextTok->next();
|
||||||
|
} else {
|
||||||
|
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
||||||
|
if (!var || (!ref && !var->isPointer() && !var->isArray()) || (ref && (var->isPointer() || var->isArray())))
|
||||||
|
continue;
|
||||||
|
fromTok = var->typeStartToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (Token::Match(fromTok, "static|const"))
|
||||||
|
fromTok = fromTok->next();
|
||||||
|
if (!fromTok->isStandardType())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string fromType = analyzeType(fromTok);
|
||||||
|
std::string toType = analyzeType(toTok);
|
||||||
|
if (fromType != toType && !fromType.empty() && !toType.empty() && (toType != "integer" || _settings->isEnabled("portability")) && (toTok->str() != "char" || _settings->inconclusive))
|
||||||
|
invalidPointerCastError(tok, fromType, toType, toTok->str() == "char");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (Token::Match(fromTok, "static|const"))
|
|
||||||
fromTok = fromTok->next();
|
|
||||||
if (!fromTok->isStandardType())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::string fromType = analyzeType(fromTok);
|
|
||||||
std::string toType = analyzeType(toTok);
|
|
||||||
if (fromType != toType && !fromType.empty() && !toType.empty() && (toType != "integer" || _settings->isEnabled("portability")) && (toTok->str() != "char" || _settings->inconclusive))
|
|
||||||
invalidPointerCastError(tok, fromType, toType, toTok->str() == "char");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,11 +502,15 @@ void CheckOther::checkSizeofForNumericParameter()
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
if (Token::Match(tok, "sizeof ( %num% )")
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
|| Token::Match(tok, "sizeof %num%")
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
) {
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
sizeofForNumericParameterError(tok);
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
if (Token::Match(tok, "sizeof ( %num% )") ||
|
||||||
|
Token::Match(tok, "sizeof %num%")) {
|
||||||
|
sizeofForNumericParameterError(tok);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,17 +529,21 @@ void CheckOther::sizeofForNumericParameterError(const Token *tok)
|
||||||
void CheckOther::checkSizeofForArrayParameter()
|
void CheckOther::checkSizeofForArrayParameter()
|
||||||
{
|
{
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var% !![")) {
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
const Token* varTok = tok->next();
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
if (varTok->str() == "(") {
|
if (Token::Match(tok, "sizeof ( %var% )") ||
|
||||||
varTok = varTok->next();
|
Token::Match(tok, "sizeof %var% !![")) {
|
||||||
}
|
const Token* varTok = tok->next();
|
||||||
if (varTok->varId() > 0) {
|
if (varTok->str() == "(") {
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(varTok->varId());
|
varTok = varTok->next();
|
||||||
if (var && var->isArray() && var->isArgument()) {
|
}
|
||||||
sizeofForArrayParameterError(tok);
|
if (varTok->varId() > 0) {
|
||||||
|
const Variable *var = symbolDatabase->getVariableFromVarId(varTok->varId());
|
||||||
|
if (var && var->isArray() && var->isArgument()) {
|
||||||
|
sizeofForArrayParameterError(tok);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -529,80 +568,83 @@ void CheckOther::sizeofForArrayParameterError(const Token *tok)
|
||||||
|
|
||||||
void CheckOther::checkSizeofForPointerSize()
|
void CheckOther::checkSizeofForPointerSize()
|
||||||
{
|
{
|
||||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
|
||||||
|
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
const Token *tokVar;
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
const Token *variable;
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
const Token *variable2 = 0;
|
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||||
|
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||||
|
const Token *tokVar;
|
||||||
|
const Token *variable;
|
||||||
|
const Token *variable2 = 0;
|
||||||
|
|
||||||
// Find any function that may use sizeof on a pointer
|
// Find any function that may use sizeof on a pointer
|
||||||
// Once leaving those tests, it is mandatory to have:
|
// Once leaving those tests, it is mandatory to have:
|
||||||
// - variable matching the used pointer
|
// - variable matching the used pointer
|
||||||
// - tokVar pointing on the argument where sizeof may be used
|
// - tokVar pointing on the argument where sizeof may be used
|
||||||
if (Token::Match(tok, "[*;{}] %var% = malloc|alloca (")) {
|
if (Token::Match(tok, "[*;{}] %var% = malloc|alloca (")) {
|
||||||
variable = tok->next();
|
variable = tok->next();
|
||||||
tokVar = tok->tokAt(5);
|
tokVar = tok->tokAt(5);
|
||||||
|
|
||||||
} else if (Token::Match(tok, "[*;{}] %var% = calloc (")) {
|
} else if (Token::Match(tok, "[*;{}] %var% = calloc (")) {
|
||||||
variable = tok->next();
|
variable = tok->next();
|
||||||
tokVar = tok->tokAt(5)->nextArgument();
|
tokVar = tok->tokAt(5)->nextArgument();
|
||||||
|
|
||||||
} else if (Token::simpleMatch(tok, "memset (")) {
|
} else if (Token::simpleMatch(tok, "memset (")) {
|
||||||
variable = tok->tokAt(2);
|
variable = tok->tokAt(2);
|
||||||
tokVar = variable->tokAt(2)->nextArgument();
|
tokVar = variable->tokAt(2)->nextArgument();
|
||||||
|
|
||||||
// The following tests can be inconclusive in case the variable in sizeof
|
// The following tests can be inconclusive in case the variable in sizeof
|
||||||
// is constant string by intention
|
// is constant string by intention
|
||||||
} else if (!_settings->inconclusive) {
|
} else if (!_settings->inconclusive) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else if (Token::Match(tok, "memcpy|memcmp|memmove|strncpy|strncmp|strncat (")) {
|
} else if (Token::Match(tok, "memcpy|memcmp|memmove|strncpy|strncmp|strncat (")) {
|
||||||
variable = tok->tokAt(2);
|
variable = tok->tokAt(2);
|
||||||
variable2 = variable->nextArgument();
|
variable2 = variable->nextArgument();
|
||||||
tokVar = variable2->nextArgument();
|
tokVar = variable2->nextArgument();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the variables are in the symbol database
|
|
||||||
// Also ensure the variables are pointers
|
|
||||||
// Only keep variables which are pointers
|
|
||||||
const Variable *var = symbolDatabase->getVariableFromVarId(variable->varId());
|
|
||||||
if (!var || !var->isPointer() || var->isArray()) {
|
|
||||||
variable = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variable2) {
|
|
||||||
var = symbolDatabase->getVariableFromVarId(variable2->varId());
|
|
||||||
if (!var || !var->isPointer() || var->isArray()) {
|
|
||||||
variable2 = 0;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If there are no pointer variable at this point, there is
|
// Ensure the variables are in the symbol database
|
||||||
// no need to continue
|
// Also ensure the variables are pointers
|
||||||
if (variable == 0 && variable2 == 0) {
|
// Only keep variables which are pointers
|
||||||
continue;
|
const Variable *var = symbolDatabase->getVariableFromVarId(variable->varId());
|
||||||
}
|
if (!var || !var->isPointer() || var->isArray()) {
|
||||||
|
variable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Jump to the next sizeof token in the function and in the parameter
|
if (variable2) {
|
||||||
// This is to allow generic operations with sizeof
|
var = symbolDatabase->getVariableFromVarId(variable2->varId());
|
||||||
for (; tokVar && tokVar->str() != ")" && tokVar->str() != "," && tokVar->str() != "sizeof"; tokVar = tokVar->next()) {}
|
if (!var || !var->isPointer() || var->isArray()) {
|
||||||
|
variable2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now check for the sizeof usage. Once here, everything using sizeof(varid) or sizeof(&varid)
|
// If there are no pointer variable at this point, there is
|
||||||
// looks suspicious
|
// no need to continue
|
||||||
// Do it for first variable
|
if (variable == 0 && variable2 == 0) {
|
||||||
if (variable && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable->varId()) ||
|
continue;
|
||||||
Token::Match(tokVar, "sizeof &| %varid%", variable->varId()))) {
|
}
|
||||||
sizeofForPointerError(variable, variable->str());
|
|
||||||
} else if (variable2 && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable2->varId()) ||
|
// Jump to the next sizeof token in the function and in the parameter
|
||||||
Token::Match(tokVar, "sizeof &| %varid%", variable2->varId()))) {
|
// This is to allow generic operations with sizeof
|
||||||
sizeofForPointerError(variable2, variable2->str());
|
for (; tokVar && tokVar->str() != ")" && tokVar->str() != "," && tokVar->str() != "sizeof"; tokVar = tokVar->next()) {}
|
||||||
|
|
||||||
|
// Now check for the sizeof usage. Once here, everything using sizeof(varid) or sizeof(&varid)
|
||||||
|
// looks suspicious
|
||||||
|
// Do it for first variable
|
||||||
|
if (variable && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable->varId()) ||
|
||||||
|
Token::Match(tokVar, "sizeof &| %varid%", variable->varId()))) {
|
||||||
|
sizeofForPointerError(variable, variable->str());
|
||||||
|
} else if (variable2 && (Token::Match(tokVar, "sizeof ( &| %varid% )", variable2->varId()) ||
|
||||||
|
Token::Match(tokVar, "sizeof &| %varid%", variable2->varId()))) {
|
||||||
|
sizeofForPointerError(variable2, variable2->str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4578,11 +4578,11 @@ private:
|
||||||
|
|
||||||
void incrementBoolean() {
|
void incrementBoolean() {
|
||||||
check("bool bValue = true;\n"
|
check("bool bValue = true;\n"
|
||||||
"bValue++;\n");
|
"void f() { bValue++; }\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
|
||||||
|
|
||||||
check("_Bool bValue = true;\n"
|
check("_Bool bValue = true;\n"
|
||||||
"bValue++;\n");
|
"void f() { bValue++; }\n");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (style) Incrementing a variable of type 'bool' with postfix operator++ is deprecated by the C++ Standard. You should assign it the value 'true' instead.\n", errout.str());
|
||||||
|
|
||||||
check("void f(bool test){\n"
|
check("void f(bool test){\n"
|
||||||
|
@ -5253,154 +5253,182 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkPointerSizeof() {
|
void checkPointerSizeof() {
|
||||||
check(
|
check("void f() {\n"
|
||||||
"char *x = malloc(10);\n"
|
" char *x = malloc(10);\n"
|
||||||
"free(x);");
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(*x));\n"
|
" int *x = malloc(sizeof(*x));\n"
|
||||||
"free(x);");
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int));\n"
|
" int *x = malloc(sizeof(int));\n"
|
||||||
"free(x);");
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(x));\n"
|
" int *x = malloc(sizeof(x));\n"
|
||||||
"free(x);");
|
" free(x);\n"
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
"}");
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof(&x));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(100 * sizeof(x));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof(x) * 100);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof *x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(100 * sizeof x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = calloc(1, sizeof(*x));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = calloc(1, sizeof *x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = calloc(1, sizeof(x));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = calloc(1, sizeof x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:1]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = calloc(1, sizeof(int));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"char x[10];\n"
|
|
||||||
"memset(x, 0, sizeof(x));");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"char* x[10];\n"
|
|
||||||
"memset(x, 0, sizeof(x));");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"char x[10];\n"
|
|
||||||
"memset(x, 0, sizeof x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof(int));\n"
|
|
||||||
"memset(x, 0, sizeof(int));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof(int));\n"
|
|
||||||
"memset(x, 0, sizeof(*x));\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof(int));\n"
|
|
||||||
"memset(x, 0, sizeof *x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
|
||||||
|
|
||||||
check(
|
|
||||||
"int *x = malloc(sizeof(int));\n"
|
|
||||||
"memset(x, 0, sizeof x);\n"
|
|
||||||
"free(x);");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int));\n"
|
" int *x = malloc(sizeof(&x));\n"
|
||||||
"memset(x, 0, sizeof(x));\n"
|
" free(x);\n"
|
||||||
"free(x);");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int) * 10);\n"
|
" int *x = malloc(100 * sizeof(x));\n"
|
||||||
"memset(x, 0, sizeof(x) * 10);\n"
|
" free(x);\n"
|
||||||
"free(x);");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int) * 10);\n"
|
" int *x = malloc(sizeof(x) * 100);\n"
|
||||||
"memset(x, 0, sizeof x * 10);\n"
|
" free(x);\n"
|
||||||
"free(x);");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int) * 10);\n"
|
" int *x = malloc(sizeof *x);\n"
|
||||||
"memset(x, 0, sizeof(*x) * 10);\n"
|
" free(x);\n"
|
||||||
"free(x);");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int) * 10);\n"
|
" int *x = malloc(sizeof x);\n"
|
||||||
"memset(x, 0, sizeof *x * 10);\n"
|
" free(x);\n"
|
||||||
"free(x);");
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(100 * sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof(*x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(
|
check("void f() {\n"
|
||||||
"int *x = malloc(sizeof(int) * 10);\n"
|
" int *x = calloc(1, sizeof *x);\n"
|
||||||
"memset(x, 0, sizeof(int) * 10);\n"
|
" free(x);\n"
|
||||||
"free(x);");
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof(x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = calloc(1, sizeof(int));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char x[10];\n"
|
||||||
|
" memset(x, 0, sizeof(x));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char* x[10];\n"
|
||||||
|
" memset(x, 0, sizeof(x));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" char x[10];\n"
|
||||||
|
" memset(x, 0, sizeof x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof(int));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof(*x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof *x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof x);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int));\n"
|
||||||
|
" memset(x, 0, sizeof(x));\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof(x) * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof x * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Size of pointer 'x' used instead of size of its data.\n", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof(*x) * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof *x * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void f() {\n"
|
||||||
|
" int *x = malloc(sizeof(int) * 10);\n"
|
||||||
|
" memset(x, 0, sizeof(int) * 10);\n"
|
||||||
|
" free(x);\n"
|
||||||
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check(
|
check(
|
||||||
|
|
Loading…
Reference in New Issue