Skip to content

Commit 141e089

Browse files
committed
ast: different handling of for loops. create a syntax tree for whole 'f(a;b;c)'.
1 parent d43191a commit 141e089

3 files changed

Lines changed: 70 additions & 21 deletions

File tree

lib/tokenlist.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,58 @@ static void compileExpression(Token *&tok, std::stack<Token*> &op)
687687
void TokenList::createAst()
688688
{
689689
for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) {
690+
if (Token::simpleMatch(tok,"for (")) {
691+
std::stack<Token *> operands;
692+
Token *tok2 = tok->tokAt(2);
693+
Token *init1 = 0;
694+
while (tok2 && tok2->str() != ";") {
695+
if (tok2->str() == "<" && tok2->link()) {
696+
tok2 = tok2->link();
697+
if (!tok2)
698+
break;
699+
} else if (Token::Match(tok2, "%var% %op%|(|[|.|=|::") || Token::Match(tok2->previous(), "[;{}] %cop%|(")) {
700+
init1 = tok2;
701+
compileExpression(tok2, operands);
702+
if (tok2->str() == ";")
703+
break;
704+
init1 = 0;
705+
}
706+
tok2 = tok2->next();
707+
}
708+
if (!tok2 || tok2->str() != ";") {
709+
tok = tok->next();
710+
continue;
711+
}
712+
713+
Token * const init = init1 ? init1 : tok2;
714+
715+
Token * const semicolon1 = tok2;
716+
tok2 = tok2->next();
717+
compileExpression(tok2, operands);
718+
719+
Token * const semicolon2 = tok2;
720+
tok2 = tok2->next();
721+
compileExpression(tok2, operands);
722+
723+
if (init != semicolon1)
724+
semicolon1->astOperand1(init);
725+
tok2 = semicolon1->next();
726+
while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber())
727+
tok2 = tok2->next();
728+
if (tok2 != semicolon2)
729+
semicolon2->astOperand1(tok2);
730+
tok2 = tok->linkAt(1);
731+
while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber())
732+
tok2 = tok2->previous();
733+
if (tok2 != semicolon2)
734+
semicolon2->astOperand2(tok2);
735+
736+
semicolon1->astOperand2(semicolon2);
737+
tok->next()->astOperand1(tok);
738+
tok->next()->astOperand2(semicolon1);
739+
740+
tok = tok->linkAt(1);
741+
}
690742
if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|=|::") || Token::Match(tok->previous(), "[;{}] %cop%|(")) {
691743
std::stack<Token *> operands;
692744
compileExpression(tok, operands);

lib/valueflow.cpp

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -159,33 +159,26 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
159159
}
160160

161161
// bailout: while-condition, variable is changed in while loop
162-
for (const Token *tok2 = tok; tok2; tok2 = tok2->previous()) {
163-
if (tok2->str() == ")")
164-
tok2 = tok2->link();
165-
166-
else if (tok2->str() == "(" && Token::simpleMatch(tok2->link(), ") {")) {
167-
if (Token::Match(tok2->previous(), "for|while (")) {
168-
const Token *start = tok2->link()->next();
169-
const Token *end = start->link();
170-
if (Token::findmatch(start,"++|--| %varid% ++|--|=",end,varid)) {
171-
varid = 0U;
172-
if (settings->debugwarnings)
173-
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + " used in loop");
174-
}
175-
}
162+
for (const Token *tok2 = tok; tok2; tok2 = tok2->astParent()) {
163+
if (tok2->astParent() || tok2->str() != "(" || !Token::simpleMatch(tok2->link(), ") {"))
164+
continue;
176165

177-
// if,macro => bailout
178-
else if (Token::simpleMatch(tok2->previous(), "if (") && tok2->previous()->isExpandedMacro()) {
166+
if (Token::Match(tok2->previous(), "for|while (")) {
167+
const Token *start = tok2->link()->next();
168+
const Token *end = start->link();
169+
if (Token::findmatch(start,"++|--| %varid% ++|--|=",end,varid)) {
179170
varid = 0U;
180171
if (settings->debugwarnings)
181-
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + ", condition is defined in macro");
172+
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + " used in loop");
182173
}
183-
184-
break;
185174
}
186175

187-
else if (Token::Match(tok2, "[{}]"))
188-
break;
176+
// if,macro => bailout
177+
else if (Token::simpleMatch(tok2->previous(), "if (") && tok2->previous()->isExpandedMacro()) {
178+
varid = 0U;
179+
if (settings->debugwarnings)
180+
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + ", condition is defined in macro");
181+
}
189182
}
190183
if (varid == 0U)
191184
continue;

test/testtokenize.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10098,6 +10098,10 @@ class TestTokenizer : public TestFixture {
1009810098

1009910099
ASSERT_EQUALS("a0>bc/?d:", testAst("(a>0) ? (b/(c)) : d;"));
1010010100
ASSERT_EQUALS("abc/+d+", testAst("a + (b/(c)) + d;"));
10101+
10102+
// for
10103+
ASSERT_EQUALS("for;;(", testAst("for(;;)"));
10104+
ASSERT_EQUALS("fora0=a8<a++;;(", testAst("for(a=0;a<8;a++)"));
1010110105
}
1010210106

1010310107
void astpar() const { // parentheses

0 commit comments

Comments
 (0)