|
102 | 102 | #include <map> |
103 | 103 | #include <set> |
104 | 104 | #include <stack> |
| 105 | +#include <tuple> |
105 | 106 | #include <vector> |
106 | 107 |
|
107 | 108 | static void bailoutInternal(TokenList *tokenlist, ErrorLogger *errorLogger, const Token *tok, const std::string &what, const std::string &file, int line, const std::string &function) |
@@ -1838,6 +1839,29 @@ static void valueFlowReverse(TokenList *tokenlist, |
1838 | 1839 | } |
1839 | 1840 |
|
1840 | 1841 | if (tok2->str() == "}") { |
| 1842 | + const Token* condTok = getCondTokFromEnd(tok2); |
| 1843 | + // Evaluate condition of for and while loops first |
| 1844 | + if (condTok && condTok->astTop() && Token::Match(condTok->astTop()->previous(), "for|while (")) { |
| 1845 | + const Token* startTok = nullptr; |
| 1846 | + const Token* endTok = nullptr; |
| 1847 | + std::tie(startTok, endTok) = condTok->findExpressionStartEndTokens(); |
| 1848 | + if (!isVariableChanged(startTok, endTok, varid, false, settings, true)) { |
| 1849 | + std::list<ValueFlow::Value> values = {val}; |
| 1850 | + if (val2.condition) { |
| 1851 | + values.push_back(val2); |
| 1852 | + } |
| 1853 | + const Token *expr = Token::findmatch(tok2, "%varid%", varid); |
| 1854 | + valueFlowForward(const_cast<Token*>(startTok), |
| 1855 | + endTok, |
| 1856 | + expr, |
| 1857 | + values, |
| 1858 | + false, |
| 1859 | + false, |
| 1860 | + tokenlist, |
| 1861 | + errorLogger, |
| 1862 | + settings); |
| 1863 | + } |
| 1864 | + } |
1841 | 1865 | const Token *vartok = Token::findmatch(tok2->link(), "%varid%", tok2, varid); |
1842 | 1866 | while (Token::Match(vartok, "%name% = %num% ;") && !vartok->tokAt(2)->getValue(num)) |
1843 | 1867 | vartok = Token::findmatch(vartok->next(), "%varid%", tok2, varid); |
@@ -4089,26 +4113,27 @@ struct ValueFlowConditionHandler { |
4089 | 4113 | // After conditional code.. |
4090 | 4114 | if (Token::simpleMatch(top->link(), ") {")) { |
4091 | 4115 | Token *after = top->link()->linkAt(1); |
4092 | | - std::string unknownFunction; |
4093 | | - if (settings->library.isScopeNoReturn(after, &unknownFunction)) { |
4094 | | - if (settings->debugwarnings && !unknownFunction.empty()) |
4095 | | - bailout(tokenlist, errorLogger, after, "possible noreturn scope"); |
4096 | | - continue; |
4097 | | - } |
4098 | | - |
4099 | | - bool dead_if = isReturnScope(after, &settings->library) || |
| 4116 | + const Token* unknownFunction = nullptr; |
| 4117 | + bool dead_if = isReturnScope(after, &settings->library, &unknownFunction) || |
4100 | 4118 | (tok->astParent() && Token::simpleMatch(tok->astParent()->previous(), "while (") && |
4101 | 4119 | !isBreakScope(after)); |
4102 | 4120 | bool dead_else = false; |
4103 | 4121 |
|
| 4122 | + if (!dead_if && unknownFunction) { |
| 4123 | + if (settings->debugwarnings) |
| 4124 | + bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope"); |
| 4125 | + continue; |
| 4126 | + } |
| 4127 | + |
4104 | 4128 | if (Token::simpleMatch(after, "} else {")) { |
4105 | 4129 | after = after->linkAt(2); |
4106 | | - if (Token::simpleMatch(after->tokAt(-2), ") ; }")) { |
| 4130 | + unknownFunction = nullptr; |
| 4131 | + dead_else = isReturnScope(after, &settings->library, &unknownFunction); |
| 4132 | + if (!dead_else && unknownFunction) { |
4107 | 4133 | if (settings->debugwarnings) |
4108 | | - bailout(tokenlist, errorLogger, after, "possible noreturn scope"); |
| 4134 | + bailout(tokenlist, errorLogger, unknownFunction, "possible noreturn scope"); |
4109 | 4135 | continue; |
4110 | 4136 | } |
4111 | | - dead_else = isReturnScope(after, &settings->library); |
4112 | 4137 | } |
4113 | 4138 |
|
4114 | 4139 | if (dead_if && dead_else) |
|
0 commit comments