Fixed #5406 (crash inside valueFlowBeforeCondition() on files from kernel-git)

This commit is contained in:
Daniel Marjamäki 2014-01-27 06:18:42 +01:00
parent 2b8cf462c9
commit c8a1424e10
2 changed files with 101 additions and 71 deletions

View File

@ -686,9 +686,8 @@ static void compileExpression(Token *&tok, std::stack<Token*> &op)
compileComma(tok,op); compileComma(tok,op);
} }
void TokenList::createAst() static Token * createAstAtToken(Token *tok)
{ {
for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) {
if (Token::simpleMatch(tok,"for (")) { if (Token::simpleMatch(tok,"for (")) {
Token *tok2 = tok->tokAt(2); Token *tok2 = tok->tokAt(2);
Token *init1 = 0; Token *init1 = 0;
@ -713,8 +712,7 @@ void TokenList::createAst()
tok->next()->astOperand2(init1); tok->next()->astOperand2(init1);
tok->next()->astOperand1(tok); tok->next()->astOperand1(tok);
} }
tok = tok2; return tok2;
continue;
} }
Token * const init = init1 ? init1 : tok2; Token * const init = init1 ? init1 : tok2;
@ -746,12 +744,34 @@ void TokenList::createAst()
tok->next()->astOperand1(tok); tok->next()->astOperand1(tok);
tok->next()->astOperand2(semicolon1); tok->next()->astOperand2(semicolon1);
tok = tok->linkAt(1); return tok->linkAt(1);
} }
if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|=|::") || Token::Match(tok->previous(), "[;{}] %cop%|(")) {
if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%var% %op%|(|[|.|=|::") || Token::Match(tok->previous(), "[;{}] %cop%|( !!{")) {
std::stack<Token *> operands; std::stack<Token *> operands;
Token * const tok1 = tok;
compileExpression(tok, operands); compileExpression(tok, operands);
Token * const endToken = tok;
// Compile inner expressions inside inner ({..})
for (tok = tok1; tok && tok != endToken; tok = tok ? tok->next() : NULL) {
if (!Token::simpleMatch(tok, "( {"))
continue;
const Token * const endToken2 = tok->linkAt(1);
for (; tok && tok != endToken && tok != endToken2; tok = tok ? tok->next() : NULL)
tok = createAstAtToken(tok);
} }
return endToken ? endToken->previous() : NULL;
}
return tok;
}
void TokenList::createAst()
{
for (Token *tok = _front; tok; tok = tok ? tok->next() : NULL) {
tok = createAstAtToken(tok);
} }
} }

View File

@ -10065,13 +10065,18 @@ private:
// Create AST.. // Create AST..
tokenList.createAst(); tokenList.createAst();
// Return stringified AST
std::string ret;
std::set<const Token *> astTop;
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) { for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
if (tok->astOperand1()) if (tok->astOperand1() && astTop.find(tok->astTop()) == astTop.end()) {
return tok->astTop()->astString(); astTop.insert(tok->astTop());
if (!ret.empty())
ret = ret + " ";
ret += tok->astTop()->astString();
} }
}
// No AST found return ret;
return "";
} }
void astexpr() const { // simple expressions with arithmetical ops void astexpr() const { // simple expressions with arithmetical ops
@ -10108,6 +10113,11 @@ private:
TODO_ASSERT_EQUALS("fori1=current0=,iNUM<=i++;;(", "fori1=current0=,i<NUM=i++;;(", testAst("for(i = (1), current = 0; i <= (NUM); ++i)")); TODO_ASSERT_EQUALS("fori1=current0=,iNUM<=i++;;(", "fori1=current0=,i<NUM=i++;;(", testAst("for(i = (1), current = 0; i <= (NUM); ++i)"));
ASSERT_EQUALS("foreachxy,((", testAst("for(each(x,y)){}")); // it's not well-defined what this ast should be ASSERT_EQUALS("foreachxy,((", testAst("for(each(x,y)){}")); // it's not well-defined what this ast should be
ASSERT_EQUALS("forab:(", testAst("for (int a : b);")); ASSERT_EQUALS("forab:(", testAst("for (int a : b);"));
// problems with multiple expressions
ASSERT_EQUALS("ax( whilex(", testAst("a(x) while (x)"));
ASSERT_EQUALS("ifx( i0= whilei(", testAst("if (x) { ({ int i = 0; while(i); }) };"));
ASSERT_EQUALS("ifx( BUG_ON{!( i0= whilei(", testAst("if (x) { BUG_ON(!({int i=0; while(i);})); }"));
} }
void astpar() const { // parentheses void astpar() const { // parentheses
@ -10126,8 +10136,8 @@ private:
ASSERT_EQUALS("ab::r&c(=", testAst("a::b& r = (a::b&)c;")); // #5261 ASSERT_EQUALS("ab::r&c(=", testAst("a::b& r = (a::b&)c;")); // #5261
// ({..}) // ({..})
ASSERT_EQUALS("a{+d+", testAst("a+({b+c;})+d")); ASSERT_EQUALS("a{+d+ bc+", testAst("a+({b+c;})+d"));
ASSERT_EQUALS("a{d*+", testAst("a+({b+c;})*d")); ASSERT_EQUALS("a{d*+ bc+", testAst("a+({b+c;})*d"));
} }
void astbrackets() const { // [] void astbrackets() const { // []
@ -10162,7 +10172,7 @@ private:
void asttemplate() const { // uninstantiated templates will have <,>,etc.. void asttemplate() const { // uninstantiated templates will have <,>,etc..
ASSERT_EQUALS("a(3==", testAst("a<int>()==3")); ASSERT_EQUALS("a(3==", testAst("a<int>()==3"));
ASSERT_EQUALS("ab(==", testAst("a == b<c>(); f();")); ASSERT_EQUALS("ab(== f(", testAst("a == b<c>(); f();"));
} }
}; };