UninitVar: Improve whole program analysis, used isVariableUsage()

This commit is contained in:
Daniel Marjamäki 2018-01-25 21:49:21 +01:00
parent 51c2ded23f
commit 9109956c8c
3 changed files with 22 additions and 17 deletions

View File

@ -1307,9 +1307,9 @@ std::string CheckUninitVar::MyFileInfo::toString() const
return ret.str(); return ret.str();
} }
#define FUNCTION_ID(function) tokenizer->list.file(function->tokenDef) + ':' + MathLib::toString(function->tokenDef->linenr()) #define FUNCTION_ID(function) _tokenizer->list.file(function->tokenDef) + ':' + MathLib::toString(function->tokenDef->linenr())
CheckUninitVar::MyFileInfo::FunctionArg::FunctionArg(const Tokenizer *tokenizer, const Scope *scope, unsigned int argnr_, const Token *tok) CheckUninitVar::MyFileInfo::FunctionArg::FunctionArg(const Tokenizer *_tokenizer, const Scope *scope, unsigned int argnr_, const Token *tok)
: :
id(FUNCTION_ID(scope->function)), id(FUNCTION_ID(scope->function)),
functionName(scope->className), functionName(scope->className),
@ -1317,11 +1317,11 @@ CheckUninitVar::MyFileInfo::FunctionArg::FunctionArg(const Tokenizer *tokenizer,
argnr2(0), argnr2(0),
variableName(scope->function->getArgumentVar(argnr-1)->name()) variableName(scope->function->getArgumentVar(argnr-1)->name())
{ {
location.fileName = tokenizer->list.file(tok); location.fileName = _tokenizer->list.file(tok);
location.linenr = tok->linenr(); location.linenr = tok->linenr();
} }
static bool isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) bool CheckUninitVar::isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const
{ {
const Variable * const argvar = scope->function->getArgumentVar(argnr); const Variable * const argvar = scope->function->getArgumentVar(argnr);
if (!argvar->isPointer()) if (!argvar->isPointer())
@ -1329,11 +1329,7 @@ static bool isUnsafeFunction(const Scope *scope, int argnr, const Token **tok)
for (const Token *tok2 = scope->classStart; tok2 != scope->classEnd; tok2 = tok2->next()) { for (const Token *tok2 = scope->classStart; tok2 != scope->classEnd; tok2 = tok2->next()) {
if (tok2->variable() != argvar) if (tok2->variable() != argvar)
continue; continue;
if (!Token::Match(tok2->astParent(), "*|[")) if (!isVariableUsage(tok2, true, Alloc::ARRAY))
return false;
while (Token::Match(tok2->astParent(), "*|["))
tok2 = tok2->astParent();
if (!Token::Match(tok2->astParent(),"%cop%"))
return false; return false;
*tok = tok2; *tok = tok2;
return true; return true;
@ -1370,9 +1366,15 @@ static int isCallFunction(const Scope *scope, int argnr, const Token **tok)
return -1; return -1;
} }
Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const Settings * /*settings*/) const Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const Settings *settings) const
{ {
const SymbolDatabase * const symbolDatabase = tokenizer->getSymbolDatabase(); const CheckUninitVar checker(tokenizer, settings, nullptr);
return checker.getFileInfo();
}
Check::FileInfo *CheckUninitVar::getFileInfo() const
{
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
std::list<Scope>::const_iterator scope; std::list<Scope>::const_iterator scope;
MyFileInfo *fileInfo = new MyFileInfo; MyFileInfo *fileInfo = new MyFileInfo;
@ -1398,7 +1400,7 @@ Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const S
// null pointer.. // null pointer..
const ValueFlow::Value *value = argtok->getValue(0); const ValueFlow::Value *value = argtok->getValue(0);
if (value && !value->isInconclusive()) if (value && !value->isInconclusive())
fileInfo->nullPointer.push_back(MyFileInfo::FunctionArg(FUNCTION_ID(tok->astOperand1()->function()), tok->astOperand1()->str(), argnr+1, tokenizer->list.file(argtok), argtok->linenr(), argtok->str())); fileInfo->nullPointer.push_back(MyFileInfo::FunctionArg(FUNCTION_ID(tok->astOperand1()->function()), tok->astOperand1()->str(), argnr+1, _tokenizer->list.file(argtok), argtok->linenr(), argtok->str()));
} }
// pointer to uninitialized data.. // pointer to uninitialized data..
if (argtok->str() != "&" || argtok->astOperand2()) if (argtok->str() != "&" || argtok->astOperand2())
@ -1411,7 +1413,7 @@ Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const S
const ValueFlow::Value &v = argtok->values().front(); const ValueFlow::Value &v = argtok->values().front();
if (v.valueType != ValueFlow::Value::UNINIT || v.isInconclusive()) if (v.valueType != ValueFlow::Value::UNINIT || v.isInconclusive())
continue; continue;
fileInfo->uninitialized.push_back(MyFileInfo::FunctionArg(FUNCTION_ID(tok->astOperand1()->function()), tok->astOperand1()->str(), argnr+1, tokenizer->list.file(argtok), argtok->linenr(), argtok->str())); fileInfo->uninitialized.push_back(MyFileInfo::FunctionArg(FUNCTION_ID(tok->astOperand1()->function()), tok->astOperand1()->str(), argnr+1, _tokenizer->list.file(argtok), argtok->linenr(), argtok->str()));
} }
} }
@ -1419,9 +1421,9 @@ Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const S
for (int argnr = 0; argnr < function->argCount(); ++argnr) { for (int argnr = 0; argnr < function->argCount(); ++argnr) {
const Token *tok; const Token *tok;
if (isUnsafeFunction(&*scope, argnr, &tok)) if (isUnsafeFunction(&*scope, argnr, &tok))
fileInfo->readData.push_back(MyFileInfo::FunctionArg(tokenizer, &*scope, argnr+1, tok)); fileInfo->readData.push_back(MyFileInfo::FunctionArg(_tokenizer, &*scope, argnr+1, tok));
if (CheckNullPointer::isUnsafeFunction(&*scope, argnr, &tok)) if (CheckNullPointer::isUnsafeFunction(&*scope, argnr, &tok))
fileInfo->dereferenced.push_back(MyFileInfo::FunctionArg(tokenizer, &*scope, argnr+1, tok)); fileInfo->dereferenced.push_back(MyFileInfo::FunctionArg(_tokenizer, &*scope, argnr+1, tok));
} }
// Nested function calls // Nested function calls
@ -1429,7 +1431,7 @@ Check::FileInfo *CheckUninitVar::getFileInfo(const Tokenizer *tokenizer, const S
const Token *tok; const Token *tok;
int argnr2 = isCallFunction(&*scope, argnr, &tok); int argnr2 = isCallFunction(&*scope, argnr, &tok);
if (argnr2 > 0) { if (argnr2 > 0) {
MyFileInfo::FunctionArg fa(tokenizer, &*scope, argnr+1, tok); MyFileInfo::FunctionArg fa(_tokenizer, &*scope, argnr+1, tok);
fa.id = FUNCTION_ID(function); fa.id = FUNCTION_ID(function);
fa.id2 = FUNCTION_ID(tok->function()); fa.id2 = FUNCTION_ID(tok->function());
fa.argnr2 = argnr2; fa.argnr2 = argnr2;

View File

@ -155,6 +155,9 @@ public:
void uninitStructMemberError(const Token *tok, const std::string &membername); void uninitStructMemberError(const Token *tok, const std::string &membername);
private: private:
Check::FileInfo *getFileInfo() const;
bool isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const;
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const { void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const {
CheckUninitVar c(nullptr, settings, errorLogger); CheckUninitVar c(nullptr, settings, errorLogger);

View File

@ -3996,7 +3996,7 @@ private:
void ctu() { void ctu() {
ctu("void f(int *p) {\n" ctu("void f(int *p) {\n"
" a = *p + 3;\n" " a = *p;\n"
"}\n" "}\n"
"int main() {\n" "int main() {\n"
" int x;\n" " int x;\n"