diff --git a/lib/astutils.cpp b/lib/astutils.cpp index c91f41d9651..600b888e44e 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2482,13 +2482,6 @@ static bool isArray(const Token* tok) return false; } -static inline -// limit it to CLang as compiling with GCC might fail with -// error: inlining failed in call to always_inline 'bool isMutableExpression(const Token*)': function not considered for inlining -// error: inlining failed in call to ‘always_inline’ ‘bool isMutableExpression(const Token*)’: recursive inlining -#if defined(__clang__) -__attribute__((always_inline)) -#endif bool isMutableExpression(const Token* tok) { if (!tok) @@ -2632,7 +2625,9 @@ static bool hasOverloadedMemberAccess(const Token* tok) bool isVariableChanged(const Token *tok, int indirect, const Settings &settings, int depth) { - if (!isMutableExpression(tok)) + if (!tok) + return false; + if (!tok->isMutableExpr()) return false; if (indirect == 0 && isConstVarExpression(tok)) @@ -2924,7 +2919,9 @@ static bool isExpressionChangedAt(const F& getExprTok, { if (depth < 0) return true; - if (!isMutableExpression(tok)) + if (!tok) + return false; + if (!tok->isMutableExpr()) return false; if (tok->exprId() != exprid || (!tok->varId() && !tok->isName())) { if (globalvar && Token::Match(tok, "%name% (") && diff --git a/lib/astutils.h b/lib/astutils.h index 06f01acab11..4002e065ab5 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -319,6 +319,8 @@ Token* getTokenArgumentFunction(Token* tok, int& argn); std::vector getArgumentVars(const Token* tok, int argnr); +bool isMutableExpression(const Token* tok); + /** Is variable changed by function call? * In case the answer of the question is inconclusive, e.g. because the function declaration is not known * the return value is false and the output parameter inconclusive is set to true diff --git a/lib/token.cpp b/lib/token.cpp index 5633f291083..f55fcc14830 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2753,3 +2753,10 @@ const SmallVector& Token::refs(bool temporary) const mImpl->mRefs.reset(new SmallVector(followAllReferences(this, false))); return *mImpl->mRefs; } + +bool Token::isMutableExpr() const +{ + if (mImpl->mMutableExpr == -1) + mImpl->mMutableExpr = isMutableExpression(this); + return !!mImpl->mMutableExpr; +} diff --git a/lib/token.h b/lib/token.h index d26c7ac7640..5cf427974c4 100644 --- a/lib/token.h +++ b/lib/token.h @@ -173,6 +173,8 @@ class CPPCHECKLIB Token { std::unique_ptr> mRefs; std::unique_ptr> mRefsTemp; + std::int8_t mMutableExpr{-1}; + void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value); bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const; @@ -1364,6 +1366,8 @@ class CPPCHECKLIB Token { // provides and caches result of a followAllReferences() call const SmallVector& refs(bool temporary = true) const; + bool isMutableExpr() const; + /** * Sets the original name. */