diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 0ffb97645..293e7b6a1 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -135,16 +135,9 @@ const Token * astIsVariableComparison(const Token *tok, const std::string &comp, const Token * nextAfterAstRightmostLeaf(const Token * tok) { - const Token * rightmostLeaf = tok; - if (!rightmostLeaf || !rightmostLeaf->astOperand1()) + if (!tok || !tok->astOperand1()) return nullptr; - do { - if (rightmostLeaf->astOperand2()) - rightmostLeaf = rightmostLeaf->astOperand2(); - else - rightmostLeaf = rightmostLeaf->astOperand1(); - } while (rightmostLeaf->astOperand1()); - return rightmostLeaf->next(); + return tok->findExpressionStartEndTokens().second->next(); } static const Token * getVariableInitExpression(const Variable * var) diff --git a/lib/token.cpp b/lib/token.cpp index 6e3b018f8..bce14ced5 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1166,6 +1166,62 @@ void Token::astOperand2(Token *tok) mAstOperand2 = tok; } +static const Token* goToLeftParenthesis(const Token* start, const Token* end) +{ + // move start to lpar in such expression: '(*it).x' + int par = 0; + for (const Token *tok = start; tok && tok != end; tok = tok->next()) { + if (tok->str() == "(") + ++par; + else if (tok->str() == ")") { + if (par == 0) + start = tok->link(); + else + --par; + } + } + return start; +} + +static const Token* goToRightParenthesis(const Token* start, const Token* end) +{ + // move end to rpar in such expression: '2>(x+1)' + int par = 0; + for (const Token *tok = end; tok && tok != start; tok = tok->previous()) { + if (tok->str() == ")") + ++par; + else if (tok->str() == "(") { + if (par == 0) + end = tok->link(); + else + --par; + } + } + return end; +} + +std::pair Token::findExpressionStartEndTokens() const +{ + const Token * const top = this; + const Token *start = top; + while (start->astOperand1() && + (start->astOperand2() || !start->isUnaryPreOp() || Token::simpleMatch(start, "( )") || start->str() == "{")) + start = start->astOperand1(); + const Token *end = top; + while (end->astOperand1() && (end->astOperand2() || end->isUnaryPreOp())) { + if (Token::Match(end,"(|[") && + !(Token::Match(end, "( %type%") && !end->astOperand2())) { + end = end->link(); + break; + } + end = end->astOperand2() ? end->astOperand2() : end->astOperand1(); + } + + start = goToLeftParenthesis(start, end); + end = goToRightParenthesis(start, end); + return std::pair(start,end); +} + bool Token::isCalculation() const { if (!Token::Match(this, "%cop%|++|--")) @@ -1221,40 +1277,6 @@ bool Token::isUnaryPreOp() const return false; // <- guess } -static const Token* goToLeftParenthesis(const Token* start, const Token* end) -{ - // move start to lpar in such expression: '(*it).x' - int par = 0; - for (const Token *tok = start; tok && tok != end; tok = tok->next()) { - if (tok->str() == "(") - ++par; - else if (tok->str() == ")") { - if (par == 0) - start = tok->link(); - else - --par; - } - } - return start; -} - -static const Token* goToRightParenthesis(const Token* start, const Token* end) -{ - // move end to rpar in such expression: '2>(x+1)' - int par = 0; - for (const Token *tok = end; tok && tok != start; tok = tok->previous()) { - if (tok->str() == ")") - ++par; - else if (tok->str() == "(") { - if (par == 0) - end = tok->link(); - else - --par; - } - } - return end; -} - static std::string stringFromTokenRange(const Token* start, const Token* end) { std::ostringstream ret; @@ -1277,25 +1299,8 @@ static std::string stringFromTokenRange(const Token* start, const Token* end) std::string Token::expressionString() const { - const Token * const top = this; - const Token *start = top; - while (start->astOperand1() && - (start->astOperand2() || !start->isUnaryPreOp() || Token::simpleMatch(start, "( )") || start->str() == "{")) - start = start->astOperand1(); - const Token *end = top; - while (end->astOperand1() && (end->astOperand2() || end->isUnaryPreOp())) { - if (Token::Match(end,"(|[") && - !(Token::Match(end, "( %type%") && !end->astOperand2())) { - end = end->link(); - break; - } - end = end->astOperand2() ? end->astOperand2() : end->astOperand1(); - } - - start = goToLeftParenthesis(start, end); - end = goToRightParenthesis(start, end); - - return stringFromTokenRange(start, end); + const auto tokens = findExpressionStartEndTokens(); + return stringFromTokenRange(tokens.first, tokens.second); } static void astStringXml(const Token *tok, std::size_t indent, std::ostream &out) diff --git a/lib/token.h b/lib/token.h index 9cf9d5886..094597c3e 100644 --- a/lib/token.h +++ b/lib/token.h @@ -1049,6 +1049,8 @@ public: return ret; } + std::pair findExpressionStartEndTokens() const; + /** * Is current token a calculation? Only true for operands. * For '*' and '&' tokens it is looked up if this is a