value flow: improved bailouts in ?:

This commit is contained in:
Daniel Marjamäki 2014-01-08 06:39:15 +01:00
parent 7cfa4c8654
commit 1e3c43e708
2 changed files with 31 additions and 11 deletions

View File

@ -50,7 +50,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
unsigned int varid; unsigned int varid;
MathLib::bigint num; MathLib::bigint num;
const Variable *var; const Variable *var;
if (Token::Match(tok, "==|!=|>=|<=") && tok->astOperand1() && tok->astOperand2()) { if (tok->isComparisonOp() && tok->astOperand1() && tok->astOperand2()) {
if (tok->astOperand1()->isName() && tok->astOperand2()->isNumber()) { if (tok->astOperand1()->isName() && tok->astOperand2()->isNumber()) {
varid = tok->astOperand1()->varId(); varid = tok->astOperand1()->varId();
var = tok->astOperand1()->variable(); var = tok->astOperand1()->variable();
@ -62,11 +62,6 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
} else { } else {
continue; continue;
} }
if (Token::Match(tok->astParent(), "[?:]")) {
if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + " stopping on " + tok->astParent()->str());
continue;
}
} else if (Token::Match(tok->previous(), "if|while ( %var% %oror%|&&|)") || } else if (Token::Match(tok->previous(), "if|while ( %var% %oror%|&&|)") ||
Token::Match(tok, "%oror%|&& %var% %oror%|&&|)")) { Token::Match(tok, "%oror%|&& %var% %oror%|&&|)")) {
varid = tok->next()->varId(); varid = tok->next()->varId();
@ -111,6 +106,16 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
break; break;
} }
// skip if variable is conditionally used in ?: expression.
const Token *parent = tok2->astParent();
while (parent && !Token::Match(parent, "[?:]"))
parent = parent->astParent();
if (parent) {
if (settings->debugwarnings)
bailout(tokenlist, errorLogger, tok2, "no simplification of " + tok2->str() + " within ?: expression");
continue;
}
tok2->values.push_back(val); tok2->values.push_back(val);
if (var && tok2 == var->nameToken()) if (var && tok2 == var->nameToken())
break; break;

View File

@ -76,7 +76,9 @@ private:
void valueFlowBeforeCondition() { void valueFlowBeforeCondition() {
const char code[] = "void f(int x) {\n" const char *code;
code = "void f(int x) {\n"
" int a = x;\n" " int a = x;\n"
" if (x == 123) {}\n" " if (x == 123) {}\n"
"}"; "}";
@ -86,7 +88,20 @@ private:
bailout("void f(int x) {\n" bailout("void f(int x) {\n"
" y = ((x<0) ? x : ((x==2)?3:4));\n" " y = ((x<0) ? x : ((x==2)?3:4));\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: variable x stopping on :\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: no simplification of x within ?: expression\n", errout.str());
bailout("int f(int x) {\n"
" int r = x ? 1 / x : 0;\n"
" if (x == 0) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (debug) ValueFlow bailout: no simplification of x within ?: expression\n", errout.str());
code = "void f(int x) {\n"
" int a = x;\n"
" a = b ? x/2 : 20/x;\n"
" if (x == 123) {}\n"
"}";
ASSERT_EQUALS(true, testValueOfX(code, 2U, 123));
// bailout: if/else/etc // bailout: if/else/etc
bailout("void f(int x) {\n" bailout("void f(int x) {\n"