Refactorization: Use SymbolDatabase scope information in ValueFlow
This commit is contained in:
parent
54b6b8e571
commit
a4cc4c3e3f
|
@ -1638,7 +1638,7 @@ bool Tokenizer::tokenize(std::istream &code,
|
||||||
}
|
}
|
||||||
|
|
||||||
list.createAst();
|
list.createAst();
|
||||||
ValueFlow::setValues(&list, _errorLogger, _settings);
|
ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3854,7 +3854,7 @@ bool Tokenizer::simplifyTokenList2()
|
||||||
|
|
||||||
list.createAst();
|
list.createAst();
|
||||||
|
|
||||||
ValueFlow::setValues(&list, _errorLogger, _settings);
|
ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings);
|
||||||
|
|
||||||
if (_settings->terminated())
|
if (_settings->terminated())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -421,9 +421,12 @@ static void valueFlowBitAnd(TokenList *tokenlist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowBeforeCondition(TokenList *tokenlist, SymbolDatabase *symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
const std::size_t functions = symboldatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symboldatabase->functionScopes[i];
|
||||||
|
for (Token* tok = const_cast<Token*>(scope->classStart); tok != scope->classEnd; tok = tok->next()) {
|
||||||
unsigned int varid=0;
|
unsigned int varid=0;
|
||||||
MathLib::bigint num=0;
|
MathLib::bigint num=0;
|
||||||
const Variable *var=0;
|
const Variable *var=0;
|
||||||
|
@ -515,7 +518,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Token *tok2 = tok->previous(); ; tok2 = tok2->previous()) {
|
for (Token *tok2 = tok->previous(); ; tok2 = tok2->previous()) {
|
||||||
if (!tok2) {
|
if (!tok2 || tok2->next() == scope->classStart) {
|
||||||
if (settings->debugwarnings) {
|
if (settings->debugwarnings) {
|
||||||
std::list<ErrorLogger::ErrorMessage::FileLocation> callstack;
|
std::list<ErrorLogger::ErrorMessage::FileLocation> callstack;
|
||||||
callstack.push_back(ErrorLogger::ErrorMessage::FileLocation(tok,tokenlist));
|
callstack.push_back(ErrorLogger::ErrorMessage::FileLocation(tok,tokenlist));
|
||||||
|
@ -649,6 +652,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void removeValues(std::list<ValueFlow::Value> &values, const std::list<ValueFlow::Value> &valuesToRemove)
|
static void removeValues(std::list<ValueFlow::Value> &values, const std::list<ValueFlow::Value> &valuesToRemove)
|
||||||
|
@ -1010,21 +1014,22 @@ static bool valueFlowForward(Token * const startToken,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
const std::size_t functions = symboldatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symboldatabase->functionScopes[i];
|
||||||
|
for (Token* tok = const_cast<Token*>(scope->classStart); tok != scope->classEnd; tok = tok->next()) {
|
||||||
// Assignment
|
// Assignment
|
||||||
if ((tok->str() != "=") || (tok->astParent()))
|
if ((tok->str() != "=") || (tok->astParent()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Lhs should be a variable
|
// Lhs should be a variable
|
||||||
if (!tok->astOperand1() || !tok->astOperand1()->isName())
|
if (!tok->astOperand1() || !tok->astOperand1()->varId())
|
||||||
continue;
|
continue;
|
||||||
const unsigned int varid = tok->astOperand1()->varId();
|
const unsigned int varid = tok->astOperand1()->varId();
|
||||||
if (varid == 0U)
|
|
||||||
continue;
|
|
||||||
const Variable *var = tok->astOperand1()->variable();
|
const Variable *var = tok->astOperand1()->variable();
|
||||||
if (!var || !var->isLocal())
|
if (!var || (!var->isLocal() && !var->isArgument()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const Token * const endOfVarScope = var->typeStartToken()->scope()->classEnd;
|
const Token * const endOfVarScope = var->typeStartToken()->scope()->classEnd;
|
||||||
|
@ -1037,15 +1042,19 @@ static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger,
|
||||||
const bool constValue = tok->astOperand2()->isNumber();
|
const bool constValue = tok->astOperand2()->isNumber();
|
||||||
valueFlowForward(tok, endOfVarScope, var, varid, values, constValue, tokenlist, errorLogger, settings);
|
valueFlowForward(tok, endOfVarScope, var, varid, values, constValue, tokenlist, errorLogger, settings);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowAfterCondition(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
const std::size_t functions = symboldatabase->functionScopes.size();
|
||||||
|
for (std::size_t i = 0; i < functions; ++i) {
|
||||||
|
const Scope * scope = symboldatabase->functionScopes[i];
|
||||||
|
for (Token* tok = const_cast<Token*>(scope->classStart); tok != scope->classEnd; tok = tok->next()) {
|
||||||
const Token *vartok, *numtok;
|
const Token *vartok, *numtok;
|
||||||
|
|
||||||
// Comparison
|
// Comparison
|
||||||
if (Token::Match(tok,"==|!=|>=|<=")) {
|
if (Token::Match(tok, "==|!=|>=|<=")) {
|
||||||
if (!tok->astOperand1() || !tok->astOperand2())
|
if (!tok->astOperand1() || !tok->astOperand2())
|
||||||
continue;
|
continue;
|
||||||
if (tok->astOperand1()->isNumber()) {
|
if (tok->astOperand1()->isNumber()) {
|
||||||
|
@ -1104,7 +1113,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
tokens.push(const_cast<Token*>(rhstok->astOperand2()));
|
tokens.push(const_cast<Token*>(rhstok->astOperand2()));
|
||||||
if (rhstok->varId() == varid)
|
if (rhstok->varId() == varid)
|
||||||
setTokenValue(rhstok, values.front());
|
setTokenValue(rhstok, values.front());
|
||||||
if (Token::Match(rhstok, "++|--|=") && Token::Match(rhstok->astOperand1(),"%varid%",varid)) {
|
if (Token::Match(rhstok, "++|--|=") && Token::Match(rhstok->astOperand1(), "%varid%", varid)) {
|
||||||
assign = true;
|
assign = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1120,7 +1129,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
// does condition reassign variable?
|
// does condition reassign variable?
|
||||||
if (tok != top->astOperand2() &&
|
if (tok != top->astOperand2() &&
|
||||||
Token::Match(top->astOperand2(), "%oror%|&&") &&
|
Token::Match(top->astOperand2(), "%oror%|&&") &&
|
||||||
isVariableChanged(top,top->link(),varid)) {
|
isVariableChanged(top, top->link(), varid)) {
|
||||||
if (settings->debugwarnings)
|
if (settings->debugwarnings)
|
||||||
bailout(tokenlist, errorLogger, tok, "assignment in condition");
|
bailout(tokenlist, errorLogger, tok, "assignment in condition");
|
||||||
continue;
|
continue;
|
||||||
|
@ -1160,7 +1169,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
if (ok && Token::simpleMatch(top->link(), ") {")) {
|
if (ok && Token::simpleMatch(top->link(), ") {")) {
|
||||||
Token *after = top->link()->linkAt(1);
|
Token *after = top->link()->linkAt(1);
|
||||||
std::string unknownFunction;
|
std::string unknownFunction;
|
||||||
if (settings->library.isScopeNoReturn(after,&unknownFunction)) {
|
if (settings->library.isScopeNoReturn(after, &unknownFunction)) {
|
||||||
if (settings->debugwarnings && !unknownFunction.empty())
|
if (settings->debugwarnings && !unknownFunction.empty())
|
||||||
bailout(tokenlist, errorLogger, after, "possible noreturn scope");
|
bailout(tokenlist, errorLogger, after, "possible noreturn scope");
|
||||||
continue;
|
continue;
|
||||||
|
@ -1187,6 +1196,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execute(const Token *expr,
|
static void execute(const Token *expr,
|
||||||
|
@ -1512,17 +1522,14 @@ static void valueFlowForLoopSimplifyAfter(Token *fortok, unsigned int varid, con
|
||||||
settings);
|
settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void valueFlowForLoop(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowForLoop(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
|
for (std::list<Scope>::const_iterator scope = symboldatabase->scopeList.begin(); scope != symboldatabase->scopeList.end(); ++scope) {
|
||||||
if (!Token::simpleMatch(tok, "for (") ||
|
if (scope->type != Scope::eFor)
|
||||||
!Token::simpleMatch(tok->next()->astOperand2(), ";") ||
|
|
||||||
!Token::simpleMatch(tok->next()->astOperand2()->astOperand2(), ";"))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Token * const bodyStart = tok->linkAt(1)->next();
|
Token* tok = const_cast<Token*>(scope->classDef);
|
||||||
if (!bodyStart || !bodyStart->link() || bodyStart->str() != "{")
|
Token* const bodyStart = const_cast<Token*>(scope->classStart);
|
||||||
continue;
|
|
||||||
|
|
||||||
unsigned int varid(0);
|
unsigned int varid(0);
|
||||||
MathLib::bigint num1(0), num2(0), numAfter(0);
|
MathLib::bigint num1(0), num2(0), numAfter(0);
|
||||||
|
@ -1678,7 +1685,7 @@ static void valueFlowFunctionReturn(TokenList *tokenlist, ErrorLogger *errorLogg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueFlow::setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings)
|
void ValueFlow::setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
|
for (Token *tok = tokenlist->front(); tok; tok = tok->next())
|
||||||
tok->values.clear();
|
tok->values.clear();
|
||||||
|
@ -1688,9 +1695,9 @@ void ValueFlow::setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const
|
||||||
valueFlowPointerAlias(tokenlist);
|
valueFlowPointerAlias(tokenlist);
|
||||||
valueFlowFunctionReturn(tokenlist, errorLogger, settings);
|
valueFlowFunctionReturn(tokenlist, errorLogger, settings);
|
||||||
valueFlowBitAnd(tokenlist);
|
valueFlowBitAnd(tokenlist);
|
||||||
valueFlowForLoop(tokenlist, errorLogger, settings);
|
valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowBeforeCondition(tokenlist, errorLogger, settings);
|
valueFlowBeforeCondition(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowAfterAssign(tokenlist, errorLogger, settings);
|
valueFlowAfterAssign(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowAfterCondition(tokenlist, errorLogger, settings);
|
valueFlowAfterCondition(tokenlist, symboldatabase, errorLogger, settings);
|
||||||
valueFlowSubFunction(tokenlist, errorLogger, settings);
|
valueFlowSubFunction(tokenlist, errorLogger, settings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
class Token;
|
class Token;
|
||||||
class TokenList;
|
class TokenList;
|
||||||
|
class SymbolDatabase;
|
||||||
class ErrorLogger;
|
class ErrorLogger;
|
||||||
class Settings;
|
class Settings;
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ namespace ValueFlow {
|
||||||
bool inconclusive;
|
bool inconclusive;
|
||||||
};
|
};
|
||||||
|
|
||||||
void setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings);
|
void setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // valueflowH
|
#endif // valueflowH
|
||||||
|
|
Loading…
Reference in New Issue