From 3947a3a0159b555fdcbe0e0834db98dbf59df9b2 Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 12 Nov 2025 13:38:47 +0100 Subject: [PATCH 1/5] Tokenizer: removed `TemplateSimplifier` friend class declaration --- lib/templatesimplifier.cpp | 2 +- lib/tokenize.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 492e5906cd8..1f90593560f 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -275,7 +275,7 @@ bool TemplateSimplifier::TokenAndName::isAliasToken(const Token *tok) const TemplateSimplifier::TemplateSimplifier(Tokenizer &tokenizer) : mTokenizer(tokenizer), mTokenList(mTokenizer.list), mSettings(mTokenizer.getSettings()), - mErrorLogger(mTokenizer.mErrorLogger) + mErrorLogger(mTokenizer.getErrorLogger()) {} void TemplateSimplifier::checkComplicatedSyntaxErrorsInTemplates() diff --git a/lib/tokenize.h b/lib/tokenize.h index 8ae367a10d0..9a9532ef0c1 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -48,7 +48,6 @@ enum class Severity : std::uint8_t; class CPPCHECKLIB Tokenizer { friend class SymbolDatabase; - friend class TemplateSimplifier; friend class TestSimplifyTemplate; friend class TestSimplifyTypedef; @@ -244,7 +243,9 @@ class CPPCHECKLIB Tokenizer { /** */ +public: bool simplifyUsing(); +private: void simplifyUsingError(const Token* usingStart, const Token* usingEnd); /** Simplify useless C++ empty namespaces, like: 'namespace %name% { }'*/ From b5d981129708cb545f06afde64e1c58e83c1a6fd Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 12 Nov 2025 13:45:39 +0100 Subject: [PATCH 2/5] Tokenizer: removed `TestSimplifyTemplate` friend class declaration --- lib/tokenize.h | 6 +++++- test/testsimplifytemplate.cpp | 17 +++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/tokenize.h b/lib/tokenize.h index 9a9532ef0c1..7c14578a544 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -49,7 +49,6 @@ class CPPCHECKLIB Tokenizer { friend class SymbolDatabase; - friend class TestSimplifyTemplate; friend class TestSimplifyTypedef; friend class TestTokenizer; @@ -115,6 +114,7 @@ class CPPCHECKLIB Tokenizer { void removeExtraTemplateKeywords(); +protected: /** Split up template right angle brackets. * foo < bar < >> => foo < bar < > > */ @@ -353,11 +353,13 @@ class CPPCHECKLIB Tokenizer { */ NORETURN void cppcheckError(const Token *tok) const; +protected: /** * Setup links for tokens so that one can call Token::link(). */ void createLinks(); +private: /** * Setup links between < and >. */ @@ -645,8 +647,10 @@ class CPPCHECKLIB Tokenizer { /** Symbol database that all checks etc can use */ SymbolDatabase* mSymbolDatabase{}; +protected: TemplateSimplifier * const mTemplateSimplifier; +private: std::set mTemplateVarIdUsage; /** E.g. "A" for code where "#ifdef A" is true. This is used to diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index a17646854e9..963ba058b2b 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -319,6 +319,15 @@ class TestSimplifyTemplate : public TestFixture { TEST_CASE(dumpTemplateArgFrom); } + class TokenizerTest : public Tokenizer + { + friend class TestSimplifyTemplate; + public: + TokenizerTest(TokenList tokenList, ErrorLogger &errorLogger) + : Tokenizer(std::move(tokenList), errorLogger) + {} + }; + struct CheckOptions { bool debugwarnings = false; @@ -5461,7 +5470,7 @@ class TestSimplifyTemplate : public TestFixture { tokenlist.appendFileIfNew("test.cpp"); if (!tokenlist.createTokensFromString(data)) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); @@ -5531,7 +5540,7 @@ class TestSimplifyTemplate : public TestFixture { tokenlist.appendFileIfNew("test.cpp"); if (!tokenlist.createTokensFromString(data)) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); @@ -5602,7 +5611,7 @@ class TestSimplifyTemplate : public TestFixture { TokenList tokenlist{settings, Standards::Language::CPP}; if (!TokenListHelper::createTokensFromString(tokenlist, data, "test.cpp")) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); @@ -5633,7 +5642,7 @@ class TestSimplifyTemplate : public TestFixture { if (!TokenListHelper::createTokensFromString(tokenlist, data, "test.cpp")) return false; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.splitTemplateRightAngleBrackets(false); From 769bafc1b31dcd05960011660492be7f225a7c32 Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 12 Nov 2025 13:51:36 +0100 Subject: [PATCH 3/5] Tokenizer: removed `TestSimplifyTypedef` friend class declaration --- lib/tokenize.h | 5 ++++- test/helpers.h | 1 + test/testsimplifytypedef.cpp | 21 +++++++++++++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/tokenize.h b/lib/tokenize.h index 7c14578a544..9992ab78421 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -49,7 +49,6 @@ class CPPCHECKLIB Tokenizer { friend class SymbolDatabase; - friend class TestSimplifyTypedef; friend class TestTokenizer; public: @@ -230,7 +229,9 @@ class CPPCHECKLIB Tokenizer { * typedef A mytype; * A c; */ +protected: void simplifyTypedef(); +private: void simplifyTypedefCpp(); /** * Move typedef token to the left og the expression @@ -398,12 +399,14 @@ class CPPCHECKLIB Tokenizer { */ void validateC() const; +protected: /** * assert that tokens are ok - used during debugging for example * to catch problems in simplifyTokenList1/2. */ void validate() const; +private: /** Detect unknown macros and throw unknownMacro */ void reportUnknownMacros() const; diff --git a/test/helpers.h b/test/helpers.h index bb05598d8ea..5a0bd106812 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -231,6 +231,7 @@ struct LibraryHelper }; class SimpleTokenizer2 : public Tokenizer { + friend class TestSimplifyTypedef; // TODO: get rid of this public: template SimpleTokenizer2(const Settings &settings, ErrorLogger &errorlogger, const char (&code)[size], const std::string& file0) diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 3ffa4290341..368a143a9ad 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -257,6 +257,15 @@ class TestSimplifyTypedef : public TestFixture { TEST_CASE(typedefInfo3); } + class TokenizerTest : public Tokenizer + { + friend class TestSimplifyTypedef; + public: + TokenizerTest(TokenList tokenList, ErrorLogger &errorLogger) + : Tokenizer(std::move(tokenList), errorLogger) + {} + }; + struct TokOptions { bool simplify = true; @@ -280,7 +289,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::CPP}; if (!tokenlist.createTokensFromString(data)) return ""; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -315,7 +324,7 @@ class TestSimplifyTypedef : public TestFixture { if (!TokenListHelper::createTokensFromString(tokenlist, data, "file.c")) return ""; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); try { @@ -331,7 +340,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; if (!TokenListHelper::createTokensFromString(tokenlist, code, "file.c")) return {}; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); try { @@ -4457,7 +4466,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -4499,7 +4508,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); @@ -4517,7 +4526,7 @@ class TestSimplifyTypedef : public TestFixture { TokenList tokenlist{settings1, Standards::Language::C}; ASSERT(TokenListHelper::createTokensFromString(tokenlist, code, "file.c")); - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.createLinks(); tokenizer.simplifyTypedef(); From 0d7e8a0d36f96e04e88dc712cb671786d3bb7542 Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 12 Nov 2025 14:00:12 +0100 Subject: [PATCH 4/5] Tokenizer: removed `TestTokenizer` friend class declaration --- lib/tokenize.h | 13 ++++++++++--- test/testtokenize.cpp | 13 +++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/tokenize.h b/lib/tokenize.h index 9992ab78421..f712485a292 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -49,8 +49,6 @@ class CPPCHECKLIB Tokenizer { friend class SymbolDatabase; - friend class TestTokenizer; - public: Tokenizer(TokenList tokenList, ErrorLogger &errorLogger); ~Tokenizer(); @@ -191,6 +189,7 @@ class CPPCHECKLIB Tokenizer { */ void simplifyVariableMultipleAssign(); +protected: /** * Simplify the 'C Alternative Tokens' * Examples: @@ -200,6 +199,7 @@ class CPPCHECKLIB Tokenizer { */ bool simplifyCAlternativeTokens(); +private: /** Add braces to an if-block, for-block, etc. * @return true if no syntax errors */ @@ -307,10 +307,12 @@ class CPPCHECKLIB Tokenizer { void fillTypeSizes(); +protected: void combineOperators(); void combineStringAndCharLiterals(); +private: void concatenateNegativeNumberAndAnyPositive(); void simplifyExternC(); @@ -327,6 +329,7 @@ class CPPCHECKLIB Tokenizer { void findComplicatedSyntaxErrorsInTemplates(); +protected: /** * Modify strings in the token list by replacing hex and oct * values. E.g. "\x61" -> "a" and "\000" -> "\0" @@ -360,12 +363,12 @@ class CPPCHECKLIB Tokenizer { */ void createLinks(); -private: /** * Setup links between < and >. */ void createLinks2(); +private: /** * Set isCast() for C++ casts */ @@ -439,9 +442,11 @@ class CPPCHECKLIB Tokenizer { */ void simplifyCppcheckAttribute(); +protected: /** Simplify c++20 spaceship operator */ void simplifySpaceshipOperator(); +private: /** * Remove keywords "volatile", "inline", "register", and "restrict" */ @@ -528,11 +533,13 @@ class CPPCHECKLIB Tokenizer { */ void simplifyCoroutines(); +protected: /** * Prepare ternary operators with parentheses so that the AST can be created * */ void prepareTernaryOpForAST(); +private: /** * report error message */ diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 97ae9f9b9e3..45df39a4557 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -508,6 +508,15 @@ class TestTokenizer : public TestFixture { TEST_CASE(simplifyRedundantParentheses); } + class TokenizerTest : public Tokenizer + { + friend class TestTokenizer; + public: + TokenizerTest(TokenList tokenList, ErrorLogger &errorLogger) + : Tokenizer(std::move(tokenList), errorLogger) + {} + }; + struct TokenizeOptions { bool expand = true; @@ -3782,7 +3791,7 @@ class TestTokenizer : public TestFixture { void simplifyString() { TokenList tokenlist{settings0, Standards::Language::CPP}; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); ASSERT_EQUALS("\"abc\"", tokenizer.simplifyString("\"abc\"")); ASSERT_EQUALS("\"\n\"", tokenizer.simplifyString("\"\\xa\"")); ASSERT_EQUALS("\"3\"", tokenizer.simplifyString("\"\\x33\"")); @@ -6349,7 +6358,7 @@ class TestTokenizer : public TestFixture { if (!tokenlist.createTokensFromString(data)) return "ERROR"; - Tokenizer tokenizer(std::move(tokenlist), *this); + TokenizerTest tokenizer(std::move(tokenlist), *this); tokenizer.combineStringAndCharLiterals(); tokenizer.combineOperators(); tokenizer.simplifySpaceshipOperator(); From 4f2f811ea0dd41e6bb64b0d0883a194b21187705 Mon Sep 17 00:00:00 2001 From: firewave Date: Wed, 12 Nov 2025 14:05:50 +0100 Subject: [PATCH 5/5] Tokenizer: cleaned up member access --- lib/tokenize.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/tokenize.h b/lib/tokenize.h index f712485a292..f9feebb43f0 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -382,6 +382,7 @@ class CPPCHECKLIB Tokenizer { /** Syntax error. Unmatched character. */ NORETURN void unmatchedToken(const Token *tok) const; +private: /** Syntax error. C++ code in C file. */ NORETURN void syntaxErrorC(const Token *tok, const std::string &what) const; @@ -390,8 +391,6 @@ class CPPCHECKLIB Tokenizer { void unhandledCharLiteral(const Token *tok, const std::string& msg) const; -private: - /** Report that there is an unhandled "class x y {" code */ void unhandled_macro_class_x_y(const Token *tok, const std::string& type, const std::string& x, const std::string& y, const std::string& bracket) const; @@ -574,8 +573,10 @@ class CPPCHECKLIB Tokenizer { void dump(std::ostream &out) const; +private: Token *deleteInvalidTypedef(Token *typeDef); +public: /** * Get variable count. * @return number of variables