Fixed two bugs in AST compilation (#5830):
- Correctly parse operators .* and ->* - Support empty branch in ternary expression (a?:c)
This commit is contained in:
parent
5c566e838c
commit
d1c4777053
|
@ -1094,19 +1094,27 @@ std::string Token::stringifyList(bool varid) const
|
|||
|
||||
void Token::astOperand1(Token *tok)
|
||||
{
|
||||
if (_astOperand1)
|
||||
_astOperand1->_astParent = nullptr;
|
||||
// goto parent operator
|
||||
if (tok) {
|
||||
while (tok->_astParent)
|
||||
tok = tok->_astParent;
|
||||
tok->_astParent = this;
|
||||
}
|
||||
_astOperand1 = tok;
|
||||
}
|
||||
|
||||
void Token::astOperand2(Token *tok)
|
||||
{
|
||||
if (_astOperand2)
|
||||
_astOperand2->_astParent = nullptr;
|
||||
// goto parent operator
|
||||
if (tok) {
|
||||
while (tok->_astParent)
|
||||
tok = tok->_astParent;
|
||||
tok->_astParent = this;
|
||||
}
|
||||
_astOperand2 = tok;
|
||||
}
|
||||
|
||||
|
|
|
@ -473,7 +473,7 @@ static void compileScope(Token *&tok, std::stack<Token*> &op, unsigned int depth
|
|||
static bool isPrefixUnary(const Token* tok)
|
||||
{
|
||||
if (!tok->previous()
|
||||
|| (Token::Match(tok->previous(), "(|[|{|%op%|;|}|?|:|,|return|throw")
|
||||
|| (Token::Match(tok->previous(), "(|[|{|%op%|;|}|?|:|,|.|return|throw")
|
||||
&& (tok->previous()->type() != Token::eIncDecOp || tok->type() == Token::eIncDecOp)))
|
||||
return true;
|
||||
|
||||
|
@ -486,7 +486,7 @@ static void compilePrecedence2(Token *&tok, std::stack<Token*> &op, unsigned int
|
|||
while (tok) {
|
||||
if (tok->type() == Token::eIncDecOp && !isPrefixUnary(tok)) {
|
||||
compileUnaryOp(tok, compileScope, op, depth);
|
||||
} else if (tok->str() == ".") {
|
||||
} else if (tok->str() == "." && tok->strAt(1) != "*") {
|
||||
compileBinOp(tok, compileScope, op, depth);
|
||||
} else if (tok->str() == "[") {
|
||||
Token* tok2 = tok;
|
||||
|
@ -530,9 +530,19 @@ static void compilePrecedence3(Token *&tok, std::stack<Token*> &op, unsigned int
|
|||
}
|
||||
}
|
||||
|
||||
static void compileMulDiv(Token *&tok, std::stack<Token*> &op, unsigned int depth)
|
||||
static void compilePointerToElem(Token *&tok, std::stack<Token*> &op, unsigned int depth)
|
||||
{
|
||||
compilePrecedence3(tok, op, depth);
|
||||
while (tok) {
|
||||
if (Token::simpleMatch(tok, ". *")) {
|
||||
compileBinOp(tok, compilePrecedence3, op, depth);
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
static void compileMulDiv(Token *&tok, std::stack<Token*> &op, unsigned int depth)
|
||||
{
|
||||
compilePointerToElem(tok, op, depth);
|
||||
while (tok) {
|
||||
if (Token::Match(tok, "[*/%]")) {
|
||||
if (Token::Match(tok, "* [*,)]")) {
|
||||
|
@ -540,11 +550,10 @@ static void compileMulDiv(Token *&tok, std::stack<Token*> &op, unsigned int dept
|
|||
while (tok2->next() && tok2->str() == "*")
|
||||
tok2 = tok2->next();
|
||||
if (Token::Match(tok2, "[,)]")) {
|
||||
//tok = tok2->next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
compileBinOp(tok, compilePrecedence3, op, depth);
|
||||
compileBinOp(tok, compilePointerToElem, op, depth);
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
@ -646,6 +655,9 @@ static void compileAssignTernary(Token *&tok, std::stack<Token*> &op, unsigned i
|
|||
// TODO: http://en.cppreference.com/w/cpp/language/operator_precedence says:
|
||||
// "The expression in the middle of the conditional operator (between ? and :) is parsed as if parenthesized: its precedence relative to ?: is ignored."
|
||||
if (tok->isAssignmentOp() || Token::Match(tok, "[?:]")) {
|
||||
if (tok->str() == "?" && tok->strAt(1) == ":") {
|
||||
op.push(0);
|
||||
}
|
||||
compileBinOp(tok, compileAssignTernary, op, depth);
|
||||
} else break;
|
||||
}
|
||||
|
|
|
@ -10384,7 +10384,7 @@ private:
|
|||
|
||||
// Basic AST validation
|
||||
for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
||||
if (tok->astOperand2() && !tok->astOperand1() && tok->str() != ";")
|
||||
if (tok->astOperand2() && !tok->astOperand1() && tok->str() != ";" && tok->str() != ":")
|
||||
return "Op2 but no Op1 for token: " + tok->str();
|
||||
}
|
||||
|
||||
|
@ -10433,6 +10433,8 @@ private:
|
|||
ASSERT_EQUALS("ab|=", testAst("a|=b;"));
|
||||
ASSERT_EQUALS("ab^=", testAst("a^=b;"));
|
||||
|
||||
ASSERT_EQUALS("ab*c*.(+return", testAst("return a + ((*b).*c)();"));
|
||||
|
||||
// assignments are executed from right to left
|
||||
ASSERT_EQUALS("abc==", testAst("a=b=c;"));
|
||||
|
||||
|
@ -10465,6 +10467,9 @@ private:
|
|||
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);})); }"));
|
||||
ASSERT_EQUALS("v0= while{( v0= while{( v0=", testAst("({ v = 0; }); while (({ v = 0; }) != 0); while (({ v = 0; }) != 0);"));
|
||||
|
||||
|
||||
ASSERT_EQUALS("abc.1:?1+bd.1:?+=", testAst("a =(b.c ? : 1) + 1 + (b.d ? : 1);"));
|
||||
}
|
||||
|
||||
void astpar() const { // parentheses
|
||||
|
|
Loading…
Reference in New Issue