From 00d32fe377d7b5cd820e798afc6a4dbd0b798dfb Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 17 Sep 2025 10:37:32 +0200 Subject: [PATCH 1/3] Token: do not rely on `TokenImpl` in interface --- lib/checkleakautovar.cpp | 2 +- lib/token.cpp | 6 +++--- lib/token.h | 24 +++++++++++++---------- lib/tokenize.cpp | 12 ++++++------ lib/tokenlist.cpp | 8 ++++---- lib/valueflow.cpp | 4 ++-- test/testtokenize.cpp | 42 ++++++++++++++++++++-------------------- 7 files changed, 51 insertions(+), 47 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 17f5629b009..d129e954075 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -396,7 +396,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, } } - if (tok->isCpp11init() == TokenImpl::Cpp11init::CPP11INIT) { + if (tok->isCpp11init() == Cpp11init::CPP11INIT) { const Token *newTok = tok->astOperand1(); const Token *oldTok = tok->astOperand2(); if (newTok && newTok->varId() && oldTok && oldTok->varId()) { diff --git a/lib/token.cpp b/lib/token.cpp index 8313305c2c8..7dd16810fdc 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -58,7 +58,7 @@ namespace { }; } -const std::list TokenImpl::mEmptyValueList; +const std::list Token::mEmptyValueList; const std::string Token::mEmptyString; Token::Token(const TokenList& tokenlist, std::shared_ptr tokensFrontBack) @@ -2663,7 +2663,7 @@ TokenImpl::~TokenImpl() } } -void TokenImpl::setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) +void TokenImpl::setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value) { CppcheckAttributes *attr = mCppcheckAttributes; while (attr && attr->type != type) @@ -2679,7 +2679,7 @@ void TokenImpl::setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, M } } -bool TokenImpl::getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint &value) const +bool TokenImpl::getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const { CppcheckAttributes *attr = mCppcheckAttributes; while (attr && attr->type != type) diff --git a/lib/token.h b/lib/token.h index 6ef14af33c1..dc3d4006c99 100644 --- a/lib/token.h +++ b/lib/token.h @@ -63,6 +63,10 @@ struct ScopeInfo2 { enum class TokenDebug : std::uint8_t { None, ValueFlow, ValueType }; +// TODO: move these to Token when TokenImpl has been moved into the implementation +enum CppcheckAttributesType : std::uint8_t { LOW, HIGH }; +enum class Cpp11init : std::uint8_t { UNKNOWN, CPP11INIT, NOINIT }; + struct TokenImpl { nonneg int mVarId{}; nonneg int mFileIndex{}; @@ -114,7 +118,6 @@ struct TokenImpl { // ValueFlow std::list* mValues{}; - static const std::list mEmptyValueList; // Pointer to a template in the template simplifier std::set* mTemplateSimplifierPointers{}; @@ -124,7 +127,7 @@ struct TokenImpl { // __cppcheck_in_range__ struct CppcheckAttributes { - enum Type : std::uint8_t { LOW, HIGH } type = LOW; + CppcheckAttributesType type{LOW}; MathLib::bigint value{}; CppcheckAttributes* next{}; }; @@ -142,12 +145,12 @@ struct TokenImpl { std::string mAttributeCleanup; // For memoization, to speed up parsing of huge arrays #8897 - enum class Cpp11init : std::uint8_t { UNKNOWN, CPP11INIT, NOINIT } mCpp11init = Cpp11init::UNKNOWN; + Cpp11init mCpp11init{Cpp11init::UNKNOWN}; TokenDebug mDebug{}; - void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value); - bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint &value) const; + void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value); + bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const; TokenImpl() : mFunction(nullptr) {} @@ -594,10 +597,10 @@ class CPPCHECKLIB Token { bool hasAttributeCleanup() const { return !mImpl->mAttributeCleanup.empty(); } - void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) { + void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value) { mImpl->setCppcheckAttribute(type, value); } - bool getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint &value) const { + bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const { return mImpl->getCppcheckAttribute(type, value); } // cppcheck-suppress unusedFunction @@ -1346,7 +1349,7 @@ class CPPCHECKLIB Token { } const std::list& values() const { - return mImpl->mValues ? *mImpl->mValues : TokenImpl::mEmptyValueList; + return mImpl->mValues ? *mImpl->mValues : mEmptyValueList; } /** @@ -1406,6 +1409,7 @@ class CPPCHECKLIB Token { void assignIndexes(); private: + static const std::list mEmptyValueList; void next(Token *nextToken) { mNext = nextToken; @@ -1630,9 +1634,9 @@ class CPPCHECKLIB Token { std::shared_ptr scopeInfo() const; void setCpp11init(bool cpp11init) const { - mImpl->mCpp11init=cpp11init ? TokenImpl::Cpp11init::CPP11INIT : TokenImpl::Cpp11init::NOINIT; + mImpl->mCpp11init=cpp11init ? Cpp11init::CPP11INIT : Cpp11init::NOINIT; } - TokenImpl::Cpp11init isCpp11init() const { + Cpp11init isCpp11init() const { return mImpl->mCpp11init; } diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 9c6db66a4c6..247a14c1d63 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9471,10 +9471,10 @@ void Tokenizer::simplifyCppcheckAttribute() if (vartok->isName()) { if (Token::Match(tok->previous(), "__cppcheck_low__ ( %num% )")) - vartok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, + vartok->setCppcheckAttribute(CppcheckAttributesType::LOW, MathLib::toBigNumber(tok->tokAt(1))); else if (Token::Match(tok->previous(), "__cppcheck_high__ ( %num% )")) - vartok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, + vartok->setCppcheckAttribute(CppcheckAttributesType::HIGH, MathLib::toBigNumber(tok->tokAt(1))); } @@ -9562,16 +9562,16 @@ void Tokenizer::simplifyCPPAttribute() } if (argtok && argtok->str() == vartok->str()) { if (vartok->strAt(1) == ">=") - argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, + argtok->setCppcheckAttribute(CppcheckAttributesType::LOW, MathLib::toBigNumber(vartok->tokAt(2))); else if (vartok->strAt(1) == ">") - argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, + argtok->setCppcheckAttribute(CppcheckAttributesType::LOW, MathLib::toBigNumber(vartok->tokAt(2)) + 1); else if (vartok->strAt(1) == "<=") - argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, + argtok->setCppcheckAttribute(CppcheckAttributesType::HIGH, MathLib::toBigNumber(vartok->tokAt(2))); else if (vartok->strAt(1) == "<") - argtok->setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, + argtok->setCppcheckAttribute(CppcheckAttributesType::HIGH, MathLib::toBigNumber(vartok->tokAt(2)) - 1); } } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 3466202414b..957d5426b33 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -559,9 +559,9 @@ static Token * findCppTypeInitPar(Token *tok) static bool iscpp11init_impl(const Token * tok); static bool iscpp11init(const Token * const tok) { - if (tok->isCpp11init() == TokenImpl::Cpp11init::UNKNOWN) + if (tok->isCpp11init() == Cpp11init::UNKNOWN) tok->setCpp11init(iscpp11init_impl(tok)); - return tok->isCpp11init() == TokenImpl::Cpp11init::CPP11INIT; + return tok->isCpp11init() == Cpp11init::CPP11INIT; } static bool iscpp11init_impl(const Token * const tok) @@ -570,8 +570,8 @@ static bool iscpp11init_impl(const Token * const tok) return false; const Token *nameToken = tok; while (nameToken && nameToken->str() == "{") { - if (nameToken->isCpp11init() != TokenImpl::Cpp11init::UNKNOWN) - return nameToken->isCpp11init() == TokenImpl::Cpp11init::CPP11INIT; + if (nameToken->isCpp11init() != Cpp11init::UNKNOWN) + return nameToken->isCpp11init() == Cpp11init::CPP11INIT; nameToken = nameToken->previous(); if (nameToken && nameToken->str() == "," && Token::simpleMatch(nameToken->previous(), "} ,")) nameToken = nameToken->linkAt(-1); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index bba2f0bcaf3..012e9a5ae2f 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -7158,8 +7158,8 @@ static void valueFlowSafeFunctions(const TokenList& tokenlist, const SymbolDatab } MathLib::bigint low, high; - bool isLow = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::LOW, low); - bool isHigh = arg.nameToken()->getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type::HIGH, high); + bool isLow = arg.nameToken()->getCppcheckAttribute(CppcheckAttributesType::LOW, low); + bool isHigh = arg.nameToken()->getCppcheckAttribute(CppcheckAttributesType::HIGH, high); if (!isLow && !isHigh && !all) continue; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 6e468ad524d..23e16ed6b52 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -8203,7 +8203,7 @@ class TestTokenizer : public TestFixture { void cpp11init() { #define testIsCpp11init(...) testIsCpp11init_(__FILE__, __LINE__, __VA_ARGS__) - auto testIsCpp11init_ = [this](const char* file, int line, const std::string& code, const char* find, TokenImpl::Cpp11init expected) { + auto testIsCpp11init_ = [this](const char* file, int line, const std::string& code, const char* find, Cpp11init expected) { SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT_LOC(tokenizer.tokenize(code.data(), code.size()), file, line); @@ -8214,44 +8214,44 @@ class TestTokenizer : public TestFixture { testIsCpp11init("class X : public A, C::D {};", "D {", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("auto f() -> void {}", "void {", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("auto f() & -> void {}", "void {", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("auto f() const noexcept(false) -> void {}", "void {", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("auto f() -> std::vector { return {}; }", "{ return", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("auto f() -> std::vector { return {}; }", "vector", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("auto f() -> std::vector { return {}; }", "std ::", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("class X{};", "{ }", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("class X{}", // forgotten ; so not properly recognized as a class "{ }", - TokenImpl::Cpp11init::CPP11INIT); + Cpp11init::CPP11INIT); testIsCpp11init("namespace abc::def { TEST(a, b) {} }", "{ TEST", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("namespace { TEST(a, b) {} }", // anonymous namespace "{ TEST", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("enum { e = decltype(s)::i };", "{ e", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("template \n" // #11378 "class D> : public B, T> {\n" @@ -8259,7 +8259,7 @@ class TestTokenizer : public TestFixture { " D(int x) : B, T>(x) {}\n" "};\n", "{ public:", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("template \n" "class D> : B, T> {\n" @@ -8267,7 +8267,7 @@ class TestTokenizer : public TestFixture { " D(int x) : B, T>(x) {}\n" "};\n", "{ public:", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("using namespace std;\n" "namespace internal {\n" @@ -8277,21 +8277,21 @@ class TestTokenizer : public TestFixture { " S::S() {}\n" "}\n", "{ } }", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("template \n" "struct C : public C, public B {\n" " ~C() {}\n" "};\n", "{ } }", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("struct S { int i; } s;\n" "struct T : decltype (s) {\n" " T() : decltype(s) ({ 0 }) { }\n" "};\n", "{ } }", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("struct S {};\n" "template\n" @@ -8301,21 +8301,21 @@ class TestTokenizer : public TestFixture { " void operator()(Args...) {}\n" "};\n", "{ void", - TokenImpl::Cpp11init::NOINIT); + Cpp11init::NOINIT); testIsCpp11init("struct S {\n" " std::uint8_t* p;\n" " S() : p{ new std::uint8_t[1]{} } {}\n" "};\n", "{ } } {", - TokenImpl::Cpp11init::CPP11INIT); + Cpp11init::CPP11INIT); testIsCpp11init("struct S {\n" " S() : p{new (malloc(4)) int{}} {}\n" " int* p;\n" "};\n", "{ } } {", - TokenImpl::Cpp11init::CPP11INIT); + Cpp11init::CPP11INIT); ASSERT_NO_THROW(tokenizeAndStringify("template struct X {};\n" // don't crash "template auto f(T t) -> X {}\n")); From 6001d2dd675648dd8ec195689b81b5d75b8fc55e Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 17 Sep 2025 14:48:50 +0200 Subject: [PATCH 2/3] moved `TokenImpl` out of global scope --- lib/checkleakautovar.cpp | 2 +- lib/token.cpp | 11 +-- lib/token.h | 196 +++++++++++++++++++-------------------- lib/tokenize.cpp | 12 +-- lib/tokenlist.cpp | 8 +- lib/valueflow.cpp | 4 +- test/testtokenize.cpp | 42 ++++----- 7 files changed, 137 insertions(+), 138 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index d129e954075..cf29a06a7fa 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -396,7 +396,7 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken, } } - if (tok->isCpp11init() == Cpp11init::CPP11INIT) { + if (tok->isCpp11init() == Token::Cpp11init::CPP11INIT) { const Token *newTok = tok->astOperand1(); const Token *oldTok = tok->astOperand2(); if (newTok && newTok->varId() && oldTok && oldTok->varId()) { diff --git a/lib/token.cpp b/lib/token.cpp index 7dd16810fdc..46315eb85fd 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -64,11 +64,10 @@ const std::string Token::mEmptyString; Token::Token(const TokenList& tokenlist, std::shared_ptr tokensFrontBack) : mList(tokenlist) , mTokensFrontBack(std::move(tokensFrontBack)) + , mImpl(new Impl) , mIsC(mList.isC()) , mIsCpp(mList.isCPP()) -{ - mImpl = new TokenImpl(); -} +{} Token::Token(const Token* tok) : Token(tok->mList, const_cast(tok)->mTokensFrontBack) @@ -2642,7 +2641,7 @@ const ValueFlow::Value* Token::getContainerSizeValue(const MathLib::bigint val) return it == mImpl->mValues->end() ? nullptr : &*it; } -TokenImpl::~TokenImpl() +Token::Impl::~Impl() { delete mMacroName; delete mOriginalName; @@ -2663,7 +2662,7 @@ TokenImpl::~TokenImpl() } } -void TokenImpl::setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value) +void Token::Impl::setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value) { CppcheckAttributes *attr = mCppcheckAttributes; while (attr && attr->type != type) @@ -2679,7 +2678,7 @@ void TokenImpl::setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigin } } -bool TokenImpl::getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const +bool Token::Impl::getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const { CppcheckAttributes *attr = mCppcheckAttributes; while (attr && attr->type != type) diff --git a/lib/token.h b/lib/token.h index dc3d4006c99..066f0b14c66 100644 --- a/lib/token.h +++ b/lib/token.h @@ -63,103 +63,6 @@ struct ScopeInfo2 { enum class TokenDebug : std::uint8_t { None, ValueFlow, ValueType }; -// TODO: move these to Token when TokenImpl has been moved into the implementation -enum CppcheckAttributesType : std::uint8_t { LOW, HIGH }; -enum class Cpp11init : std::uint8_t { UNKNOWN, CPP11INIT, NOINIT }; - -struct TokenImpl { - nonneg int mVarId{}; - nonneg int mFileIndex{}; - nonneg int mLineNumber{}; - nonneg int mColumn{}; - nonneg int mExprId{}; - - // original template argument location - int mTemplateArgFileIndex{-1}; - int mTemplateArgLineNumber{-1}; - int mTemplateArgColumn{-1}; - - /** - * A value from 0-100 that provides a rough idea about where in the token - * list this token is located. - */ - nonneg int mProgressValue{}; - - /** - * Token index. Position in token list - */ - nonneg int mIndex{}; - - /** Bitfield bit count. */ - short mBits = -1; - - // AST.. - Token* mAstOperand1{}; - Token* mAstOperand2{}; - Token* mAstParent{}; - - // symbol database information - const Scope* mScope{}; - union { - const Function *mFunction; - const Variable *mVariable; - const ::Type* mType; - const Enumerator *mEnumerator; - }; - - // original name like size_t - std::string* mOriginalName{}; - - // If this token came from a macro replacement list, this is the name of that macro - std::string* mMacroName{}; - - // ValueType - ValueType* mValueType{}; - - // ValueFlow - std::list* mValues{}; - - // Pointer to a template in the template simplifier - std::set* mTemplateSimplifierPointers{}; - - // Pointer to the object representing this token's scope - std::shared_ptr mScopeInfo; - - // __cppcheck_in_range__ - struct CppcheckAttributes { - CppcheckAttributesType type{LOW}; - MathLib::bigint value{}; - CppcheckAttributes* next{}; - }; - CppcheckAttributes* mCppcheckAttributes{}; - - // alignas expressions - std::unique_ptr> mAttributeAlignas; - void addAttributeAlignas(const std::string& a) { - if (!mAttributeAlignas) - mAttributeAlignas = std::unique_ptr>(new std::vector()); - if (std::find(mAttributeAlignas->cbegin(), mAttributeAlignas->cend(), a) == mAttributeAlignas->cend()) - mAttributeAlignas->push_back(a); - } - - std::string mAttributeCleanup; - - // For memoization, to speed up parsing of huge arrays #8897 - Cpp11init mCpp11init{Cpp11init::UNKNOWN}; - - TokenDebug mDebug{}; - - void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value); - bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const; - - TokenImpl() : mFunction(nullptr) {} - - ~TokenImpl(); - - TokenImpl(const TokenImpl &) = delete; - TokenImpl operator=(const TokenImpl &) = delete; -}; - /// @addtogroup Core /// @{ @@ -176,7 +79,104 @@ struct TokenImpl { class CPPCHECKLIB Token { friend class TestToken; +public: + enum CppcheckAttributesType : std::uint8_t { LOW, HIGH }; + enum class Cpp11init : std::uint8_t { UNKNOWN, CPP11INIT, NOINIT }; + private: + struct Impl { + nonneg int mVarId{}; + nonneg int mFileIndex{}; + nonneg int mLineNumber{}; + nonneg int mColumn{}; + nonneg int mExprId{}; + + // original template argument location + int mTemplateArgFileIndex{-1}; + int mTemplateArgLineNumber{-1}; + int mTemplateArgColumn{-1}; + + /** + * A value from 0-100 that provides a rough idea about where in the token + * list this token is located. + */ + nonneg int mProgressValue{}; + + /** + * Token index. Position in token list + */ + nonneg int mIndex{}; + + /** Bitfield bit count. */ + short mBits = -1; + + // AST.. + Token* mAstOperand1{}; + Token* mAstOperand2{}; + Token* mAstParent{}; + + // symbol database information + const Scope* mScope{}; + union { + const Function *mFunction; + const Variable *mVariable; + const ::Type* mType; + const Enumerator *mEnumerator; + }; + + // original name like size_t + std::string* mOriginalName{}; + + // If this token came from a macro replacement list, this is the name of that macro + std::string* mMacroName{}; + + // ValueType + ValueType* mValueType{}; + + // ValueFlow + std::list* mValues{}; + + // Pointer to a template in the template simplifier + std::set* mTemplateSimplifierPointers{}; + + // Pointer to the object representing this token's scope + std::shared_ptr mScopeInfo; + + // __cppcheck_in_range__ + struct CppcheckAttributes { + CppcheckAttributesType type{LOW}; + MathLib::bigint value{}; + CppcheckAttributes* next{}; + }; + CppcheckAttributes* mCppcheckAttributes{}; + + // alignas expressions + std::unique_ptr> mAttributeAlignas; + void addAttributeAlignas(const std::string& a) { + if (!mAttributeAlignas) + mAttributeAlignas = std::unique_ptr>(new std::vector()); + if (std::find(mAttributeAlignas->cbegin(), mAttributeAlignas->cend(), a) == mAttributeAlignas->cend()) + mAttributeAlignas->push_back(a); + } + + std::string mAttributeCleanup; + + // For memoization, to speed up parsing of huge arrays #8897 + Cpp11init mCpp11init{Cpp11init::UNKNOWN}; + + TokenDebug mDebug{}; + + void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value); + bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const; + + Impl() : mFunction(nullptr) {} + + ~Impl(); + + Impl(const Impl &) = delete; + Impl operator=(const Impl &) = delete; + }; + const TokenList& mList; std::shared_ptr mTokensFrontBack; @@ -1503,7 +1503,7 @@ class CPPCHECKLIB Token { uint64_t mFlags{}; - TokenImpl* mImpl{}; + Impl* mImpl{}; /** * Get specified flag state. diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 247a14c1d63..108bcb1a4b7 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -9471,10 +9471,10 @@ void Tokenizer::simplifyCppcheckAttribute() if (vartok->isName()) { if (Token::Match(tok->previous(), "__cppcheck_low__ ( %num% )")) - vartok->setCppcheckAttribute(CppcheckAttributesType::LOW, + vartok->setCppcheckAttribute(Token::CppcheckAttributesType::LOW, MathLib::toBigNumber(tok->tokAt(1))); else if (Token::Match(tok->previous(), "__cppcheck_high__ ( %num% )")) - vartok->setCppcheckAttribute(CppcheckAttributesType::HIGH, + vartok->setCppcheckAttribute(Token::CppcheckAttributesType::HIGH, MathLib::toBigNumber(tok->tokAt(1))); } @@ -9562,16 +9562,16 @@ void Tokenizer::simplifyCPPAttribute() } if (argtok && argtok->str() == vartok->str()) { if (vartok->strAt(1) == ">=") - argtok->setCppcheckAttribute(CppcheckAttributesType::LOW, + argtok->setCppcheckAttribute(Token::CppcheckAttributesType::LOW, MathLib::toBigNumber(vartok->tokAt(2))); else if (vartok->strAt(1) == ">") - argtok->setCppcheckAttribute(CppcheckAttributesType::LOW, + argtok->setCppcheckAttribute(Token::CppcheckAttributesType::LOW, MathLib::toBigNumber(vartok->tokAt(2)) + 1); else if (vartok->strAt(1) == "<=") - argtok->setCppcheckAttribute(CppcheckAttributesType::HIGH, + argtok->setCppcheckAttribute(Token::CppcheckAttributesType::HIGH, MathLib::toBigNumber(vartok->tokAt(2))); else if (vartok->strAt(1) == "<") - argtok->setCppcheckAttribute(CppcheckAttributesType::HIGH, + argtok->setCppcheckAttribute(Token::CppcheckAttributesType::HIGH, MathLib::toBigNumber(vartok->tokAt(2)) - 1); } } diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 957d5426b33..37771f02dae 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -559,9 +559,9 @@ static Token * findCppTypeInitPar(Token *tok) static bool iscpp11init_impl(const Token * tok); static bool iscpp11init(const Token * const tok) { - if (tok->isCpp11init() == Cpp11init::UNKNOWN) + if (tok->isCpp11init() == Token::Cpp11init::UNKNOWN) tok->setCpp11init(iscpp11init_impl(tok)); - return tok->isCpp11init() == Cpp11init::CPP11INIT; + return tok->isCpp11init() == Token::Cpp11init::CPP11INIT; } static bool iscpp11init_impl(const Token * const tok) @@ -570,8 +570,8 @@ static bool iscpp11init_impl(const Token * const tok) return false; const Token *nameToken = tok; while (nameToken && nameToken->str() == "{") { - if (nameToken->isCpp11init() != Cpp11init::UNKNOWN) - return nameToken->isCpp11init() == Cpp11init::CPP11INIT; + if (nameToken->isCpp11init() != Token::Cpp11init::UNKNOWN) + return nameToken->isCpp11init() == Token::Cpp11init::CPP11INIT; nameToken = nameToken->previous(); if (nameToken && nameToken->str() == "," && Token::simpleMatch(nameToken->previous(), "} ,")) nameToken = nameToken->linkAt(-1); diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 012e9a5ae2f..1f725673874 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -7158,8 +7158,8 @@ static void valueFlowSafeFunctions(const TokenList& tokenlist, const SymbolDatab } MathLib::bigint low, high; - bool isLow = arg.nameToken()->getCppcheckAttribute(CppcheckAttributesType::LOW, low); - bool isHigh = arg.nameToken()->getCppcheckAttribute(CppcheckAttributesType::HIGH, high); + bool isLow = arg.nameToken()->getCppcheckAttribute(Token::CppcheckAttributesType::LOW, low); + bool isHigh = arg.nameToken()->getCppcheckAttribute(Token::CppcheckAttributesType::HIGH, high); if (!isLow && !isHigh && !all) continue; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 23e16ed6b52..bebf570150a 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -8203,7 +8203,7 @@ class TestTokenizer : public TestFixture { void cpp11init() { #define testIsCpp11init(...) testIsCpp11init_(__FILE__, __LINE__, __VA_ARGS__) - auto testIsCpp11init_ = [this](const char* file, int line, const std::string& code, const char* find, Cpp11init expected) { + auto testIsCpp11init_ = [this](const char* file, int line, const std::string& code, const char* find, Token::Cpp11init expected) { SimpleTokenizer tokenizer(settingsDefault, *this); ASSERT_LOC(tokenizer.tokenize(code.data(), code.size()), file, line); @@ -8214,44 +8214,44 @@ class TestTokenizer : public TestFixture { testIsCpp11init("class X : public A, C::D {};", "D {", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("auto f() -> void {}", "void {", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("auto f() & -> void {}", "void {", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("auto f() const noexcept(false) -> void {}", "void {", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("auto f() -> std::vector { return {}; }", "{ return", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("auto f() -> std::vector { return {}; }", "vector", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("auto f() -> std::vector { return {}; }", "std ::", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("class X{};", "{ }", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("class X{}", // forgotten ; so not properly recognized as a class "{ }", - Cpp11init::CPP11INIT); + Token::Cpp11init::CPP11INIT); testIsCpp11init("namespace abc::def { TEST(a, b) {} }", "{ TEST", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("namespace { TEST(a, b) {} }", // anonymous namespace "{ TEST", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("enum { e = decltype(s)::i };", "{ e", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("template \n" // #11378 "class D> : public B, T> {\n" @@ -8259,7 +8259,7 @@ class TestTokenizer : public TestFixture { " D(int x) : B, T>(x) {}\n" "};\n", "{ public:", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("template \n" "class D> : B, T> {\n" @@ -8267,7 +8267,7 @@ class TestTokenizer : public TestFixture { " D(int x) : B, T>(x) {}\n" "};\n", "{ public:", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("using namespace std;\n" "namespace internal {\n" @@ -8277,21 +8277,21 @@ class TestTokenizer : public TestFixture { " S::S() {}\n" "}\n", "{ } }", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("template \n" "struct C : public C, public B {\n" " ~C() {}\n" "};\n", "{ } }", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("struct S { int i; } s;\n" "struct T : decltype (s) {\n" " T() : decltype(s) ({ 0 }) { }\n" "};\n", "{ } }", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("struct S {};\n" "template\n" @@ -8301,21 +8301,21 @@ class TestTokenizer : public TestFixture { " void operator()(Args...) {}\n" "};\n", "{ void", - Cpp11init::NOINIT); + Token::Cpp11init::NOINIT); testIsCpp11init("struct S {\n" " std::uint8_t* p;\n" " S() : p{ new std::uint8_t[1]{} } {}\n" "};\n", "{ } } {", - Cpp11init::CPP11INIT); + Token::Cpp11init::CPP11INIT); testIsCpp11init("struct S {\n" " S() : p{new (malloc(4)) int{}} {}\n" " int* p;\n" "};\n", "{ } } {", - Cpp11init::CPP11INIT); + Token::Cpp11init::CPP11INIT); ASSERT_NO_THROW(tokenizeAndStringify("template struct X {};\n" // don't crash "template auto f(T t) -> X {}\n")); From b98a60194300d96c44aacb82e138fb29b43adb36 Mon Sep 17 00:00:00 2001 From: firewave Date: Thu, 18 Sep 2025 04:12:25 +0200 Subject: [PATCH 3/3] token.cpp: fixed `shadowFunction` selfcheck warning --- lib/token.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/token.cpp b/lib/token.cpp index 46315eb85fd..35b5a9141b8 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2649,8 +2649,8 @@ Token::Impl::~Impl() delete mValues; if (mTemplateSimplifierPointers) { - for (auto *templateSimplifierPointer : *mTemplateSimplifierPointers) { - templateSimplifierPointer->token(nullptr); + for (auto *p : *mTemplateSimplifierPointers) { + p->token(nullptr); } } delete mTemplateSimplifierPointers;