From 1e3c43e708ed613ed26ad52110e34216c70cd3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 8 Jan 2014 06:39:15 +0100 Subject: [PATCH] value flow: improved bailouts in ?: --- lib/valueflow.cpp | 17 +++++++++++------ test/testvalueflow.cpp | 25 ++++++++++++++++++++----- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 53795bc66..db48285df 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -50,7 +50,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog unsigned int varid; MathLib::bigint num; 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()) { varid = tok->astOperand1()->varId(); var = tok->astOperand1()->variable(); @@ -62,11 +62,6 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog } else { 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%|&&|)") || Token::Match(tok, "%oror%|&& %var% %oror%|&&|)")) { varid = tok->next()->varId(); @@ -111,6 +106,16 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog 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); if (var && tok2 == var->nameToken()) break; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index d8a04f6cf..71904b601 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -76,17 +76,32 @@ private: void valueFlowBeforeCondition() { - const char code[] = "void f(int x) {\n" - " int a = x;\n" - " if (x == 123) {}\n" - "}"; + const char *code; + + code = "void f(int x) {\n" + " int a = x;\n" + " if (x == 123) {}\n" + "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 123)); // bailout: ?: bailout("void f(int x) {\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("void f(int x) {\n"