astutils: Add function that visits nodes in AST tree
This commit is contained in:
parent
c181d28b1a
commit
ecb3c04fba
|
@ -28,7 +28,30 @@
|
|||
#include "valueflow.h"
|
||||
|
||||
#include <list>
|
||||
#include <functional>
|
||||
#include <stack>
|
||||
|
||||
|
||||
void visitAstNodes(const Token *ast, std::function<ChildrenToVisit(const Token *)> visitor)
|
||||
{
|
||||
std::stack<const Token *> tokens;
|
||||
tokens.push(ast);
|
||||
while (!tokens.empty()) {
|
||||
const Token *tok = tokens.top();
|
||||
tokens.pop();
|
||||
if (!tok)
|
||||
continue;
|
||||
|
||||
ChildrenToVisit c = visitor(tok);
|
||||
|
||||
if (c == ChildrenToVisit::done)
|
||||
break;
|
||||
if (c == ChildrenToVisit::op1 || c == ChildrenToVisit::op1_and_op2)
|
||||
tokens.push(tok->astOperand1());
|
||||
if (c == ChildrenToVisit::op1 || c == ChildrenToVisit::op1_and_op2)
|
||||
tokens.push(tok->astOperand2());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool astIsCharWithSign(const Token *tok, ValueType::Sign sign)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define astutilsH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -32,6 +33,19 @@ class Settings;
|
|||
class Token;
|
||||
class Variable;
|
||||
|
||||
enum class ChildrenToVisit {
|
||||
none,
|
||||
op1,
|
||||
op2,
|
||||
op1_and_op2,
|
||||
done // found what we looked for, don't visit any more children
|
||||
};
|
||||
|
||||
/**
|
||||
* Visit AST nodes recursively. The order is not "well defined"
|
||||
*/
|
||||
void visitAstNodes(const Token *ast, std::function<ChildrenToVisit(const Token *)> visitor);
|
||||
|
||||
/** Is expression a 'signed char' if no promotion is used */
|
||||
bool astIsSignedChar(const Token *tok);
|
||||
/** Is expression a 'char' if no promotion is used? */
|
||||
|
|
|
@ -594,28 +594,24 @@ void CheckOther::checkRedundantAssignment()
|
|||
bool error = oldeq && eq->astOperand1() && isSameExpression(mTokenizer->isCPP(), true, eq->astOperand1(), oldeq->astOperand1(), mSettings->library, true, false);
|
||||
|
||||
// Ensure that variable is not used on right side
|
||||
std::stack<const Token *> tokens;
|
||||
tokens.push(eq->astOperand2());
|
||||
while (!tokens.empty()) {
|
||||
const Token *rhs = tokens.top();
|
||||
tokens.pop();
|
||||
if (!rhs)
|
||||
continue;
|
||||
tokens.push(rhs->astOperand1());
|
||||
tokens.push(rhs->astOperand2());
|
||||
visitAstNodes(eq->astOperand2(),
|
||||
[&](const Token *rhs) {
|
||||
if (rhs->varId() == tok->varId()) {
|
||||
error = false;
|
||||
break;
|
||||
return ChildrenToVisit::done;
|
||||
}
|
||||
|
||||
if (Token::Match(rhs->previous(), "%name% (") && nonLocalVolatile(tok->variable())) { // Called function might use the variable
|
||||
const Function* const func = rhs->function();
|
||||
const Variable* const var = tok->variable();
|
||||
if (!var || var->isGlobal() || var->isReference() || ((!func || func->nestedIn) && rhs->strAt(-1) != ".")) {// Global variable, or member function
|
||||
error = false;
|
||||
break;
|
||||
return ChildrenToVisit::done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ChildrenToVisit::op1_and_op2;
|
||||
});
|
||||
|
||||
if (error) {
|
||||
if (printWarning && scope.type == Scope::eSwitch && Token::findmatch(it->second, "default|case", tok))
|
||||
|
|
Loading…
Reference in New Issue