This commit is contained in:
Paul 2020-09-10 17:06:49 -05:00
parent bb9dbaa8f5
commit 4d1b3e06c7
2 changed files with 39 additions and 5 deletions

View File

@ -10,9 +10,19 @@
struct ForwardTraversal { struct ForwardTraversal {
enum class Progress { Continue, Break, Skip }; enum class Progress { Continue, Break, Skip };
ForwardTraversal(const ValuePtr<ForwardAnalyzer>& analyzer, const Settings* settings)
: analyzer(analyzer), settings(settings), actions(ForwardAnalyzer::Action::None), analyzeOnly(false)
{}
ValuePtr<ForwardAnalyzer> analyzer; ValuePtr<ForwardAnalyzer> analyzer;
const Settings* settings; const Settings* settings;
ForwardAnalyzer::Action actions; ForwardAnalyzer::Action actions;
bool analyzeOnly;
bool stopUpdates()
{
analyzeOnly = true;
return actions.isModified();
}
std::pair<bool, bool> evalCond(const Token* tok) { std::pair<bool, bool> evalCond(const Token* tok) {
std::vector<int> result = analyzer->evaluate(tok); std::vector<int> result = analyzer->evaluate(tok);
@ -92,7 +102,7 @@ struct ForwardTraversal {
std::tie(checkThen, checkElse) = evalCond(condTok); std::tie(checkThen, checkElse) = evalCond(condTok);
if (!checkThen && !checkElse) { if (!checkThen && !checkElse) {
// Stop if the value is conditional // Stop if the value is conditional
if (!traverseUnknown && analyzer->isConditional()) if (!traverseUnknown && analyzer->isConditional() && stopUpdates())
return Progress::Break; return Progress::Break;
checkThen = true; checkThen = true;
checkElse = true; checkElse = true;
@ -117,7 +127,7 @@ struct ForwardTraversal {
Progress update(Token* tok) { Progress update(Token* tok) {
ForwardAnalyzer::Action action = analyzer->analyze(tok); ForwardAnalyzer::Action action = analyzer->analyze(tok);
actions |= action; actions |= action;
if (!action.isNone()) if (!action.isNone() && !analyzeOnly)
analyzer->update(tok, action); analyzer->update(tok, action);
if (action.isInconclusive() && !analyzer->lowerToInconclusive()) if (action.isInconclusive() && !analyzer->lowerToInconclusive())
return Progress::Break; return Progress::Break;
@ -402,6 +412,7 @@ struct ForwardTraversal {
} else { } else {
tok = endBlock; tok = endBlock;
} }
actions |= (thenAction | elseAction);
if (bail) if (bail)
return Progress::Break; return Progress::Break;
if (returnThen && returnElse) if (returnThen && returnElse)
@ -415,7 +426,7 @@ struct ForwardTraversal {
if (checkThen) { if (checkThen) {
return Progress::Break; return Progress::Break;
} else { } else {
if (analyzer->isConditional()) if (analyzer->isConditional() && stopUpdates())
return Progress::Break; return Progress::Break;
analyzer->assume(condTok, false); analyzer->assume(condTok, false);
} }
@ -424,7 +435,7 @@ struct ForwardTraversal {
if (!analyzer->lowerToInconclusive()) if (!analyzer->lowerToInconclusive())
return Progress::Break; return Progress::Break;
} else if (thenAction.isModified() || elseAction.isModified()) { } else if (thenAction.isModified() || elseAction.isModified()) {
if (!hasElse && analyzer->isConditional()) if (!hasElse && analyzer->isConditional() && stopUpdates())
return Progress::Break; return Progress::Break;
if (!analyzer->lowerToPossible()) if (!analyzer->lowerToPossible())
return Progress::Break; return Progress::Break;

View File

@ -2424,6 +2424,29 @@ private:
" }" " }"
"}"; "}";
ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 2)); ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 2));
code = "int f(int i, int j) {\n"
" if (i == 0) {\n"
" if (j < 0)\n"
" return 0;\n"
" i = j+1;\n"
" }\n"
" int x = i;\n"
" return x;\n"
"}\n";
ASSERT_EQUALS(false, testValueOfX(code, 8U, 0));
code = "int f(int i, int j) {\n"
" if (i == 0) {\n"
" if (j < 0)\n"
" return 0;\n"
" if (j < 0)\n"
" i = j+1;\n"
" }\n"
" int x = i;\n"
" return x;\n"
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 9U, 0));
} }
void valueFlowAfterConditionExpr() { void valueFlowAfterConditionExpr() {