ast: different handling of for loops. create a syntax tree for whole 'f(a;b;c)'.
This commit is contained in:
parent
d43191a9e3
commit
141e089329
|
@ -687,6 +687,58 @@ static void compileExpression(Token *&tok, std::stack<Token*> &op)
|
|||
void TokenList::createAst()
|
||||
{
|
||||
for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) {
|
||||
if (Token::simpleMatch(tok,"for (")) {
|
||||
std::stack<Token *> operands;
|
||||
Token *tok2 = tok->tokAt(2);
|
||||
Token *init1 = 0;
|
||||
while (tok2 && tok2->str() != ";") {
|
||||
if (tok2->str() == "<" && tok2->link()) {
|
||||
tok2 = tok2->link();
|
||||
if (!tok2)
|
||||
break;
|
||||
} else if (Token::Match(tok2, "%var% %op%|(|[|.|=|::") || Token::Match(tok2->previous(), "[;{}] %cop%|(")) {
|
||||
init1 = tok2;
|
||||
compileExpression(tok2, operands);
|
||||
if (tok2->str() == ";")
|
||||
break;
|
||||
init1 = 0;
|
||||
}
|
||||
tok2 = tok2->next();
|
||||
}
|
||||
if (!tok2 || tok2->str() != ";") {
|
||||
tok = tok->next();
|
||||
continue;
|
||||
}
|
||||
|
||||
Token * const init = init1 ? init1 : tok2;
|
||||
|
||||
Token * const semicolon1 = tok2;
|
||||
tok2 = tok2->next();
|
||||
compileExpression(tok2, operands);
|
||||
|
||||
Token * const semicolon2 = tok2;
|
||||
tok2 = tok2->next();
|
||||
compileExpression(tok2, operands);
|
||||
|
||||
if (init != semicolon1)
|
||||
semicolon1->astOperand1(init);
|
||||
tok2 = semicolon1->next();
|
||||
while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber())
|
||||
tok2 = tok2->next();
|
||||
if (tok2 != semicolon2)
|
||||
semicolon2->astOperand1(tok2);
|
||||
tok2 = tok->linkAt(1);
|
||||
while (tok2 != semicolon2 && !tok2->isName() && !tok2->isNumber())
|
||||
tok2 = tok2->previous();
|
||||
if (tok2 != semicolon2)
|
||||
semicolon2->astOperand2(tok2);
|
||||
|
||||
semicolon1->astOperand2(semicolon2);
|
||||
tok->next()->astOperand1(tok);
|
||||
tok->next()->astOperand2(semicolon1);
|
||||
|
||||
tok = tok->linkAt(1);
|
||||
}
|
||||
if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|=|::") || Token::Match(tok->previous(), "[;{}] %cop%|(")) {
|
||||
std::stack<Token *> operands;
|
||||
compileExpression(tok, operands);
|
||||
|
|
|
@ -159,33 +159,26 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog
|
|||
}
|
||||
|
||||
// bailout: while-condition, variable is changed in while loop
|
||||
for (const Token *tok2 = tok; tok2; tok2 = tok2->previous()) {
|
||||
if (tok2->str() == ")")
|
||||
tok2 = tok2->link();
|
||||
for (const Token *tok2 = tok; tok2; tok2 = tok2->astParent()) {
|
||||
if (tok2->astParent() || tok2->str() != "(" || !Token::simpleMatch(tok2->link(), ") {"))
|
||||
continue;
|
||||
|
||||
else if (tok2->str() == "(" && Token::simpleMatch(tok2->link(), ") {")) {
|
||||
if (Token::Match(tok2->previous(), "for|while (")) {
|
||||
const Token *start = tok2->link()->next();
|
||||
const Token *end = start->link();
|
||||
if (Token::findmatch(start,"++|--| %varid% ++|--|=",end,varid)) {
|
||||
varid = 0U;
|
||||
if (settings->debugwarnings)
|
||||
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + " used in loop");
|
||||
}
|
||||
}
|
||||
|
||||
// if,macro => bailout
|
||||
else if (Token::simpleMatch(tok2->previous(), "if (") && tok2->previous()->isExpandedMacro()) {
|
||||
if (Token::Match(tok2->previous(), "for|while (")) {
|
||||
const Token *start = tok2->link()->next();
|
||||
const Token *end = start->link();
|
||||
if (Token::findmatch(start,"++|--| %varid% ++|--|=",end,varid)) {
|
||||
varid = 0U;
|
||||
if (settings->debugwarnings)
|
||||
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + ", condition is defined in macro");
|
||||
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + " used in loop");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
else if (Token::Match(tok2, "[{}]"))
|
||||
break;
|
||||
// if,macro => bailout
|
||||
else if (Token::simpleMatch(tok2->previous(), "if (") && tok2->previous()->isExpandedMacro()) {
|
||||
varid = 0U;
|
||||
if (settings->debugwarnings)
|
||||
bailout(tokenlist, errorLogger, tok, "variable " + var->nameToken()->str() + ", condition is defined in macro");
|
||||
}
|
||||
}
|
||||
if (varid == 0U)
|
||||
continue;
|
||||
|
|
|
@ -10098,6 +10098,10 @@ private:
|
|||
|
||||
ASSERT_EQUALS("a0>bc/?d:", testAst("(a>0) ? (b/(c)) : d;"));
|
||||
ASSERT_EQUALS("abc/+d+", testAst("a + (b/(c)) + d;"));
|
||||
|
||||
// for
|
||||
ASSERT_EQUALS("for;;(", testAst("for(;;)"));
|
||||
ASSERT_EQUALS("fora0=a8<a++;;(", testAst("for(a=0;a<8;a++)"));
|
||||
}
|
||||
|
||||
void astpar() const { // parentheses
|
||||
|
|
Loading…
Reference in New Issue