From a17f6e89d12b1d5cb683e66573f3247c2fbc826a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 7 Aug 2023 18:39:57 +0200 Subject: [PATCH 01/18] pass `Suppressions` separately from `const Settings` into executors (#5278) --- cli/cppcheckexecutor.cpp | 6 +++--- cli/executor.cpp | 6 +++--- cli/executor.h | 6 ++++-- cli/processexecutor.cpp | 6 +++--- cli/processexecutor.h | 3 ++- cli/singleexecutor.cpp | 4 ++-- cli/singleexecutor.h | 3 ++- cli/threadexecutor.cpp | 4 ++-- cli/threadexecutor.h | 3 ++- test/testprocessexecutor.cpp | 2 +- test/testsingleexecutor.cpp | 2 +- test/testsuppressions.cpp | 6 +++--- test/testthreadexecutor.cpp | 2 +- 13 files changed, 29 insertions(+), 24 deletions(-) diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index cb07f3f356e..06dcd597205 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -285,13 +285,13 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) unsigned int returnValue = 0; if (settings.useSingleJob()) { // Single process - SingleExecutor executor(cppcheck, mFiles, settings, *this); + SingleExecutor executor(cppcheck, mFiles, settings, settings.nomsg, *this); returnValue = executor.check(); } else { #if defined(THREADING_MODEL_THREAD) - ThreadExecutor executor(mFiles, settings, *this); + ThreadExecutor executor(mFiles, settings, settings.nomsg, *this); #elif defined(THREADING_MODEL_FORK) - ProcessExecutor executor(mFiles, settings, *this); + ProcessExecutor executor(mFiles, settings, settings.nomsg, *this); #endif returnValue = executor.check(); } diff --git a/cli/executor.cpp b/cli/executor.cpp index 7185db07b73..489d9f8951b 100644 --- a/cli/executor.cpp +++ b/cli/executor.cpp @@ -27,8 +27,8 @@ #include // IWYU pragma: keep #include -Executor::Executor(const std::map &files, Settings &settings, ErrorLogger &errorLogger) - : mFiles(files), mSettings(settings), mErrorLogger(errorLogger) +Executor::Executor(const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger) + : mFiles(files), mSettings(settings), mSuppressions(suppressions), mErrorLogger(errorLogger) {} Executor::~Executor() @@ -36,7 +36,7 @@ Executor::~Executor() bool Executor::hasToLog(const ErrorMessage &msg) { - if (!mSettings.nomsg.isSuppressed(msg)) + if (!mSuppressions.isSuppressed(msg)) { std::string errmsg = msg.toString(mSettings.verbose); diff --git a/cli/executor.h b/cli/executor.h index f8f010c2d83..1b7db25e71e 100644 --- a/cli/executor.h +++ b/cli/executor.h @@ -28,6 +28,7 @@ class Settings; class ErrorLogger; class ErrorMessage; +class Suppressions; /// @addtogroup CLI /// @{ @@ -38,7 +39,7 @@ class ErrorMessage; */ class Executor { public: - Executor(const std::map &files, Settings &settings, ErrorLogger &errorLogger); + Executor(const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger); virtual ~Executor(); Executor(const Executor &) = delete; @@ -65,7 +66,8 @@ class Executor { bool hasToLog(const ErrorMessage &msg); const std::map &mFiles; - Settings &mSettings; + const Settings &mSettings; + Suppressions &mSuppressions; ErrorLogger &mErrorLogger; private: diff --git a/cli/processexecutor.cpp b/cli/processexecutor.cpp index e6aca40ee3a..445b545f8c3 100644 --- a/cli/processexecutor.cpp +++ b/cli/processexecutor.cpp @@ -61,8 +61,8 @@ enum class Color; using std::memset; -ProcessExecutor::ProcessExecutor(const std::map &files, Settings &settings, ErrorLogger &errorLogger) - : Executor(files, settings, errorLogger) +ProcessExecutor::ProcessExecutor(const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger) + : Executor(files, settings, suppressions, errorLogger) { assert(mSettings.jobs > 1); } @@ -391,7 +391,7 @@ void ProcessExecutor::reportInternalChildErr(const std::string &childname, const "cppcheckError", Certainty::normal); - if (!mSettings.nomsg.isSuppressed(errmsg)) + if (!mSuppressions.isSuppressed(errmsg)) mErrorLogger.reportErr(errmsg); } diff --git a/cli/processexecutor.h b/cli/processexecutor.h index c472fe89500..4b51d596acc 100644 --- a/cli/processexecutor.h +++ b/cli/processexecutor.h @@ -27,6 +27,7 @@ class Settings; class ErrorLogger; +class Suppressions; /// @addtogroup CLI /// @{ @@ -37,7 +38,7 @@ class ErrorLogger; */ class ProcessExecutor : public Executor { public: - ProcessExecutor(const std::map &files, Settings &settings, ErrorLogger &errorLogger); + ProcessExecutor(const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger); ProcessExecutor(const ProcessExecutor &) = delete; ~ProcessExecutor() override; void operator=(const ProcessExecutor &) = delete; diff --git a/cli/singleexecutor.cpp b/cli/singleexecutor.cpp index ce7476f3d4c..4de711a2c84 100644 --- a/cli/singleexecutor.cpp +++ b/cli/singleexecutor.cpp @@ -30,8 +30,8 @@ class ErrorLogger; -SingleExecutor::SingleExecutor(CppCheck &cppcheck, const std::map &files, Settings &settings, ErrorLogger &errorLogger) - : Executor(files, settings, errorLogger) +SingleExecutor::SingleExecutor(CppCheck &cppcheck, const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger) + : Executor(files, settings, suppressions, errorLogger) , mCppcheck(cppcheck) { assert(mSettings.jobs == 1); diff --git a/cli/singleexecutor.h b/cli/singleexecutor.h index 74143be7c00..4ca53768b43 100644 --- a/cli/singleexecutor.h +++ b/cli/singleexecutor.h @@ -28,11 +28,12 @@ class ErrorLogger; class Settings; class CppCheck; +class Suppressions; class SingleExecutor : public Executor { public: - SingleExecutor(CppCheck &cppcheck, const std::map &files, Settings &settings, ErrorLogger &errorLogger); + SingleExecutor(CppCheck &cppcheck, const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger); SingleExecutor(const SingleExecutor &) = delete; ~SingleExecutor() override; void operator=(const SingleExecutor &) = delete; diff --git a/cli/threadexecutor.cpp b/cli/threadexecutor.cpp index 8efdfeea76f..26c3c03aa18 100644 --- a/cli/threadexecutor.cpp +++ b/cli/threadexecutor.cpp @@ -40,8 +40,8 @@ enum class Color; -ThreadExecutor::ThreadExecutor(const std::map &files, Settings &settings, ErrorLogger &errorLogger) - : Executor(files, settings, errorLogger) +ThreadExecutor::ThreadExecutor(const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger) + : Executor(files, settings, suppressions, errorLogger) { assert(mSettings.jobs > 1); } diff --git a/cli/threadexecutor.h b/cli/threadexecutor.h index 5c24dfe0c13..62ad8e0a860 100644 --- a/cli/threadexecutor.h +++ b/cli/threadexecutor.h @@ -27,6 +27,7 @@ class Settings; class ErrorLogger; +class Suppressions; /// @addtogroup CLI /// @{ @@ -37,7 +38,7 @@ class ErrorLogger; */ class ThreadExecutor : public Executor { public: - ThreadExecutor(const std::map &files, Settings &settings, ErrorLogger &errorLogger); + ThreadExecutor(const std::map &files, const Settings &settings, Suppressions &suppressions, ErrorLogger &errorLogger); ThreadExecutor(const ThreadExecutor &) = delete; ~ThreadExecutor() override; void operator=(const ThreadExecutor &) = delete; diff --git a/test/testprocessexecutor.cpp b/test/testprocessexecutor.cpp index 100aaa580d8..f9cf2d0d9fd 100644 --- a/test/testprocessexecutor.cpp +++ b/test/testprocessexecutor.cpp @@ -82,7 +82,7 @@ class TestProcessExecutor : public TestFixture { if (opt.plistOutput) settings.plistOutput = opt.plistOutput; // TODO: test with settings.project.fileSettings; - ProcessExecutor executor(filemap, settings, *this); + ProcessExecutor executor(filemap, settings, settings.nomsg, *this); std::vector> scopedfiles; scopedfiles.reserve(filemap.size()); for (std::map::const_iterator i = filemap.cbegin(); i != filemap.cend(); ++i) diff --git a/test/testsingleexecutor.cpp b/test/testsingleexecutor.cpp index beb1dd78f65..9208ca72ed2 100644 --- a/test/testsingleexecutor.cpp +++ b/test/testsingleexecutor.cpp @@ -117,7 +117,7 @@ class TestSingleExecutorBase : public TestFixture { filemap.clear(); // TODO: test with settings.project.fileSettings; - SingleExecutor executor(cppcheck, filemap, settings, *this); + SingleExecutor executor(cppcheck, filemap, settings, settings.nomsg, *this); ASSERT_EQUALS(result, executor.check()); } diff --git a/test/testsuppressions.cpp b/test/testsuppressions.cpp index 22061415bac..f1c6a7d8a47 100644 --- a/test/testsuppressions.cpp +++ b/test/testsuppressions.cpp @@ -206,7 +206,7 @@ class TestSuppressions : public TestFixture { if (!suppression.empty()) { EXPECT_EQ("", settings.nomsg.addSuppressionLine(suppression)); } - SingleExecutor executor(cppCheck, files, settings, *this); + SingleExecutor executor(cppCheck, files, settings, settings.nomsg, *this); std::vector> scopedfiles; scopedfiles.reserve(files.size()); for (std::map::const_iterator i = f.cbegin(); i != f.cend(); ++i) @@ -233,7 +233,7 @@ class TestSuppressions : public TestFixture { if (!suppression.empty()) { EXPECT_EQ("", settings.nomsg.addSuppressionLine(suppression)); } - ThreadExecutor executor(files, settings, *this); + ThreadExecutor executor(files, settings, settings.nomsg, *this); std::vector> scopedfiles; scopedfiles.reserve(files.size()); for (std::map::const_iterator i = files.cbegin(); i != files.cend(); ++i) @@ -261,7 +261,7 @@ class TestSuppressions : public TestFixture { if (!suppression.empty()) { EXPECT_EQ("", settings.nomsg.addSuppressionLine(suppression)); } - ProcessExecutor executor(files, settings, *this); + ProcessExecutor executor(files, settings, settings.nomsg, *this); std::vector> scopedfiles; scopedfiles.reserve(files.size()); for (std::map::const_iterator i = files.cbegin(); i != files.cend(); ++i) diff --git a/test/testthreadexecutor.cpp b/test/testthreadexecutor.cpp index d438dfa13a0..8d7f11bc5e6 100644 --- a/test/testthreadexecutor.cpp +++ b/test/testthreadexecutor.cpp @@ -83,7 +83,7 @@ class TestThreadExecutor : public TestFixture { if (opt.plistOutput) settings1.plistOutput = opt.plistOutput; // TODO: test with settings.project.fileSettings; - ThreadExecutor executor(filemap, settings1, *this); + ThreadExecutor executor(filemap, settings1, settings1.nomsg, *this); std::vector> scopedfiles; scopedfiles.reserve(filemap.size()); for (std::map::const_iterator i = filemap.cbegin(); i != filemap.cend(); ++i) From e38a031ae6c17d5edaada7e7952e4edb6456731a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 7 Aug 2023 18:41:50 +0200 Subject: [PATCH 02/18] ValueFlow: pass `SymbolDatabase` by reference into `ValueFlow::setValues()` (#5295) --- lib/cppcheck.cpp | 2 +- lib/tokenize.cpp | 4 +- lib/valueflow.cpp | 105 ++++++++++++++++++++++------------------------ lib/valueflow.h | 2 +- 4 files changed, 55 insertions(+), 58 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index f074abebc68..9b7a72cad62 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -545,7 +545,7 @@ unsigned int CppCheck::check(const std::string &path) tokenizer.list.appendFileIfNew(path); clangimport::parseClangAstDump(&tokenizer, ast); ValueFlow::setValues(tokenizer.list, - const_cast(tokenizer.getSymbolDatabase()), + const_cast(*tokenizer.getSymbolDatabase()), this, &mSettings, &s_timerResults); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 5af99c21ec2..deb580111a3 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3361,9 +3361,9 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) if (doValueFlow) { if (mTimerResults) { Timer t("Tokenizer::simplifyTokens1::ValueFlow", mSettings->showtime, mTimerResults); - ValueFlow::setValues(list, mSymbolDatabase, mErrorLogger, mSettings, mTimerResults); + ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults); } else { - ValueFlow::setValues(list, mSymbolDatabase, mErrorLogger, mSettings, mTimerResults); + ValueFlow::setValues(list, *mSymbolDatabase, mErrorLogger, mSettings, mTimerResults); } } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 03765c69cdf..3091275a2fe 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1925,10 +1925,9 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings* sett } } -static void valueFlowEnumValue(SymbolDatabase * symboldatabase, const Settings * settings) +static void valueFlowEnumValue(SymbolDatabase & symboldatabase, const Settings * settings) { - - for (Scope & scope : symboldatabase->scopeList) { + for (Scope & scope : symboldatabase.scopeList) { if (scope.type != Scope::eEnum) continue; MathLib::bigint value = 0; @@ -4745,7 +4744,7 @@ static bool isContainerOfPointers(const Token* tok, const Settings* settings) return vt.pointer > 0; } -static void valueFlowLifetime(TokenList &tokenlist, SymbolDatabase* /*db*/, ErrorLogger *errorLogger, const Settings *settings) +static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger *errorLogger, const Settings *settings) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->scope()) @@ -5076,11 +5075,11 @@ static const Token * findEndOfFunctionCallForParameter(const Token * parameterTo return nextAfterAstRightmostLeaf(parent); } -static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowAfterMove(TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings) { if (!tokenlist.isCPP() || settings->standards.cpp < Standards::CPP11) return; - for (const Scope * scope : symboldatabase->functionScopes) { + for (const Scope * scope : symboldatabase.functionScopes) { if (!scope) continue; const Token * start = scope->bodyStart; @@ -5215,9 +5214,9 @@ static const Scope* getLoopScope(const Token* tok) } // -static void valueFlowConditionExpressions(TokenList &tokenlist, const SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings &settings) +static void valueFlowConditionExpressions(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) { - for (const Scope * scope : symboldatabase->functionScopes) { + for (const Scope * scope : symboldatabase.functionScopes) { if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) { if (incompleteTok->isIncompleteVar()) { if (settings.debugwarnings) @@ -5345,9 +5344,9 @@ static std::set getVarIds(const Token* tok) return result; } -static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowSymbolic(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings) { - for (const Scope* scope : symboldatabase->functionScopes) { + for (const Scope* scope : symboldatabase.functionScopes) { for (Token* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { if (!Token::simpleMatch(tok, "=")) continue; @@ -5438,9 +5437,9 @@ static const Token* isStrlenOf(const Token* tok, const Token* expr, int depth = static ValueFlow::Value inferCondition(const std::string& op, const Token* varTok, MathLib::bigint val); -static void valueFlowSymbolicOperators(const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, const Settings* settings) { - for (const Scope* scope : symboldatabase->functionScopes) { + for (const Scope* scope : symboldatabase.functionScopes) { for (Token* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { if (tok->hasKnownIntValue()) continue; @@ -5549,9 +5548,9 @@ struct SymbolicInferModel : InferModel { } }; -static void valueFlowSymbolicInfer(const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowSymbolicInfer(const SymbolDatabase& symboldatabase, const Settings* settings) { - for (const Scope* scope : symboldatabase->functionScopes) { + for (const Scope* scope : symboldatabase.functionScopes) { for (Token* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { if (!Token::Match(tok, "-|%comp%")) continue; @@ -5829,12 +5828,12 @@ static bool intersects(const C1& c1, const C2& c2) } static void valueFlowAfterAssign(TokenList &tokenlist, - const SymbolDatabase* symboldatabase, + const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings, const std::set& skippedFunctions) { - for (const Scope * scope : symboldatabase->functionScopes) { + for (const Scope * scope : symboldatabase.functionScopes) { if (skippedFunctions.count(scope)) continue; std::unordered_map> backAssigns; @@ -5966,11 +5965,11 @@ static std::vector getVariables(const Token* tok) } static void valueFlowAfterSwap(TokenList& tokenlist, - const SymbolDatabase* symboldatabase, + const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings* settings) { - for (const Scope* scope : symboldatabase->functionScopes) { + for (const Scope* scope : symboldatabase.functionScopes) { for (Token* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { if (!Token::simpleMatch(tok, "swap (")) continue; @@ -6140,12 +6139,12 @@ struct ConditionHandler { } void traverseCondition(const TokenList& tokenlist, - const SymbolDatabase* symboldatabase, + const SymbolDatabase& symboldatabase, const Settings* settings, const std::set& skippedFunctions, const std::function& f) const { - for (const Scope *scope : symboldatabase->functionScopes) { + for (const Scope *scope : symboldatabase.functionScopes) { if (skippedFunctions.count(scope)) continue; for (Token *tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { @@ -6178,7 +6177,7 @@ struct ConditionHandler { } void beforeCondition(TokenList& tokenlist, - const SymbolDatabase* symboldatabase, + const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings* settings, const std::set& skippedFunctions) const { @@ -6326,7 +6325,7 @@ struct ConditionHandler { } void afterCondition(TokenList& tokenlist, - const SymbolDatabase* symboldatabase, + const SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings* settings, const std::set& skippedFunctions) const { @@ -6659,7 +6658,7 @@ struct ConditionHandler { static void valueFlowCondition(const ValuePtr& handler, TokenList& tokenlist, - SymbolDatabase* symboldatabase, + SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings* settings, const std::set& skippedFunctions) @@ -7082,9 +7081,9 @@ static void valueFlowForLoopSimplifyAfter(Token* fortok, nonneg int varid, const } } -static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) +static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings) { - for (const Scope &scope : symboldatabase->scopeList) { + for (const Scope &scope : symboldatabase.scopeList) { if (scope.type != Scope::eFor) continue; @@ -7158,10 +7157,9 @@ static void valueFlowForLoop(TokenList &tokenlist, const SymbolDatabase* symbold struct MultiValueFlowAnalyzer : ValueFlowAnalyzer { std::unordered_map values; std::unordered_map vars; - SymbolDatabase* symboldatabase; - MultiValueFlowAnalyzer(const std::unordered_map& args, const TokenList& t, const Settings* set, SymbolDatabase* s) - : ValueFlowAnalyzer(t, set), values(), vars(), symboldatabase(s) { + MultiValueFlowAnalyzer(const std::unordered_map& args, const TokenList& t, const Settings* set) + : ValueFlowAnalyzer(t, set), values(), vars() { for (const auto& p:args) { values[p.first->declarationId()] = p.second; vars[p.first->declarationId()] = p.first; @@ -7357,14 +7355,13 @@ bool productParams(const Settings* settings, const std::unordered_map>& vars) { const bool r = productParams(&settings, vars, [&](const std::unordered_map& arg) { - MultiValueFlowAnalyzer a(arg, tokenlist, &settings, symboldatabase); + MultiValueFlowAnalyzer a(arg, tokenlist, &settings); valueFlowGenericForward(const_cast(functionScope->bodyStart), functionScope->bodyEnd, a, settings); }); if (!r) { @@ -7399,9 +7396,9 @@ static void valueFlowInjectParameter(const TokenList& tokenlist, settings); } -static void valueFlowSwitchVariable(TokenList &tokenlist, const SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) +static void valueFlowSwitchVariable(TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings *settings) { - for (const Scope &scope : symboldatabase->scopeList) { + for (const Scope &scope : symboldatabase.scopeList) { if (scope.type != Scope::ScopeType::eSwitch) continue; if (!Token::Match(scope.classDef, "switch ( %var% ) {")) @@ -7535,10 +7532,10 @@ IteratorRange MakeIteratorRange(Iterator start, Iterator last) return {start, last}; } -static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase* symboldatabase, ErrorLogger* errorLogger, const Settings& settings) +static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings& settings) { int id = 0; - for (const Scope* scope : MakeIteratorRange(symboldatabase->functionScopes.crbegin(), symboldatabase->functionScopes.crend())) { + for (const Scope* scope : MakeIteratorRange(symboldatabase.functionScopes.crbegin(), symboldatabase.functionScopes.crend())) { const Function* function = scope->function; if (!function) continue; @@ -7612,17 +7609,17 @@ static void valueFlowSubFunction(TokenList& tokenlist, SymbolDatabase* symboldat argvars[argvar] = argvalues; } - valueFlowInjectParameter(tokenlist, symboldatabase, errorLogger, settings, calledFunctionScope, argvars); + valueFlowInjectParameter(tokenlist, errorLogger, settings, calledFunctionScope, argvars); } } } -static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowFunctionDefaultParameter(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings) { if (!tokenlist.isCPP()) return; - for (const Scope* scope : symboldatabase->functionScopes) { + for (const Scope* scope : symboldatabase.functionScopes) { const Function* function = scope->function; if (!function) continue; @@ -7947,7 +7944,7 @@ static Token* findStartToken(const Variable* var, Token* start, const Library* l return tok; } -static void valueFlowUninit(TokenList& tokenlist, SymbolDatabase* /*symbolDatabase*/, const Settings* settings) +static void valueFlowUninit(TokenList& tokenlist, const Settings* settings) { for (Token *tok = tokenlist.front(); tok; tok = tok->next()) { if (!tok->scope()->isExecutable()) @@ -8677,13 +8674,13 @@ static const Scope* getFunctionScope(const Scope* scope) { } static void valueFlowContainerSize(TokenList& tokenlist, - const SymbolDatabase* symboldatabase, + const SymbolDatabase& symboldatabase, ErrorLogger* /*errorLogger*/, const Settings* settings, const std::set& skippedFunctions) { // declaration - for (const Variable *var : symboldatabase->variableList()) { + for (const Variable *var : symboldatabase.variableList()) { if (!var) continue; if (!var->scope() || !var->scope()->bodyEnd || !var->scope()->bodyStart) @@ -8754,7 +8751,7 @@ static void valueFlowContainerSize(TokenList& tokenlist, } // after assignment - for (const Scope *functionScope : symboldatabase->functionScopes) { + for (const Scope *functionScope : symboldatabase.functionScopes) { for (Token* tok = const_cast(functionScope->bodyStart); tok != functionScope->bodyEnd; tok = tok->next()) { if (Token::Match(tok, "%name%|;|{|} %var% = %str% ;")) { Token* containerTok = tok->next(); @@ -8891,7 +8888,7 @@ struct ContainerConditionHandler : ConditionHandler { } }; -static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings) { auto getBufferSizeFromAllocFunc = [&](const Token* funcTok) -> MathLib::bigint { MathLib::bigint sizeValue = -1; @@ -8962,7 +8959,7 @@ static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolD return sizeValue; }; - for (const Scope *functionScope : symboldatabase->functionScopes) { + for (const Scope *functionScope : symboldatabase.functionScopes) { for (const Token *tok = functionScope->bodyStart; tok != functionScope->bodyEnd; tok = tok->next()) { if (!Token::Match(tok, "[;{}] %var% =")) continue; @@ -8976,7 +8973,7 @@ static void valueFlowDynamicBufferSize(const TokenList& tokenlist, const SymbolD if (!rhs) continue; - const bool isNew = symboldatabase->isCPP() && rhs->str() == "new"; + const bool isNew = symboldatabase.isCPP() && rhs->str() == "new"; if (!isNew && !Token::Match(rhs->previous(), "%name% (")) continue; @@ -9060,9 +9057,9 @@ static bool getMinMaxValues(const std::string &typestr, const Settings *settings return getMinMaxValues(&vt, settings->platform, minvalue, maxvalue); } -static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase* symboldatabase, const Settings* settings) +static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& symboldatabase, const Settings* settings) { - for (const Scope *functionScope : symboldatabase->functionScopes) { + for (const Scope *functionScope : symboldatabase.functionScopes) { if (!functionScope->bodyStart) continue; const Function *function = functionScope->function; @@ -9216,14 +9213,14 @@ const ValueFlow::Value *ValueFlow::valueFlowConstantFoldAST(Token *expr, const S struct ValueFlowState { explicit ValueFlowState(TokenList& tokenlist, - SymbolDatabase* symboldatabase = nullptr, + SymbolDatabase& symboldatabase, ErrorLogger* errorLogger = nullptr, const Settings* settings = nullptr) : tokenlist(tokenlist), symboldatabase(symboldatabase), errorLogger(errorLogger), settings(settings) {} TokenList& tokenlist; - SymbolDatabase* symboldatabase = nullptr; + SymbolDatabase& symboldatabase; ErrorLogger* errorLogger = nullptr; const Settings* settings = nullptr; std::set skippedFunctions = {}; @@ -9313,7 +9310,7 @@ struct ValueFlowPassRunner { void setSkippedFunctions() { if (state.settings->performanceValueFlowMaxIfCount > 0) { - for (const Scope* functionScope : state.symboldatabase->functionScopes) { + for (const Scope* functionScope : state.symboldatabase.functionScopes) { int countIfScopes = 0; std::vector scopes{functionScope}; while (!scopes.empty()) { @@ -9386,7 +9383,7 @@ ValueFlowPassAdaptor makeValueFlowPassAdaptor(const char* name, bool cpp, F r makeValueFlowPassAdaptor(#__VA_ARGS__, \ cpp, \ [](TokenList& tokenlist, \ - SymbolDatabase* symboldatabase, \ + SymbolDatabase& symboldatabase, \ ErrorLogger* errorLogger, \ const Settings* settings, \ const std::set& skippedFunctions) { \ @@ -9402,7 +9399,7 @@ ValueFlowPassAdaptor makeValueFlowPassAdaptor(const char* name, bool cpp, F r #define VFA_CPP(...) VALUEFLOW_ADAPTOR(true, __VA_ARGS__) void ValueFlow::setValues(TokenList& tokenlist, - SymbolDatabase* symboldatabase, + SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings* settings, TimerResultsIntf* timerResults) @@ -9422,7 +9419,7 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowNumber(tokenlist, settings)), VFA(valueFlowGlobalStaticVar(tokenlist, settings)), VFA(valueFlowPointerAlias(tokenlist, settings)), - VFA(valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings)), + VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), VFA(valueFlowSymbolic(tokenlist, symboldatabase, settings)), VFA(valueFlowBitAnd(tokenlist, settings)), VFA(valueFlowSameExpressions(tokenlist, settings)), @@ -9445,9 +9442,9 @@ void ValueFlow::setValues(TokenList& tokenlist, VFA(valueFlowForLoop(tokenlist, symboldatabase, errorLogger, settings)), VFA(valueFlowSubFunction(tokenlist, symboldatabase, errorLogger, *settings)), VFA(valueFlowFunctionReturn(tokenlist, errorLogger, settings)), - VFA(valueFlowLifetime(tokenlist, symboldatabase, errorLogger, settings)), + VFA(valueFlowLifetime(tokenlist, errorLogger, settings)), VFA(valueFlowFunctionDefaultParameter(tokenlist, symboldatabase, settings)), - VFA(valueFlowUninit(tokenlist, symboldatabase, settings)), + VFA(valueFlowUninit(tokenlist, settings)), VFA_CPP(valueFlowAfterMove(tokenlist, symboldatabase, settings)), VFA_CPP(valueFlowSmartPointer(tokenlist, errorLogger, settings)), VFA_CPP(valueFlowIterators(tokenlist, settings)), diff --git a/lib/valueflow.h b/lib/valueflow.h index d54de1e206a..0c0395a37ef 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -52,7 +52,7 @@ namespace ValueFlow { /// Perform valueflow analysis. void setValues(TokenList& tokenlist, - SymbolDatabase* symboldatabase, + SymbolDatabase& symboldatabase, ErrorLogger* errorLogger, const Settings* settings, TimerResultsIntf* timerResults); From cc592a69277e54691f4d2250f24cbac42b2ab32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 7 Aug 2023 19:48:11 +0200 Subject: [PATCH 03/18] CppCheckExecutor: improved library loading error handling a bit (#5275) --- cli/cppcheckexecutor.cpp | 32 ++++++++++++++------------------ test/cli/test-other.py | 13 ++++++++++++- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 06dcd597205..30ed27a0e81 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -43,6 +43,7 @@ #endif #include +#include #include #include // EXIT_SUCCESS and EXIT_FAILURE #include @@ -66,6 +67,8 @@ #include #endif +// TODO: do not directly write to stdout + /*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout; @@ -319,21 +322,7 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) bool CppCheckExecutor::loadLibraries(Settings& settings) { - const bool std = tryLoadLibrary(settings.library, settings.exename, "std.cfg"); - - const auto failed_lib = std::find_if(settings.libraries.begin(), settings.libraries.end(), [&](const std::string& lib) { - return !tryLoadLibrary(settings.library, settings.exename, lib.c_str()); - }); - if (failed_lib != settings.libraries.end()) { - const std::string msg("Failed to load the library " + *failed_lib); - const std::list callstack; - ErrorMessage errmsg(callstack, emptyString, Severity::information, msg, "failedToLoadCfg", Certainty::normal); - reportErr(errmsg); - return false; - } - - if (!std) { - const std::list callstack; + if (!tryLoadLibrary(settings.library, settings.exename, "std.cfg")) { const std::string msg("Failed to load std.cfg. Your Cppcheck installation is broken, please re-install."); #ifdef FILESDIR const std::string details("The Cppcheck binary was compiled with FILESDIR set to \"" @@ -345,12 +334,17 @@ bool CppCheckExecutor::loadLibraries(Settings& settings) "std.cfg should be available in " + cfgfolder + " or the FILESDIR " "should be configured."); #endif - ErrorMessage errmsg(callstack, emptyString, Severity::information, msg+" "+details, "failedToLoadCfg", Certainty::normal); - reportErr(errmsg); + std::cout << msg << " " << details << std::endl; return false; } - return true; + bool result = true; + for (const auto& lib : settings.libraries) { + if (!tryLoadLibrary(settings.library, settings.exename, lib.c_str())) { + result = false; + } + } + return result; } #ifdef _WIN32 @@ -424,6 +418,8 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg) return; } + assert(mSettings != nullptr); + // Alert only about unique errors if (!mShownErrors.insert(msg.toString(mSettings->verbose)).second) return; diff --git a/test/cli/test-other.py b/test/cli/test-other.py index 29db8ea0c9f..d1e329434a1 100644 --- a/test/cli/test-other.py +++ b/test/cli/test-other.py @@ -60,4 +60,15 @@ def test_missing_include_inline_suppr(tmpdir): args = ['--enable=missingInclude', '--inline-suppr', test_file] _, _, stderr = cppcheck(args) - assert stderr == '' \ No newline at end of file + assert stderr == '' + +def test_invalid_library(tmpdir): + args = ['--library=none', '--library=posix', '--library=none2', '--platform=native', 'file.c'] + + exitcode, stdout, stderr = cppcheck(args) + assert exitcode == 1 + assert (stdout == "cppcheck: Failed to load library configuration file 'none'. File not found\n" + "cppcheck: Failed to load library configuration file 'none2'. File not found\n") + assert stderr == "" + +# TODO: test missing std.cfg \ No newline at end of file From dcdf67a694a61569041d0a12245f4707e07415da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 7 Aug 2023 20:44:25 +0200 Subject: [PATCH 04/18] some `-Wdouble-promotion` Clang compiler warnings (#4820) --- cmake/compileroptions.cmake | 23 +++++++++++++++-------- externals/tinyxml2/CMakeLists.txt | 1 + lib/calculate.h | 2 +- lib/checkcondition.cpp | 2 +- lib/valueflow.cpp | 4 ++-- test/testvalueflow.cpp | 23 +++++++++++++++-------- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/cmake/compileroptions.cmake b/cmake/compileroptions.cmake index 74256f5abde..e7d0a3bf787 100644 --- a/cmake/compileroptions.cmake +++ b/cmake/compileroptions.cmake @@ -73,14 +73,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_link_options(-lc++) endif() - add_compile_options_safe(-Wno-documentation-unknown-command) - # TODO: fix and enable these warnings - or move to suppression list below + add_compile_options_safe(-Wno-documentation-unknown-command) # TODO: Clang currently does not support all commands add_compile_options_safe(-Wno-inconsistent-missing-destructor-override) # caused by Qt moc code add_compile_options_safe(-Wno-unused-exception-parameter) add_compile_options_safe(-Wno-old-style-cast) - add_compile_options_safe(-Wno-global-constructors) - add_compile_options_safe(-Wno-exit-time-destructors) add_compile_options_safe(-Wno-sign-conversion) add_compile_options_safe(-Wno-shadow-field-in-constructor) add_compile_options_safe(-Wno-covered-switch-default) @@ -102,16 +99,26 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options_safe(-Wno-tautological-type-limit-compare) add_compile_options(-Wno-disabled-macro-expansion) add_compile_options_safe(-Wno-bitwise-instead-of-logical) + + # these cannot be fixed properly without adopting later C++ standards add_compile_options_safe(-Wno-unsafe-buffer-usage) + add_compile_options_safe(-Wno-global-constructors) + add_compile_options_safe(-Wno-exit-time-destructors) - # warnings we are not interested in - add_compile_options(-Wno-four-char-constants) - add_compile_options(-Wno-c++98-compat) - add_compile_options(-Wno-weak-vtables) + # can only be partially addressed add_compile_options(-Wno-padded) + + # no need for C++98 compatibility + add_compile_options(-Wno-c++98-compat) add_compile_options(-Wno-c++98-compat-pedantic) + + # only need to be addressed to work around issues in older compilers add_compile_options_safe(-Wno-return-std-move-in-c++11) + # warnings we are currently not interested in + add_compile_options(-Wno-four-char-constants) + add_compile_options(-Wno-weak-vtables) + if(ENABLE_COVERAGE OR ENABLE_COVERAGE_XML) message(FATAL_ERROR "Do not use clang to generate code coverage. Use GCC instead.") endif() diff --git a/externals/tinyxml2/CMakeLists.txt b/externals/tinyxml2/CMakeLists.txt index 6ec93e526f2..6ad63ecf0f0 100644 --- a/externals/tinyxml2/CMakeLists.txt +++ b/externals/tinyxml2/CMakeLists.txt @@ -17,5 +17,6 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") target_compile_options_safe(tinyxml2_objs -Wno-suggest-destructor-override) target_compile_options_safe(tinyxml2_objs -Wno-zero-as-null-pointer-constant) target_compile_options_safe(tinyxml2_objs -Wno-format-nonliteral) + target_compile_options_safe(tinyxml2_objs -Wno-old-style-cast) endif() diff --git a/lib/calculate.h b/lib/calculate.h index 3e62e212b21..96520cc629f 100644 --- a/lib/calculate.h +++ b/lib/calculate.h @@ -36,7 +36,7 @@ inline bool isEqual(double x, double y) } inline bool isEqual(float x, float y) { - return isEqual(double{x}, double{y}); + return isEqual(double(x), double(y)); } template diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index a0799b4b41c..477719d3e6d 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -981,7 +981,7 @@ T getvalue3(const T value1, const T value2) template<> double getvalue3(const double value1, const double value2) { - return (value1 + value2) / 2.0f; + return (value1 + value2) / 2.0; } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3091275a2fe..b6601ce6be4 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -9112,12 +9112,12 @@ static void valueFlowSafeFunctions(TokenList& tokenlist, const SymbolDatabase& s std::list argValues; argValues.emplace_back(0); argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT; - argValues.back().floatValue = isLow ? low : -1E25f; + argValues.back().floatValue = isLow ? low : -1E25; argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue)); argValues.back().safe = true; argValues.emplace_back(0); argValues.back().valueType = ValueFlow::Value::ValueType::FLOAT; - argValues.back().floatValue = isHigh ? high : 1E25f; + argValues.back().floatValue = isHigh ? high : 1E25; argValues.back().errorPath.emplace_back(arg.nameToken(), "Safe checks: Assuming argument has value " + MathLib::toString(argValues.back().floatValue)); argValues.back().safe = true; valueFlowForward(const_cast(functionScope->bodyStart->next()), diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 4e322596175..8a50059ef89 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -349,7 +349,7 @@ class TestValueFlow : public TestFixture { return false; } - bool testValueOfX_(const char* file, int line, const char code[], unsigned int linenr, float value, float diff) { + bool testValueOfX_(const char* file, int line, const char code[], unsigned int linenr, double value, double diff) { // Tokenize.. Tokenizer tokenizer(&settings, this); std::istringstream istr(code); @@ -565,7 +565,7 @@ class TestValueFlow : public TestFixture { void valueFlowNumber() { ASSERT_EQUALS(123, valueOfTok("x=123;", "123").intvalue); ASSERT_EQUALS_DOUBLE(192.0, valueOfTok("x=0x0.3p10;", "0x0.3p10").floatValue, 1e-5); // 3 * 16^-1 * 2^10 = 192 - ASSERT(std::fabs(valueOfTok("x=0.5;", "0.5").floatValue - 0.5f) < 0.1f); + ASSERT(std::fabs(valueOfTok("x=0.5;", "0.5").floatValue - 0.5) < 0.1); ASSERT_EQUALS(10, valueOfTok("enum {A=10,B=15}; x=A+0;", "+").intvalue); ASSERT_EQUALS(0, valueOfTok("x=false;", "false").intvalue); ASSERT_EQUALS(1, valueOfTok("x=true;", "true").intvalue); @@ -3491,7 +3491,7 @@ class TestValueFlow : public TestFixture { void valueFlowForwardCompoundAssign() { const char *code; - code = "void f() {\n" + code = "int f() {\n" " int x = 123;\n" " x += 43;\n" " return x;\n" @@ -3501,19 +3501,26 @@ class TestValueFlow : public TestFixture { "3,Compound assignment '+=', assigned value is 166\n", getErrorPathForX(code, 4U)); - code = "void f() {\n" + code = "int f() {\n" " int x = 123;\n" " x /= 0;\n" // don't crash when evaluating x/=0 " return x;\n" "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 123)); - code = "void f() {\n" - " float x = 123.45;\n" + code = "float f() {\n" + " float x = 123.45f;\n" " x += 67;\n" " return x;\n" "}"; - ASSERT_EQUALS(true, testValueOfX(code, 4U, 123.45F + 67, 0.01F)); + ASSERT_EQUALS(true, testValueOfX(code, 4U, (double)123.45f + 67, 0.01)); + + code = "double f() {\n" + " double x = 123.45;\n" + " x += 67;\n" + " return x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 4U, 123.45 + 67, 0.01)); code = "void f() {\n" " int x = 123;\n" @@ -3522,7 +3529,7 @@ class TestValueFlow : public TestFixture { "}"; ASSERT_EQUALS(true, testValueOfX(code, 4U, 61)); - code = "void f() {\n" + code = "int f() {\n" " int x = 123;\n" " x <<= 1;\n" " return x;\n" From 988edd24c2bbaa3b38ecd11534b54de1d67a0d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 7 Aug 2023 20:47:24 +0200 Subject: [PATCH 05/18] TestSingleExecutor: test clang-tidy invocation (#5294) --- cli/processexecutor.cpp | 2 ++ cli/singleexecutor.cpp | 4 +-- cli/threadexecutor.cpp | 1 + test/testprocessexecutor.cpp | 3 +++ test/testsingleexecutor.cpp | 51 +++++++++++++++++++++++++++++++++--- test/testthreadexecutor.cpp | 3 +++ 6 files changed, 59 insertions(+), 5 deletions(-) diff --git a/cli/processexecutor.cpp b/cli/processexecutor.cpp index 445b545f8c3..be9c61d1548 100644 --- a/cli/processexecutor.cpp +++ b/cli/processexecutor.cpp @@ -280,9 +280,11 @@ unsigned int ProcessExecutor::check() if (iFileSettings != mSettings.project.fileSettings.end()) { resultOfCheck = fileChecker.check(*iFileSettings); + // TODO: call analyseClangTidy() } else { // Read file from a file resultOfCheck = fileChecker.check(iFile->first); + // TODO: call analyseClangTidy()? } pipewriter.writeEnd(std::to_string(resultOfCheck)); diff --git a/cli/singleexecutor.cpp b/cli/singleexecutor.cpp index 4de711a2c84..c3fea886b24 100644 --- a/cli/singleexecutor.cpp +++ b/cli/singleexecutor.cpp @@ -61,7 +61,7 @@ unsigned int SingleExecutor::check() processedsize += i->second; if (!mSettings.quiet) reportStatus(c + 1, mFiles.size(), processedsize, totalfilesize); - // TODO: call analyseClangTidy() + // TODO: call analyseClangTidy()? c++; } } @@ -92,7 +92,7 @@ unsigned int SingleExecutor::check() processedsize += i->second; if (!mSettings.quiet) reportStatus(c + 1, mFiles.size(), processedsize, totalfilesize); - // TODO: call analyseClangTidy() + // TODO: call analyseClangTidy()? c++; } } diff --git a/cli/threadexecutor.cpp b/cli/threadexecutor.cpp index 26c3c03aa18..8590651a29a 100644 --- a/cli/threadexecutor.cpp +++ b/cli/threadexecutor.cpp @@ -129,6 +129,7 @@ class ThreadData } else { // Read file from a file result = fileChecker.check(*file); + // TODO: call analyseClangTidy()? } return result; } diff --git a/test/testprocessexecutor.cpp b/test/testprocessexecutor.cpp index f9cf2d0d9fd..ecf9a5f070c 100644 --- a/test/testprocessexecutor.cpp +++ b/test/testprocessexecutor.cpp @@ -229,6 +229,9 @@ class TestProcessExecutor : public TestFixture { output.str());*/ settings = settingsOld; } + + // TODO: test clang-tidy + // TODO: test whole program analysis }; REGISTER_TEST(TestProcessExecutor) diff --git a/test/testsingleexecutor.cpp b/test/testsingleexecutor.cpp index 9208ca72ed2..56e5e847823 100644 --- a/test/testsingleexecutor.cpp +++ b/test/testsingleexecutor.cpp @@ -67,6 +67,9 @@ class TestSingleExecutorBase : public TestFixture { SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; const char* plistOutput = nullptr; std::vector filesList; + bool executeCommandCalled = false; + std::string exe; + std::vector args; }; void check(int files, int result, const std::string &data, const CheckOptions &opt = {}) { @@ -101,9 +104,16 @@ class TestSingleExecutorBase : public TestFixture { settings.showtime = opt.showtime; if (opt.plistOutput) settings.plistOutput = opt.plistOutput; + + bool executeCommandCalled = false; + std::string exe; + std::vector args; // NOLINTNEXTLINE(performance-unnecessary-value-param) - CppCheck cppcheck(*this, true, [](std::string,std::vector,std::string,std::string&){ - return false; + CppCheck cppcheck(*this, true, [&executeCommandCalled, &exe, &args](std::string e,std::vector a,std::string,std::string&){ + executeCommandCalled = true; + exe = std::move(e); + args = std::move(a); + return true; }); cppcheck.settings() = settings; @@ -119,6 +129,13 @@ class TestSingleExecutorBase : public TestFixture { // TODO: test with settings.project.fileSettings; SingleExecutor executor(cppcheck, filemap, settings, settings.nomsg, *this); ASSERT_EQUALS(result, executor.check()); + ASSERT_EQUALS(opt.executeCommandCalled, executeCommandCalled); + ASSERT_EQUALS(opt.exe, exe); + ASSERT_EQUALS(opt.args.size(), args.size()); + for (int i = 0; i < args.size(); ++i) + { + ASSERT_EQUALS(opt.args[i], args[i]); + } } void run() override { @@ -131,6 +148,7 @@ class TestSingleExecutorBase : public TestFixture { TEST_CASE(one_error_less_files); TEST_CASE(one_error_several_files); TEST_CASE(markup); + TEST_CASE(clangTidy); } void many_files() { @@ -246,7 +264,34 @@ class TestSingleExecutorBase : public TestFixture { settings = settingsOld; } - // TODO: test clang-tidy + void clangTidy() { + // TODO: we currently only invoke it with ImportProject::FileSettings + if (!useFS) + return; + + const Settings settingsOld = settings; + settings.clangTidy = true; + +#ifdef _WIN32 + const char exe[] = "clang-tidy.exe"; +#else + const char exe[] = "clang-tidy"; +#endif + + const std::string file = fprefix() + "_001.cpp"; + check(1, 0, + "int main()\n" + "{\n" + " return 0;\n" + "}", + dinit(CheckOptions, + $.executeCommandCalled = true, + $.exe = exe, + $.args = {"-quiet", "-checks=*,-clang-analyzer-*,-llvm*", file, "--"})); + ASSERT_EQUALS("Checking " + file + " ...\n", output.str()); + settings = settingsOld; + } + // TODO: test whole program analysis }; diff --git a/test/testthreadexecutor.cpp b/test/testthreadexecutor.cpp index 8d7f11bc5e6..08cfccfda67 100644 --- a/test/testthreadexecutor.cpp +++ b/test/testthreadexecutor.cpp @@ -228,6 +228,9 @@ class TestThreadExecutor : public TestFixture { output.str());*/ settings = settingsOld; } + + // TODO: test clang-tidy + // TODO: test whole program analysis }; REGISTER_TEST(TestThreadExecutor) From 072212e708a7c1d8774dafa6e4185580b4b9dea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Mon, 7 Aug 2023 20:49:10 +0200 Subject: [PATCH 06/18] added `TestCheck` and moved some tests from `TestCppcheck` (#5289) --- Makefile | 4 ++++ test/testcheck.cpp | 53 +++++++++++++++++++++++++++++++++++++++++ test/testcppcheck.cpp | 25 ------------------- test/testrunner.vcxproj | 1 + 4 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 test/testcheck.cpp diff --git a/Makefile b/Makefile index fe2665a7726..946755da0cb 100644 --- a/Makefile +++ b/Makefile @@ -278,6 +278,7 @@ TESTOBJ = test/fixture.o \ test/testboost.o \ test/testbufferoverrun.o \ test/testcharvar.o \ + test/testcheck.o \ test/testclangimport.o \ test/testclass.o \ test/testcmdlineparser.o \ @@ -706,6 +707,9 @@ test/testbufferoverrun.o: test/testbufferoverrun.cpp externals/simplecpp/simplec test/testcharvar.o: test/testcharvar.cpp lib/check.h lib/checkother.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcharvar.cpp +test/testcheck.o: test/testcheck.cpp lib/check.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/utils.h test/fixture.h + $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testcheck.cpp + test/testclangimport.o: test/testclangimport.cpp lib/check.h lib/clangimport.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/vfvalue.h test/fixture.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o $@ test/testclangimport.cpp diff --git a/test/testcheck.cpp b/test/testcheck.cpp new file mode 100644 index 00000000000..8e570712407 --- /dev/null +++ b/test/testcheck.cpp @@ -0,0 +1,53 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2023 Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "check.h" +#include "fixture.h" + +class TestCheck : public TestFixture { +public: + TestCheck() : TestFixture("TestCheck") {} + +private: + void run() override { + TEST_CASE(instancesSorted); + TEST_CASE(classInfoFormat); + } + + void instancesSorted() const { + for (std::list::const_iterator i = Check::instances().cbegin(); i != Check::instances().cend(); ++i) { + std::list::const_iterator j = i; + ++j; + if (j != Check::instances().cend()) { + ASSERT_EQUALS(true, (*i)->name() < (*j)->name()); + } + } + } + + void classInfoFormat() const { + for (std::list::const_iterator i = Check::instances().cbegin(); i != Check::instances().cend(); ++i) { + const std::string info = (*i)->classInfo(); + if (!info.empty()) { + ASSERT('\n' != info[0]); // No \n in the beginning + ASSERT('\n' == info.back()); // \n at end + if (info.size() > 1) + ASSERT('\n' != info[info.length()-2]); // Only one \n at end + } + } + } +}; diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 08b1adcbd94..60726a425ea 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include "check.h" #include "color.h" #include "cppcheck.h" #include "errorlogger.h" @@ -45,33 +44,9 @@ class TestCppcheck : public TestFixture { }; void run() override { - TEST_CASE(instancesSorted); - TEST_CASE(classInfoFormat); TEST_CASE(getErrorMessages); } - void instancesSorted() const { - for (std::list::const_iterator i = Check::instances().cbegin(); i != Check::instances().cend(); ++i) { - std::list::const_iterator j = i; - ++j; - if (j != Check::instances().cend()) { - ASSERT_EQUALS(true, (*i)->name() < (*j)->name()); - } - } - } - - void classInfoFormat() const { - for (std::list::const_iterator i = Check::instances().cbegin(); i != Check::instances().cend(); ++i) { - const std::string info = (*i)->classInfo(); - if (!info.empty()) { - ASSERT('\n' != info[0]); // No \n in the beginning - ASSERT('\n' == info.back()); // \n at end - if (info.size() > 1) - ASSERT('\n' != info[info.length()-2]); // Only one \n at end - } - } - } - void getErrorMessages() const { ErrorLogger2 errorLogger; CppCheck::getErrorMessages(errorLogger); diff --git a/test/testrunner.vcxproj b/test/testrunner.vcxproj index 79903520643..b0ed00c2f34 100755 --- a/test/testrunner.vcxproj +++ b/test/testrunner.vcxproj @@ -72,6 +72,7 @@ + From 610777d5865c563cdc2952618df665597765b09f Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 7 Aug 2023 21:40:33 +0200 Subject: [PATCH 07/18] Set enum ValueType for :: (#5298) --- lib/symboldatabase.cpp | 6 +++++- test/testsymboldatabase.cpp | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b601689f48d..97f644f4c0f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6414,8 +6414,12 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, Source if (it != typeScope->varlist.end()) var = &*it; } - if (var) + if (var) { setValueType(parent, *var); + return; + } + if (const Enumerator* enu = parent->astOperand2()->enumerator()) + setValueType(parent, *enu); return; } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 8c2bec6bd8f..4171f68a75c 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -384,6 +384,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(enum10); // #11001 TEST_CASE(enum11); TEST_CASE(enum12); + TEST_CASE(enum13); TEST_CASE(sizeOfType); @@ -5701,6 +5702,23 @@ class TestSymbolDatabase : public TestFixture { ASSERT_EQUALS(e->enumerator(), E0); } + void enum13() { + GET_SYMBOL_DB("struct S { enum E { E0, E1 }; };\n" + "void f(bool b) {\n" + " auto e = b ? S::E0 : S::E1;\n" + "}\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 2); + const Enumerator* E1 = it->findEnumerator("E1"); + ASSERT(E1 && E1->value_known); + ASSERT_EQUALS(E1->value, 1); + const Token* const a = Token::findsimplematch(tokenizer.tokens(), "auto"); + ASSERT(a && a->valueType()); + TODO_ASSERT(E1->scope == a->valueType()->typeScope); + ASSERT_EQUALS(a->valueType()->type, ValueType::INT); + } + void sizeOfType() { // #7615 - crash in Symboldatabase::sizeOfType() GET_SYMBOL_DB("enum e;\n" From 838b6b86e3dbeab6e525039bc5f9020587595d01 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 8 Aug 2023 10:38:03 +0200 Subject: [PATCH 08/18] Fix #11862 FN constParameterPointer with increment (#5291) --- lib/astutils.cpp | 19 ++++++++++++------- lib/checkother.cpp | 13 +++++++++---- lib/checkunusedvar.cpp | 4 ++-- lib/valueflow.cpp | 25 +++++++++++++++++-------- test/testother.cpp | 8 +++++++- test/teststl.cpp | 29 +++++++++++------------------ 6 files changed, 58 insertions(+), 40 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 94307ab276f..ca7c08af30a 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -2188,7 +2188,7 @@ T* getTokenArgumentFunctionImpl(T* tok, int& argn) argn = -1; { T* parent = tok->astParent(); - if (parent && parent->isUnaryOp("&")) + if (parent && (parent->isUnaryOp("&") || parent->isIncDecOp())) parent = parent->astParent(); while (parent && parent->isCast()) parent = parent->astParent(); @@ -2196,7 +2196,7 @@ T* getTokenArgumentFunctionImpl(T* tok, int& argn) parent = parent->astParent(); // passing variable to subfunction? - if (Token::Match(parent, "[[(,{]")) + if (Token::Match(parent, "[*[(,{]")) ; else if (Token::simpleMatch(parent, ":")) { while (Token::Match(parent, "[?:]")) @@ -2347,6 +2347,10 @@ bool isVariableChangedByFunctionCall(const Token *tok, int indirect, const Setti if (addressOf) indirect++; + const bool deref = tok->astParent() && tok->astParent()->isUnaryOp("*"); + if (deref && indirect > 0) + indirect--; + int argnr; tok = getTokenArgumentFunction(tok, argnr); if (!tok) @@ -2455,7 +2459,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, (Token::simpleMatch(tok2->astParent(), ":") && Token::simpleMatch(tok2->astParent()->astParent(), "?"))) tok2 = tok2->astParent(); - if (tok2->astParent() && tok2->astParent()->tokType() == Token::eIncDecOp) + if (indirect == 0 && tok2->astParent() && tok2->astParent()->tokType() == Token::eIncDecOp) return true; auto skipRedundantPtrOp = [](const Token* tok, const Token* parent) { @@ -2578,7 +2582,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, const Token *parent = tok2->astParent(); while (Token::Match(parent, ".|::")) parent = parent->astParent(); - if (parent && parent->tokType() == Token::eIncDecOp) + if (parent && parent->tokType() == Token::eIncDecOp && (indirect == 0 || tok2 != tok)) return true; // structured binding, nonconst reference variable in lhs @@ -2615,7 +2619,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings *settings, if (indirect > 0) { // check for `*(ptr + 1) = new_value` case parent = tok2->astParent(); - while (parent && parent->isArithmeticalOp() && parent->isBinaryOp()) { + while (parent && ((parent->isArithmeticalOp() && parent->isBinaryOp()) || parent->isIncDecOp())) { parent = parent->astParent(); } if (Token::simpleMatch(parent, "*")) { @@ -2839,8 +2843,9 @@ bool isExpressionChanged(const Token* expr, const Token* start, const Token* end if (vt->type == ValueType::ITERATOR) ++indirect; } - if (isExpressionChangedAt(tok, tok2, indirect, global, settings, cpp, depth)) - return true; + for (int i = 0; i <= indirect; ++i) + if (isExpressionChangedAt(tok, tok2, i, global, settings, cpp, depth)) + return true; } } return false; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index cf421268bca..f11a523a940 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1587,9 +1587,10 @@ void CheckOther::checkConstPointer() if (std::find(nonConstPointers.cbegin(), nonConstPointers.cend(), var) != nonConstPointers.cend()) continue; pointers.emplace_back(var); - const Token* const parent = tok->astParent(); + const Token* parent = tok->astParent(); enum Deref { NONE, DEREF, MEMBER } deref = NONE; - if (parent && parent->isUnaryOp("*")) + bool hasIncDec = false; + if (parent && (parent->isUnaryOp("*") || (hasIncDec = parent->isIncDecOp() && parent->astParent() && parent->astParent()->isUnaryOp("*")))) deref = DEREF; else if (Token::simpleMatch(parent, "[") && parent->astOperand1() == tok && tok != nameTok) deref = DEREF; @@ -1600,7 +1601,7 @@ void CheckOther::checkConstPointer() else if (astIsRangeBasedForDecl(tok)) continue; if (deref != NONE) { - const Token* const gparent = parent->astParent(); + const Token* gparent = parent->astParent(); if (deref == MEMBER) { if (!gparent) continue; @@ -1613,6 +1614,10 @@ void CheckOther::checkConstPointer() } if (Token::Match(gparent, "%cop%") && !gparent->isUnaryOp("&") && !gparent->isUnaryOp("*")) continue; + if (hasIncDec) { + parent = gparent; + gparent = gparent ? gparent->astParent() : nullptr; + } int argn = -1; if (Token::simpleMatch(gparent, "return")) { const Function* function = gparent->scope()->function; @@ -1633,7 +1638,7 @@ void CheckOther::checkConstPointer() continue; else if (const Token* ftok = getTokenArgumentFunction(parent, argn)) { bool inconclusive{}; - if (!isVariableChangedByFunctionCall(ftok, vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) + if (!isVariableChangedByFunctionCall(ftok->next(), vt->pointer, var->declarationId(), mSettings, &inconclusive) && !inconclusive) continue; } } else { diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index bd42a61824c..9f0ea5dc35c 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1691,8 +1691,8 @@ bool CheckUnusedVar::isFunctionWithoutSideEffects(const Function& func, const To } // check if global variable is changed if (bodyVariable->isGlobal() || (pointersToGlobals.find(bodyVariable) != pointersToGlobals.end())) { - const int depth = 20; - if (isVariableChanged(bodyToken, depth, mSettings, mTokenizer->isCPP())) { + const int indirect = bodyVariable->isArray() ? bodyVariable->dimensions().size() : bodyVariable->isPointer(); + if (isVariableChanged(bodyToken, indirect, mSettings, mTokenizer->isCPP())) { return false; } // check if pointer to global variable assigned to another variable (another_var = &global_var) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index b6601ce6be4..dcadeaee973 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2564,19 +2564,22 @@ struct ValueFlowAnalyzer : Analyzer { return read; } - virtual Action isAliasModified(const Token* tok) const { + virtual Action isAliasModified(const Token* tok, int indirect = -1) const { // Lambda function call if (Token::Match(tok, "%var% (")) // TODO: Check if modified in the lambda function return Action::Invalid; - int indirect = 0; - if (const ValueType* vt = tok->valueType()) { - indirect = vt->pointer; - if (vt->type == ValueType::ITERATOR) - ++indirect; + if (indirect == -1) { + indirect = 0; + if (const ValueType* vt = tok->valueType()) { + indirect = vt->pointer; + if (vt->type == ValueType::ITERATOR) + ++indirect; + } } - if (isVariableChanged(tok, indirect, getSettings(), isCPP())) - return Action::Invalid; + for (int i = 0; i <= indirect; ++i) + if (isVariableChanged(tok, i, getSettings(), isCPP())) + return Action::Invalid; return Action::None; } @@ -3213,6 +3216,12 @@ struct ExpressionAnalyzer : SingleValueFlowAnalyzer { bool isVariable() const override { return expr->varId() > 0; } + + Action isAliasModified(const Token* tok, int indirect) const override { + if (value.isSymbolicValue() && tok->exprId() == value.tokvalue->exprId()) + indirect = 0; + return SingleValueFlowAnalyzer::isAliasModified(tok, indirect); + } }; struct SameExpressionAnalyzer : ExpressionAnalyzer { diff --git a/test/testother.cpp b/test/testother.cpp index cc2be93e03d..eb1b300122f 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -3800,6 +3800,12 @@ class TestOther : public TestFixture { " return strlen(p);\n" "}\n"); ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", errout.str()); + + check("void f(int* p) {\n" // #11862 + " long long j = *(p++);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:1]: (style) Parameter 'p' can be declared as pointer to const\n", + errout.str()); } void switchRedundantAssignmentTest() { @@ -8128,7 +8134,7 @@ class TestOther : public TestFixture { "void packed_object_info(struct object_info *oi) {\n" " if (*oi->typep < 0);\n" "}"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (style) Parameter 'oi' can be declared as pointer to const\n", errout.str()); } void checkSuspiciousSemicolon1() { diff --git a/test/teststl.cpp b/test/teststl.cpp index b25a4443108..bb9f3ad7b57 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -2819,27 +2819,20 @@ class TestStl : public TestFixture { } void eraseOnVector() { - check("void f(const std::vector& m_ImplementationMap) {\n" - " std::vector::iterator aIt = m_ImplementationMap.begin();\n" - " m_ImplementationMap.erase(something(unknown));\n" // All iterators become invalidated when erasing from std::vector - " m_ImplementationMap.erase(aIt);\n" - "}"); - ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'm_ImplementationMap' that may be invalid.\n", errout.str()); - - check("void f(const std::vector& m_ImplementationMap) {\n" - " std::vector::iterator aIt = m_ImplementationMap.begin();\n" - " m_ImplementationMap.erase(*aIt);\n" // All iterators become invalidated when erasing from std::vector - " m_ImplementationMap.erase(aIt);\n" + check("void f(std::vector& v) {\n" + " std::vector::iterator aIt = v.begin();\n" + " v.erase(something(unknown));\n" // All iterators become invalidated when erasing from std::vector + " v.erase(aIt);\n" "}"); - ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'm_ImplementationMap' that may be invalid.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2] -> [test.cpp:3] -> [test.cpp:1] -> [test.cpp:4]: (error) Using iterator to local container 'v' that may be invalid.\n", errout.str()); - check("void f(const std::vector& m_ImplementationMap) {\n" - " std::vector::iterator aIt = m_ImplementationMap.begin();\n" - " std::vector::iterator bIt = m_ImplementationMap.begin();\n" - " m_ImplementationMap.erase(*bIt);\n" // All iterators become invalidated when erasing from std::vector - " aIt = m_ImplementationMap.erase(aIt);\n" + check("void f(std::vector& v) {\n" + " std::vector::iterator aIt = v.begin();\n" + " std::vector::iterator bIt = v.begin();\n" + " v.erase(bIt);\n" // All iterators become invalidated when erasing from std::vector + " aIt = v.erase(aIt);\n" "}"); - ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'm_ImplementationMap' that may be invalid.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2] -> [test.cpp:4] -> [test.cpp:1] -> [test.cpp:5]: (error) Using iterator to local container 'v' that may be invalid.\n", errout.str()); } void pushback1() { From eee122173875c1257c20603bec88c336a99a13f8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:05:02 +0200 Subject: [PATCH 09/18] Use in-class initializers, default constructors, class -> struct (#4842) --- .clang-tidy | 66 +++++++- clang-tidy.md | 8 +- cli/cmdlineparser.cpp | 4 - cli/cmdlineparser.h | 8 +- cli/cppcheckexecutor.cpp | 4 - cli/cppcheckexecutor.h | 10 +- cli/threadexecutor.cpp | 10 +- gui/applicationlist.cpp | 3 +- gui/applicationlist.h | 2 +- gui/checkthread.cpp | 4 +- gui/checkthread.h | 4 +- gui/codeeditorstyle.cpp | 1 - gui/codeeditorstyle.h | 2 +- gui/codeeditstylecontrols.cpp | 3 +- gui/codeeditstylecontrols.h | 2 +- gui/cppchecklibrarydata.h | 83 +++------- gui/helpdialog.h | 4 +- gui/librarydialog.cpp | 3 +- gui/librarydialog.h | 2 +- gui/mainwindow.cpp | 6 +- gui/mainwindow.h | 8 +- gui/report.cpp | 1 - gui/resultstree.cpp | 14 +- gui/resultstree.h | 24 +-- gui/resultsview.cpp | 1 - gui/resultsview.h | 2 +- gui/statsdialog.cpp | 3 +- gui/statsdialog.h | 2 +- gui/test/projectfile/testprojectfile.cpp | 3 +- gui/threadhandler.cpp | 6 +- gui/threadhandler.h | 6 +- gui/threadresult.cpp | 5 - gui/threadresult.h | 10 +- gui/translationhandler.cpp | 3 +- gui/translationhandler.h | 2 +- lib/analyzer.h | 4 +- lib/check.cpp | 2 +- lib/check.h | 6 +- lib/checkclass.h | 10 +- lib/checkio.cpp | 19 +-- lib/checkio.h | 16 +- lib/checkuninitvar.h | 4 +- lib/checkunusedfunctions.h | 11 +- lib/checkunusedvar.cpp | 2 +- lib/clangimport.cpp | 18 +-- lib/cppcheck.cpp | 3 - lib/cppcheck.h | 6 +- lib/ctu.cpp | 2 - lib/forwardanalyzer.cpp | 8 +- lib/fwdanalysis.h | 14 +- lib/importproject.cpp | 4 +- lib/importproject.h | 7 +- lib/library.cpp | 3 - lib/library.h | 147 ++++++----------- lib/mathlib.cpp | 3 +- lib/mathlib.h | 6 +- lib/programmemory.cpp | 2 +- lib/settings.cpp | 38 ----- lib/settings.h | 103 ++++++------ lib/standards.h | 7 +- lib/suppressions.h | 14 +- lib/symboldatabase.cpp | 57 +------ lib/symboldatabase.h | 191 ++++++++--------------- lib/templatesimplifier.cpp | 2 +- lib/templatesimplifier.h | 2 +- lib/timer.cpp | 3 - lib/timer.h | 16 +- lib/token.cpp | 7 +- lib/token.h | 92 +++++------ lib/tokenize.cpp | 27 ++-- lib/tokenize.h | 10 +- lib/tokenlist.cpp | 19 +-- lib/tokenlist.h | 6 +- lib/valueflow.cpp | 75 ++++----- lib/valueflow.h | 12 +- lib/vfvalue.cpp | 21 +-- lib/vfvalue.h | 61 +++----- test/fixture.cpp | 5 +- test/fixture.h | 4 +- test/testtoken.cpp | 4 +- 80 files changed, 531 insertions(+), 861 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 95710ddfbe0..fc451fb3c9a 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,69 @@ --- -Checks: '*,-abseil-*,-altera-*,-android-*,-boost-*,-cert-*,-cppcoreguidelines-*,-darwin-*,-fuchsia-*,-google-*,-hicpp-*,-linuxkernel-*,-llvm-*,-llvmlibc-*,-mpi-*,-objc-*,-openmp-*,-zircon-*,google-explicit-constructor,-readability-braces-around-statements,-readability-magic-numbers,-bugprone-macro-parentheses,-readability-isolate-declaration,-readability-function-size,-modernize-use-trailing-return-type,-readability-implicit-bool-conversion,-readability-uppercase-literal-suffix,-modernize-use-auto,-modernize-use-default-member-init,-readability-redundant-member-init,-modernize-avoid-c-arrays,-modernize-use-equals-default,-readability-container-size-empty,-bugprone-branch-clone,-bugprone-narrowing-conversions,-modernize-raw-string-literal,-readability-convert-member-functions-to-static,-modernize-loop-convert,-readability-const-return-type,-modernize-return-braced-init-list,-performance-inefficient-string-concatenation,-misc-throw-by-value-catch-by-reference,-readability-avoid-const-params-in-decls,-misc-non-private-member-variables-in-classes,-clang-analyzer-*,-bugprone-signed-char-misuse,-misc-no-recursion,-readability-use-anyofallof,-performance-no-automatic-move,-readability-function-cognitive-complexity,-readability-redundant-access-specifiers,-concurrency-mt-unsafe,-bugprone-easily-swappable-parameters,-readability-suspicious-call-argument,-readability-identifier-length,-readability-container-data-pointer,-bugprone-assignment-in-if-condition,-misc-const-correctness,-portability-std-allocator-const,-modernize-deprecated-ios-base-aliases,-bugprone-unchecked-optional-access,-modernize-replace-auto-ptr,-readability-identifier-naming,-portability-simd-intrinsics,-misc-use-anonymous-namespace,cert-err34-c' +Checks: > + *, + -abseil-*, + -altera-*, + -android-*, + -boost-*, + -cert-*, + -cppcoreguidelines-*, + -darwin-*, + -fuchsia-*, + -google-*, + -hicpp-*, + -linuxkernel-*, + -llvm-*, + -llvmlibc-*, + -mpi-*, + -objc-*, + -openmp-*, + -zircon-*, + cert-err34-c, + google-explicit-constructor, + -bugprone-assignment-in-if-condition, + -bugprone-branch-clone, + -bugprone-easily-swappable-parameters, + -bugprone-macro-parentheses, + -bugprone-narrowing-conversions, + -bugprone-signed-char-misuse, + -bugprone-unchecked-optional-access, + -clang-analyzer-*, + -concurrency-mt-unsafe, + -misc-const-correctness, + -misc-no-recursion, + -misc-non-private-member-variables-in-classes, + -misc-throw-by-value-catch-by-reference, + -misc-use-anonymous-namespace, + -modernize-avoid-c-arrays, + -modernize-deprecated-ios-base-aliases, + -modernize-loop-convert, + -modernize-raw-string-literal, + -modernize-replace-auto-ptr, + -modernize-return-braced-init-list, + -modernize-use-auto, + -modernize-use-equals-default, + -modernize-use-trailing-return-type, + -performance-inefficient-string-concatenation, + -performance-no-automatic-move, + -portability-simd-intrinsics, + -portability-std-allocator-const, + -readability-avoid-const-params-in-decls, + -readability-braces-around-statements, + -readability-const-return-type, + -readability-container-data-pointer, + -readability-container-size-empty, + -readability-convert-member-functions-to-static, + -readability-function-cognitive-complexity, + -readability-function-size, + -readability-identifier-length, + -readability-identifier-naming, + -readability-implicit-bool-conversion, + -readability-isolate-declaration, + -readability-magic-numbers, + -readability-redundant-access-specifiers, + -readability-suspicious-call-argument, + -readability-uppercase-literal-suffix, + -readability-use-anyofallof WarningsAsErrors: '*' HeaderFilterRegex: '(cli|gui|lib|oss-fuzz|test|triage)\/[a-z]+\.h' CheckOptions: diff --git a/clang-tidy.md b/clang-tidy.md index 8e6625081a6..8d1de3c83aa 100644 --- a/clang-tidy.md +++ b/clang-tidy.md @@ -37,18 +37,16 @@ These are coding guidelines we do not follow. Some of the checks might be explic `modernize-use-auto`
`readability-uppercase-literal-suffix`
`readability-else-after-return`
-`modernize-use-default-member-init`
`readability-identifier-length`
-These do not relect the style we are (currently) enforcing. +These do not reflect the style we are (currently) enforcing. `readability-function-size`
`readability-function-cognitive-complexity`
-We are not interesting in the size/complexity of a function. +We are not interested in the size/complexity of a function. `readability-magic-numbers`
-`readability-redundant-member-init`
These do not (always) increase readability. @@ -58,7 +56,7 @@ To be documented. `readability-implicit-bool-conversion`
-This does not appear not to be useful as it is reported on very common code. +This does not appear to be useful as it is reported on very common code. `bugprone-narrowing-conversions`
`performance-no-automatic-move`
diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index a77fc33690b..92b5c6a0a78 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -113,10 +113,6 @@ CmdLineParser::CmdLineParser(Settings &settings, Suppressions &suppressions, Sup : mSettings(settings) , mSuppressions(suppressions) , mSuppressionsNoFail(suppressionsNoFail) - , mShowHelp(false) - , mShowVersion(false) - , mShowErrorMessages(false) - , mExitAfterPrint(false) {} void CmdLineParser::printMessage(const std::string &message) diff --git a/cli/cmdlineparser.h b/cli/cmdlineparser.h index e84e6835270..2cd5df1cd56 100644 --- a/cli/cmdlineparser.h +++ b/cli/cmdlineparser.h @@ -146,10 +146,10 @@ class CmdLineParser { Settings &mSettings; Suppressions &mSuppressions; Suppressions &mSuppressionsNoFail; - bool mShowHelp; - bool mShowVersion; - bool mShowErrorMessages; - bool mExitAfterPrint; + bool mShowHelp{}; + bool mShowVersion{}; + bool mShowErrorMessages{}; + bool mExitAfterPrint{}; std::string mVSConfig; }; diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 30ed27a0e81..38c365d17f8 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -72,10 +72,6 @@ /*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout; -CppCheckExecutor::CppCheckExecutor() - : mSettings(nullptr), mLatestProgressOutputTime(0), mErrorOutput(nullptr), mShowAllErrors(false) -{} - CppCheckExecutor::~CppCheckExecutor() { delete mErrorOutput; diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index 1e94aa58d22..9b73eb5d7e6 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -46,7 +46,7 @@ class CppCheckExecutor : public ErrorLogger { /** * Constructor */ - CppCheckExecutor(); + CppCheckExecutor() = default; CppCheckExecutor(const CppCheckExecutor &) = delete; void operator=(const CppCheckExecutor&) = delete; @@ -154,7 +154,7 @@ class CppCheckExecutor : public ErrorLogger { /** * Pointer to current settings; set while check() is running for reportError(). */ - const Settings* mSettings; + const Settings* mSettings{}; /** * Used to filter out duplicate error messages. @@ -169,7 +169,7 @@ class CppCheckExecutor : public ErrorLogger { /** * Report progress time */ - std::time_t mLatestProgressOutputTime; + std::time_t mLatestProgressOutputTime{}; /** * Output file name for exception handler @@ -179,12 +179,12 @@ class CppCheckExecutor : public ErrorLogger { /** * Error output */ - std::ofstream *mErrorOutput; + std::ofstream* mErrorOutput{}; /** * Has --errorlist been given? */ - bool mShowAllErrors; + bool mShowAllErrors{}; }; #endif // CPPCHECKEXECUTOR_H diff --git a/cli/threadexecutor.cpp b/cli/threadexecutor.cpp index 8590651a29a..a6a9e671bd0 100644 --- a/cli/threadexecutor.cpp +++ b/cli/threadexecutor.cpp @@ -85,7 +85,7 @@ class ThreadData { public: ThreadData(ThreadExecutor &threadExecutor, ErrorLogger &errorLogger, const Settings &settings, const std::map &files, const std::list &fileSettings) - : mFiles(files), mFileSettings(fileSettings), mProcessedFiles(0), mProcessedSize(0), mSettings(settings), logForwarder(threadExecutor, errorLogger) + : mFiles(files), mFileSettings(fileSettings), mSettings(settings), logForwarder(threadExecutor, errorLogger) { mItNextFile = mFiles.begin(); mItNextFileSettings = mFileSettings.begin(); @@ -148,10 +148,10 @@ class ThreadData const std::list &mFileSettings; std::list::const_iterator mItNextFileSettings; - std::size_t mProcessedFiles; - std::size_t mTotalFiles; - std::size_t mProcessedSize; - std::size_t mTotalFileSize; + std::size_t mProcessedFiles{}; + std::size_t mTotalFiles{}; + std::size_t mProcessedSize{}; + std::size_t mTotalFileSize{}; std::mutex mFileSync; const Settings &mSettings; diff --git a/gui/applicationlist.cpp b/gui/applicationlist.cpp index 03079b1d7ed..dde03718fea 100644 --- a/gui/applicationlist.cpp +++ b/gui/applicationlist.cpp @@ -27,8 +27,7 @@ #include ApplicationList::ApplicationList(QObject *parent) : - QObject(parent), - mDefaultApplicationIndex(-1) + QObject(parent) { //ctor } diff --git a/gui/applicationlist.h b/gui/applicationlist.h index d7885a8bc2b..537ca51af35 100644 --- a/gui/applicationlist.h +++ b/gui/applicationlist.h @@ -133,7 +133,7 @@ class ApplicationList : public QObject { * @brief Index of the default application. * */ - int mDefaultApplicationIndex; + int mDefaultApplicationIndex = -1; }; /// @} #endif // APPLICATIONLIST_H diff --git a/gui/checkthread.cpp b/gui/checkthread.cpp index 480907a599f..b45f30c6eb0 100644 --- a/gui/checkthread.cpp +++ b/gui/checkthread.cpp @@ -84,10 +84,8 @@ static bool executeCommand(std::string exe, std::vector args, std:: CheckThread::CheckThread(ThreadResult &result) : - mState(Ready), mResult(result), - mCppcheck(result, true, executeCommand), - mAnalyseWholeProgram(false) + mCppcheck(result, true, executeCommand) { //ctor } diff --git a/gui/checkthread.h b/gui/checkthread.h index 519d74923e0..9a1fea3e628 100644 --- a/gui/checkthread.h +++ b/gui/checkthread.h @@ -120,7 +120,7 @@ class CheckThread : public QThread { /** * @brief Thread's current execution state. */ - State mState; + State mState = Ready; ThreadResult &mResult; /** @@ -136,7 +136,7 @@ class CheckThread : public QThread { bool isSuppressed(const Suppressions::ErrorMessage &errorMessage) const; QStringList mFiles; - bool mAnalyseWholeProgram; + bool mAnalyseWholeProgram{}; QStringList mAddonsAndTools; QStringList mClangIncludePaths; QList mSuppressions; diff --git a/gui/codeeditorstyle.cpp b/gui/codeeditorstyle.cpp index 85900d033df..fc981ad40ba 100644 --- a/gui/codeeditorstyle.cpp +++ b/gui/codeeditorstyle.cpp @@ -42,7 +42,6 @@ CodeEditorStyle::CodeEditorStyle( // cppcheck-suppress naming-varname - TODO: fix this QColor SymbFGColor, QColor SymbBGColor, const QFont::Weight& SymbWeight) : - mSystemTheme(false), widgetFGColor(std::move(CtrlFGColor)), widgetBGColor(std::move(CtrlBGColor)), highlightBGColor(std::move(HiLiBGColor)), diff --git a/gui/codeeditorstyle.h b/gui/codeeditorstyle.h index aee3d028cfe..392602b9a07 100644 --- a/gui/codeeditorstyle.h +++ b/gui/codeeditorstyle.h @@ -81,7 +81,7 @@ class CodeEditorStyle { static void saveSettings(QSettings *settings, const CodeEditorStyle& theStyle); public: - bool mSystemTheme; + bool mSystemTheme{}; QColor widgetFGColor; QColor widgetBGColor; QColor highlightBGColor; diff --git a/gui/codeeditstylecontrols.cpp b/gui/codeeditstylecontrols.cpp index 186d76c1e42..8cd4465c568 100644 --- a/gui/codeeditstylecontrols.cpp +++ b/gui/codeeditstylecontrols.cpp @@ -69,8 +69,7 @@ const QColor& SelectColorButton::getColor() } SelectFontWeightCombo::SelectFontWeightCombo(QWidget* parent) : - QComboBox(parent), - mWeight(QFont::Normal) + QComboBox(parent) { addItem(QObject::tr("Thin"), QVariant(static_cast(QFont::Thin))); diff --git a/gui/codeeditstylecontrols.h b/gui/codeeditstylecontrols.h index b624d0e8d41..7e87c7b5fc0 100644 --- a/gui/codeeditstylecontrols.h +++ b/gui/codeeditstylecontrols.h @@ -71,7 +71,7 @@ public slots: void changeWeight(int index); private: - QFont::Weight mWeight; + QFont::Weight mWeight = QFont::Normal; }; #endif //CODEEDITORSTYLECONTROLS_H diff --git a/gui/cppchecklibrarydata.h b/gui/cppchecklibrarydata.h index e0360534e34..252d66920ba 100644 --- a/gui/cppchecklibrarydata.h +++ b/gui/cppchecklibrarydata.h @@ -33,8 +33,6 @@ class CppcheckLibraryData { CppcheckLibraryData(); struct Container { - Container() : access_arrayLike(false), size_templateParameter(-1) {} - QString id; QString inherits; QString startPattern; @@ -42,8 +40,8 @@ class CppcheckLibraryData { QString opLessAllowed; QString itEndPattern; - bool access_arrayLike; - int size_templateParameter; + bool access_arrayLike{}; + int size_templateParameter = -1; struct { QString templateParameter; @@ -72,21 +70,17 @@ class CppcheckLibraryData { }; struct Function { - Function() : noreturn(Unknown), gccPure(false), gccConst(false), - leakignore(false), useretval(false) {} - QString comments; QString name; - enum TrueFalseUnknown { False, True, Unknown } noreturn; - bool gccPure; - bool gccConst; - bool leakignore; - bool useretval; + enum TrueFalseUnknown { False, True, Unknown } noreturn = Unknown; + bool gccPure{}; + bool gccConst{}; + bool leakignore{}; + bool useretval{}; struct ReturnValue { - ReturnValue() : container(-1) {} QString type; QString value; - int container; + int container = -1; bool empty() const { return type.isNull() && value.isNull() && container < 0; } @@ -96,19 +90,16 @@ class CppcheckLibraryData { QString secure; } formatstr; struct Arg { - Arg() : nr(0), notbool(false), notnull(false), notuninit(false), - formatstr(false), strz(false) {} - QString name; - unsigned int nr; + unsigned int nr{}; static const unsigned int ANY; static const unsigned int VARIADIC; QString defaultValue; - bool notbool; - bool notnull; - bool notuninit; - bool formatstr; - bool strz; + bool notbool{}; + bool notnull{}; + bool notuninit{}; + bool formatstr{}; + bool strz{}; QString valid; struct MinSize { QString type; @@ -117,8 +108,7 @@ class CppcheckLibraryData { }; QList minsizes; struct Iterator { - Iterator() : container(-1) {} - int container; + int container = -1; QString type; } iterator; }; @@ -147,26 +137,15 @@ class CppcheckLibraryData { struct MemoryResource { QString type; // "memory" or "resource" struct Alloc { - Alloc() : - isRealloc(false), - init(false), - arg(-1), // -1: Has no optional "arg" attribute - reallocArg(-1) // -1: Has no optional "realloc-arg" attribute - {} - - bool isRealloc; - bool init; - int arg; - int reallocArg; + bool isRealloc{}; + bool init{}; + int arg = -1; // -1: Has no optional "realloc-arg" attribute + int reallocArg = -1; // -1: Has no optional "arg" attribute QString bufferSize; QString name; }; struct Dealloc { - Dealloc() : - arg(-1) // -1: Has no optional "arg" attribute - {} - - int arg; + int arg = -1; // -1: Has no optional "arg" attribute QString name; }; @@ -193,11 +172,7 @@ class CppcheckLibraryData { struct Reflection { struct Call { - Call() : - arg {-1} // -1: Mandatory "arg" attribute not available - {} - - int arg; + int arg = -1; // -1: Mandatory "arg" attribute not available QString name; }; @@ -206,12 +181,8 @@ class CppcheckLibraryData { struct Markup { struct CodeBlocks { - CodeBlocks() : - offset {-1} - {} - QStringList blocks; - int offset; + int offset = -1; QString start; QString end; }; @@ -223,8 +194,8 @@ class CppcheckLibraryData { }; QString ext; - bool afterCode; - bool reportErrors; + bool afterCode{}; + bool reportErrors{}; QStringList keywords; QStringList importer; QList codeBlocks; @@ -232,12 +203,8 @@ class CppcheckLibraryData { }; struct SmartPointer { - SmartPointer() : - unique {false} - {} - QString name; - bool unique; + bool unique{}; }; struct Entrypoint { diff --git a/gui/helpdialog.h b/gui/helpdialog.h index a5dc0b43039..075005fd8f2 100644 --- a/gui/helpdialog.h +++ b/gui/helpdialog.h @@ -34,7 +34,7 @@ namespace Ui { class HelpBrowser : public QTextBrowser { public: - explicit HelpBrowser(QWidget* parent = nullptr) : QTextBrowser(parent), mHelpEngine(nullptr) {} + explicit HelpBrowser(QWidget* parent = nullptr) : QTextBrowser(parent) {} HelpBrowser(const HelpBrowser&) = delete; HelpBrowser(HelpBrowser&&) = delete; HelpBrowser& operator=(const HelpBrowser&) = delete; @@ -42,7 +42,7 @@ class HelpBrowser : public QTextBrowser { void setHelpEngine(QHelpEngine *helpEngine); QVariant loadResource(int type, const QUrl& name) override; private: - QHelpEngine* mHelpEngine; + QHelpEngine* mHelpEngine{}; }; class HelpDialog : public QDialog { diff --git a/gui/librarydialog.cpp b/gui/librarydialog.cpp index e077a6b7677..47545679922 100644 --- a/gui/librarydialog.cpp +++ b/gui/librarydialog.cpp @@ -61,8 +61,7 @@ class FunctionListItem : public QListWidgetItem { LibraryDialog::LibraryDialog(QWidget *parent) : QDialog(parent), - mUi(new Ui::LibraryDialog), - mIgnoreChanges(false) + mUi(new Ui::LibraryDialog) { mUi->setupUi(this); mUi->buttonSave->setEnabled(false); diff --git a/gui/librarydialog.h b/gui/librarydialog.h index d8dd3c247c1..ac27d42756c 100644 --- a/gui/librarydialog.h +++ b/gui/librarydialog.h @@ -56,7 +56,7 @@ private slots: Ui::LibraryDialog *mUi; CppcheckLibraryData mData; QString mFileName; - bool mIgnoreChanges; + bool mIgnoreChanges{}; static QString getArgText(const CppcheckLibraryData::Function::Arg &arg); CppcheckLibraryData::Function *currentFunction(); diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp index 814ec585d8a..2840c48330d 100644 --- a/gui/mainwindow.cpp +++ b/gui/mainwindow.cpp @@ -109,14 +109,10 @@ MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : mApplications(new ApplicationList(this)), mTranslation(th), mUI(new Ui::MainWindow), - mScratchPad(nullptr), - mProjectFile(nullptr), mPlatformActions(new QActionGroup(this)), mCStandardActions(new QActionGroup(this)), mCppStandardActions(new QActionGroup(this)), - mSelectLanguageActions(new QActionGroup(this)), - mExiting(false), - mIsLogfileLoaded(false) + mSelectLanguageActions(new QActionGroup(this)) { { Settings tempSettings; diff --git a/gui/mainwindow.h b/gui/mainwindow.h index ab7d45d6428..78782b22bdd 100644 --- a/gui/mainwindow.h +++ b/gui/mainwindow.h @@ -437,10 +437,10 @@ private slots: QString mCurrentDirectory; /** @brief Scratchpad. */ - ScratchPad* mScratchPad; + ScratchPad* mScratchPad{}; /** @brief Project (file). */ - ProjectFile *mProjectFile; + ProjectFile* mProjectFile{}; /** @brief Filter field in the Filter toolbar. */ QLineEdit* mLineEditFilter; @@ -462,10 +462,10 @@ private slots: * If this is true then the cppcheck is waiting for check threads to exit * so that the application can be closed. */ - bool mExiting; + bool mExiting{}; /** @brief Set to true in case of loading log file. */ - bool mIsLogfileLoaded; + bool mIsLogfileLoaded{}; /** * @brief Project MRU menu actions. diff --git a/gui/report.cpp b/gui/report.cpp index 9a4c391fd0b..e7b7e06edf9 100644 --- a/gui/report.cpp +++ b/gui/report.cpp @@ -23,7 +23,6 @@ #include Report::Report(QString filename) : - QObject(), mFilename(std::move(filename)) {} diff --git a/gui/resultstree.cpp b/gui/resultstree.cpp index 241322c18ae..61f995e6bf4 100644 --- a/gui/resultstree.cpp +++ b/gui/resultstree.cpp @@ -81,19 +81,7 @@ static const int COLUMN_SINCE_DATE = 6; static const int COLUMN_TAGS = 7; ResultsTree::ResultsTree(QWidget * parent) : - QTreeView(parent), - mSettings(nullptr), - mApplications(nullptr), - mContextItem(nullptr), - mShowFullPath(false), - mSaveFullPath(false), - mSaveAllErrors(true), - mShowErrorId(false), - mVisibleErrors(false), - mSelectionModel(nullptr), - mThread(nullptr), - mShowCppcheck(true), - mShowClang(true) + QTreeView(parent) { setModel(&mModel); translate(); // Adds columns to grid diff --git a/gui/resultstree.h b/gui/resultstree.h index 1e67dca9710..5828c0e383b 100644 --- a/gui/resultstree.h +++ b/gui/resultstree.h @@ -453,7 +453,7 @@ protected slots: * @brief Program settings * */ - QSettings *mSettings; + QSettings* mSettings{}; /** * @brief A string used to filter the results for display. @@ -465,37 +465,37 @@ protected slots: * @brief List of applications to open errors with * */ - ApplicationList *mApplications; + ApplicationList* mApplications{}; /** * @brief Right clicked item (used by context menu slots) * */ - QStandardItem *mContextItem; + QStandardItem* mContextItem{}; /** * @brief Should full path of files be shown (true) or relative (false) * */ - bool mShowFullPath; + bool mShowFullPath{}; /** * @brief Should full path of files be saved * */ - bool mSaveFullPath; + bool mSaveFullPath{}; /** * @brief Save all errors (true) or only visible (false) * */ - bool mSaveAllErrors; + bool mSaveAllErrors = true; /** * @brief true if optional column "Id" is shown * */ - bool mShowErrorId; + bool mShowErrorId{}; /** * @brief Path we are currently checking @@ -507,7 +507,7 @@ protected slots: * @brief Are there any visible errors * */ - bool mVisibleErrors; + bool mVisibleErrors{}; private: /** tag selected items */ @@ -518,11 +518,11 @@ protected slots: QStringList mHiddenMessageId; - QItemSelectionModel *mSelectionModel; - ThreadHandler *mThread; + QItemSelectionModel* mSelectionModel{}; + ThreadHandler *mThread{}; - bool mShowCppcheck; - bool mShowClang; + bool mShowCppcheck = true; + bool mShowClang = true; }; /// @} #endif // RESULTSTREE_H diff --git a/gui/resultsview.cpp b/gui/resultsview.cpp index 2ee37ae9493..6c57e8c159a 100644 --- a/gui/resultsview.cpp +++ b/gui/resultsview.cpp @@ -67,7 +67,6 @@ ResultsView::ResultsView(QWidget * parent) : QWidget(parent), - mShowNoErrorsMessage(true), mUI(new Ui::ResultsView), mStatistics(new CheckStatistics(this)) { diff --git a/gui/resultsview.h b/gui/resultsview.h index f07c588732a..b44adfd0782 100644 --- a/gui/resultsview.h +++ b/gui/resultsview.h @@ -344,7 +344,7 @@ public slots: /** * @brief Should we show a "No errors found dialog" every time no errors were found? */ - bool mShowNoErrorsMessage; + bool mShowNoErrorsMessage = true; Ui::ResultsView *mUI; diff --git a/gui/statsdialog.cpp b/gui/statsdialog.cpp index 7b8db7ca66d..4f5ce9a85bf 100644 --- a/gui/statsdialog.cpp +++ b/gui/statsdialog.cpp @@ -71,8 +71,7 @@ static const QString CPPCHECK("cppcheck"); StatsDialog::StatsDialog(QWidget *parent) : QDialog(parent), - mUI(new Ui::StatsDialog), - mStatistics(nullptr) + mUI(new Ui::StatsDialog) { mUI->setupUi(this); diff --git a/gui/statsdialog.h b/gui/statsdialog.h index 1b7f41d0e06..62c93fcab58 100644 --- a/gui/statsdialog.h +++ b/gui/statsdialog.h @@ -73,7 +73,7 @@ private slots: void pdfExport(); private: Ui::StatsDialog *mUI; - const CheckStatistics *mStatistics; + const CheckStatistics* mStatistics{}; }; /// @} diff --git a/gui/test/projectfile/testprojectfile.cpp b/gui/test/projectfile/testprojectfile.cpp index 95cbe9404bd..cbd98dc86ca 100644 --- a/gui/test/projectfile/testprojectfile.cpp +++ b/gui/test/projectfile/testprojectfile.cpp @@ -39,9 +39,8 @@ const char Settings::SafeChecks::XmlClasses[] = "class-public"; const char Settings::SafeChecks::XmlExternalFunctions[] = "external-functions"; const char Settings::SafeChecks::XmlInternalFunctions[] = "internal-functions"; const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables"; -Settings::Settings() : maxCtuDepth(10), maxTemplateRecursion(100) {} +Settings::Settings() : maxCtuDepth(10) {} cppcheck::Platform::Platform() {} -Library::Library() {} ImportProject::ImportProject() {} bool ImportProject::sourceFileExists(const std::string & /*file*/) { return true; diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index fddb3348022..43faf2aea27 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -36,11 +36,7 @@ #include ThreadHandler::ThreadHandler(QObject *parent) : - QObject(parent), - mScanDuration(0), - mRunningThreadCount(0), - mAnalyseWholeProgram(false) - + QObject(parent) { setThreadCount(1); } diff --git a/gui/threadhandler.h b/gui/threadhandler.h index 93d30893d2a..cdf2a6f0261 100644 --- a/gui/threadhandler.h +++ b/gui/threadhandler.h @@ -230,7 +230,7 @@ protected slots: * @brief The previous scan duration in milliseconds. * */ - int mScanDuration; + int mScanDuration{}; /** * @brief Function to delete all threads @@ -254,9 +254,9 @@ protected slots: * @brief The amount of threads currently running * */ - int mRunningThreadCount; + int mRunningThreadCount{}; - bool mAnalyseWholeProgram; + bool mAnalyseWholeProgram{}; QStringList mAddonsAndTools; QList mSuppressions; diff --git a/gui/threadresult.cpp b/gui/threadresult.cpp index f32da9b1c74..5e1aed89b78 100644 --- a/gui/threadresult.cpp +++ b/gui/threadresult.cpp @@ -28,11 +28,6 @@ #include #include -ThreadResult::ThreadResult() : QObject(), ErrorLogger(), mMaxProgress(0), mProgress(0), mFilesChecked(0), mTotalFiles(0) -{ - //ctor -} - ThreadResult::~ThreadResult() { //dtor diff --git a/gui/threadresult.h b/gui/threadresult.h index 9a3c5895375..f08bb945230 100644 --- a/gui/threadresult.h +++ b/gui/threadresult.h @@ -45,7 +45,7 @@ class ErrorItem; class ThreadResult : public QObject, public ErrorLogger { Q_OBJECT public: - ThreadResult(); + ThreadResult() = default; ~ThreadResult() override; /** @@ -142,25 +142,25 @@ public slots: * @brief Max progress * */ - quint64 mMaxProgress; + quint64 mMaxProgress{}; /** * @brief Current progress * */ - quint64 mProgress; + quint64 mProgress{}; /** * @brief Current number of files checked * */ - unsigned long mFilesChecked; + unsigned long mFilesChecked{}; /** * @brief Total number of files * */ - unsigned long mTotalFiles; + unsigned long mTotalFiles{}; }; /// @} #endif // THREADRESULT_H diff --git a/gui/translationhandler.cpp b/gui/translationhandler.cpp index 0a0aefd0763..6b14b6241fb 100644 --- a/gui/translationhandler.cpp +++ b/gui/translationhandler.cpp @@ -42,8 +42,7 @@ static UNUSED void unused() TranslationHandler::TranslationHandler(QObject *parent) : QObject(parent), - mCurrentLanguage("en"), - mTranslator(nullptr) + mCurrentLanguage("en") { // Add our available languages // Keep this list sorted diff --git a/gui/translationhandler.h b/gui/translationhandler.h index 66effc5ed40..e9ff8722058 100644 --- a/gui/translationhandler.h +++ b/gui/translationhandler.h @@ -135,7 +135,7 @@ class TranslationHandler : QObject { * @brief Translator class instance. * */ - QTranslator *mTranslator; + QTranslator* mTranslator{}; }; /// @} diff --git a/lib/analyzer.h b/lib/analyzer.h index 51da0281f69..3c65e0e68de 100644 --- a/lib/analyzer.h +++ b/lib/analyzer.h @@ -32,7 +32,7 @@ class ValuePtr; struct Analyzer { struct Action { - Action() : mFlag(0) {} + Action() = default; template ), @@ -125,7 +125,7 @@ struct Analyzer { } private: - unsigned int mFlag; + unsigned int mFlag{}; }; enum class Terminate { None, Bail, Escape, Modified, Inconclusive, Conditional }; diff --git a/lib/check.cpp b/lib/check.cpp index f01d938a699..bc67e683dfc 100644 --- a/lib/check.cpp +++ b/lib/check.cpp @@ -35,7 +35,7 @@ //--------------------------------------------------------------------------- Check::Check(const std::string &aname) - : mTokenizer(nullptr), mSettings(nullptr), mErrorLogger(nullptr), mName(aname) + : mName(aname) { { const auto it = std::find_if(instances().begin(), instances().end(), [&](const Check *i) { diff --git a/lib/check.h b/lib/check.h index 2f29d9b1db5..39e34781505 100644 --- a/lib/check.h +++ b/lib/check.h @@ -130,9 +130,9 @@ class CPPCHECKLIB Check { static std::string getMessageId(const ValueFlow::Value &value, const char id[]); protected: - const Tokenizer * const mTokenizer; - const Settings * const mSettings; - ErrorLogger * const mErrorLogger; + const Tokenizer* const mTokenizer{}; + const Settings* const mSettings{}; + ErrorLogger* const mErrorLogger{}; /** report an error */ void reportError(const Token *tok, const Severity::SeverityType severity, const std::string &id, const std::string &msg) { diff --git a/lib/checkclass.h b/lib/checkclass.h index bd1ed8db054..ffb94d3a247 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -53,7 +53,7 @@ namespace tinyxml2 { class CPPCHECKLIB CheckClass : public Check { public: /** @brief This constructor is used when registering the CheckClass */ - CheckClass() : Check(myName()), mSymbolDatabase(nullptr) {} + CheckClass() : Check(myName()) {} /** @brief This constructor is used when running checks. */ CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger); @@ -195,7 +195,7 @@ class CPPCHECKLIB CheckClass : public Check { static const std::set stl_containers_not_const; private: - const SymbolDatabase *mSymbolDatabase; + const SymbolDatabase* mSymbolDatabase{}; // Reporting errors.. void noConstructorError(const Token *tok, const std::string &classname, bool isStruct); @@ -330,16 +330,16 @@ class CPPCHECKLIB CheckClass : public Check { // constructors helper function /** @brief Information about a member variable. Used when checking for uninitialized variables */ struct Usage { - explicit Usage(const Variable *var) : var(var), assign(false), init(false) {} + explicit Usage(const Variable *var) : var(var) {} /** Variable that this usage is for */ const Variable *var; /** @brief has this variable been assigned? */ - bool assign; + bool assign{}; /** @brief has this variable been initialized? */ - bool init; + bool init{}; }; static bool isBaseClassMutableMemberFunc(const Token *tok, const Scope *scope); diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 2a0fdc4d483..dc14c0832a7 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -106,14 +106,14 @@ static OpenMode getMode(const std::string& str) struct Filepointer { OpenMode mode; - nonneg int mode_indent; - enum class Operation {NONE, UNIMPORTANT, READ, WRITE, POSITIONING, OPEN, CLOSE, UNKNOWN_OP} lastOperation; - nonneg int op_indent; + nonneg int mode_indent{}; + enum class Operation {NONE, UNIMPORTANT, READ, WRITE, POSITIONING, OPEN, CLOSE, UNKNOWN_OP} lastOperation = Operation::NONE; + nonneg int op_indent{}; enum class AppendMode { UNKNOWN_AM, APPEND, APPEND_EX }; - AppendMode append_mode; + AppendMode append_mode = AppendMode::UNKNOWN_AM; std::string filename; explicit Filepointer(OpenMode mode_ = OpenMode::UNKNOWN_OM) - : mode(mode_), mode_indent(0), lastOperation(Operation::NONE), op_indent(0), append_mode(AppendMode::UNKNOWN_AM) {} + : mode(mode_) {} }; namespace { @@ -1331,14 +1331,7 @@ void CheckIO::checkFormatString(const Token * const tok, /// @todo add non-string literals, and generic expressions CheckIO::ArgumentInfo::ArgumentInfo(const Token * arg, const Settings *settings, bool _isCPP) - : variableInfo(nullptr) - , typeToken(nullptr) - , functionInfo(nullptr) - , tempToken(nullptr) - , element(false) - , _template(false) - , address(false) - , isCPP(_isCPP) + : isCPP(_isCPP) { if (!arg) return; diff --git a/lib/checkio.h b/lib/checkio.h index 9e9b07a2581..29c3344d5c1 100644 --- a/lib/checkio.h +++ b/lib/checkio.h @@ -86,14 +86,14 @@ class CPPCHECKLIB CheckIO : public Check { bool isStdContainer(const Token *tok); bool isLibraryType(const Settings *settings) const; - const Variable *variableInfo; - const Token *typeToken; - const Function *functionInfo; - Token *tempToken; - bool element; - bool _template; - bool address; - bool isCPP; + const Variable* variableInfo{}; + const Token* typeToken{}; + const Function* functionInfo{}; + Token* tempToken{}; + bool element{}; + bool _template{}; + bool address{}; + bool isCPP{}; }; void checkFormatString(const Token * const tok, diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index 8c4ccbccba0..fbb645e07ca 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -48,9 +48,9 @@ namespace tinyxml2 { struct VariableValue { - explicit VariableValue(MathLib::bigint val = 0) : value(val), notEqual(false) {} + explicit VariableValue(MathLib::bigint val = 0) : value(val) {} MathLib::bigint value; - bool notEqual; + bool notEqual{}; }; /// @addtogroup Checks diff --git a/lib/checkunusedfunctions.h b/lib/checkunusedfunctions.h index d635b817d3e..af008a17bd6 100644 --- a/lib/checkunusedfunctions.h +++ b/lib/checkunusedfunctions.h @@ -101,14 +101,11 @@ class CPPCHECKLIB CheckUnusedFunctions : public Check { return "Check for functions that are never called\n"; } - class CPPCHECKLIB FunctionUsage { - public: - FunctionUsage() : lineNumber(0), usedSameFile(false), usedOtherFile(false) {} - + struct CPPCHECKLIB FunctionUsage { std::string filename; - unsigned int lineNumber; - bool usedSameFile; - bool usedOtherFile; + unsigned int lineNumber{}; + bool usedSameFile{}; + bool usedOtherFile{}; }; std::unordered_map mFunctions; diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 9f0ea5dc35c..68366756fe8 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -635,7 +635,7 @@ static bool isPartOfClassStructUnion(const Token* tok) if (tok->str() == "}" || tok->str() == ")") tok = tok->link(); else if (tok->str() == "(") - return (false); + return false; else if (tok->str() == "{") { return (tok->strAt(-1) == "struct" || tok->strAt(-2) == "struct" || tok->strAt(-1) == "class" || tok->strAt(-2) == "class" || tok->strAt(-1) == "union" || tok->strAt(-2) == "union"); } diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index 328d6527507..7b91d6c4b07 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -205,10 +205,10 @@ static std::vector splitString(const std::string &line) namespace clangimport { struct Data { struct Decl { - explicit Decl(Scope *scope) : def(nullptr), enumerator(nullptr), function(nullptr), scope(scope), var(nullptr) {} - Decl(Token *def, Variable *var) : def(def), enumerator(nullptr), function(nullptr), scope(nullptr), var(var) {} - Decl(Token *def, Function *function) : def(def), enumerator(nullptr), function(function), scope(nullptr), var(nullptr) {} - Decl(Token *def, Enumerator *enumerator) : def(def), enumerator(enumerator), function(nullptr), scope(nullptr), var(nullptr) {} + explicit Decl(Scope *scope) : scope(scope) {} + Decl(Token *def, Variable *var) : def(def), var(var) {} + Decl(Token *def, Function *function) : def(def), function(function) {} + Decl(Token *def, Enumerator *enumerator) : def(def), enumerator(enumerator) {} void ref(Token *tok) const { if (enumerator) tok->enumerator(enumerator); @@ -219,11 +219,11 @@ namespace clangimport { tok->varId(var->declarationId()); } } - Token *def; - Enumerator *enumerator; - Function *function; - Scope *scope; - Variable *var; + Token* def{}; + Enumerator* enumerator{}; + Function* function{}; + Scope* scope{}; + Variable* var{}; }; const Settings *mSettings = nullptr; diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 9b7a72cad62..074e5ce71ca 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -391,10 +391,7 @@ CppCheck::CppCheck(ErrorLogger &errorLogger, bool useGlobalSuppressions, std::function,std::string,std::string&)> executeCommand) : mErrorLogger(errorLogger) - , mExitCode(0) , mUseGlobalSuppressions(useGlobalSuppressions) - , mTooManyConfigs(false) - , mSimplify(true) , mExecuteCommand(std::move(executeCommand)) {} diff --git a/lib/cppcheck.h b/lib/cppcheck.h index d9b63f02fd7..925111ae75b 100644 --- a/lib/cppcheck.h +++ b/lib/cppcheck.h @@ -217,15 +217,15 @@ class CPPCHECKLIB CppCheck : ErrorLogger { /** @brief Current preprocessor configuration */ std::string mCurrentConfig; - unsigned int mExitCode; + unsigned int mExitCode{}; bool mUseGlobalSuppressions; /** Are there too many configs? */ - bool mTooManyConfigs; + bool mTooManyConfigs{}; /** Simplify code? true by default */ - bool mSimplify; + bool mSimplify = true; /** File info used for whole program analysis */ std::list mFileInfo; diff --git a/lib/ctu.cpp b/lib/ctu.cpp index ab3a7155d31..d62f91bfb86 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -158,7 +158,6 @@ std::string CTU::toString(const std::list &unsafeUsa CTU::FileInfo::CallBase::CallBase(const Tokenizer *tokenizer, const Token *callToken) : callId(getFunctionId(tokenizer, callToken->function())) - , callArgNr(0) , callFunctionName(callToken->next()->astOperand1()->expressionString()) , location(CTU::FileInfo::Location(tokenizer, callToken)) {} @@ -166,7 +165,6 @@ CTU::FileInfo::CallBase::CallBase(const Tokenizer *tokenizer, const Token *callT CTU::FileInfo::NestedCall::NestedCall(const Tokenizer *tokenizer, const Function *myFunction, const Token *callToken) : CallBase(tokenizer, callToken) , myId(getFunctionId(tokenizer, myFunction)) - , myArgNr(0) {} static std::string readAttrString(const tinyxml2::XMLElement *e, const char *attr, bool *error) diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index 494dbd13bba..fea0526eb5d 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -51,15 +51,15 @@ struct ForwardTraversal { enum class Progress { Continue, Break, Skip }; enum class Terminate { None, Bail, Inconclusive }; ForwardTraversal(const ValuePtr& analyzer, const Settings& settings) - : analyzer(analyzer), settings(settings), actions(Analyzer::Action::None), analyzeOnly(false), analyzeTerminate(false) + : analyzer(analyzer), settings(settings) {} ValuePtr analyzer; const Settings& settings; Analyzer::Action actions; - bool analyzeOnly; - bool analyzeTerminate; + bool analyzeOnly{}; + bool analyzeTerminate{}; Analyzer::Terminate terminate = Analyzer::Terminate::None; - std::vector loopEnds = {}; + std::vector loopEnds; Progress Break(Analyzer::Terminate t = Analyzer::Terminate::None) { if ((!analyzeOnly || analyzeTerminate) && t != Analyzer::Terminate::None) diff --git a/lib/fwdanalysis.h b/lib/fwdanalysis.h index 847d1464e0c..0e83c22518b 100644 --- a/lib/fwdanalysis.h +++ b/lib/fwdanalysis.h @@ -37,7 +37,7 @@ class Library; */ class FwdAnalysis { public: - FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library), mWhat(What::Reassign), mValueFlowKnown(true) {} + FwdAnalysis(bool cpp, const Library &library) : mCpp(cpp), mLibrary(library) {} bool hasOperand(const Token *tok, const Token *lhs) const; @@ -60,8 +60,8 @@ class FwdAnalysis { bool unusedValue(const Token *expr, const Token *startToken, const Token *endToken); struct KnownAndToken { - bool known; - const Token *token; + bool known{}; + const Token* token{}; }; /** Is there some possible alias for given expression */ @@ -74,9 +74,9 @@ class FwdAnalysis { /** Result of forward analysis */ struct Result { enum class Type { NONE, READ, WRITE, BREAK, RETURN, BAILOUT } type; - explicit Result(Type type) : type(type), token(nullptr) {} + explicit Result(Type type) : type(type) {} Result(Type type, const Token *token) : type(type), token(token) {} - const Token *token; + const Token* token{}; }; struct Result check(const Token *expr, const Token *startToken, const Token *endToken); @@ -87,9 +87,9 @@ class FwdAnalysis { const bool mCpp; const Library &mLibrary; - enum class What { Reassign, UnusedValue, ValueFlow } mWhat; + enum class What { Reassign, UnusedValue, ValueFlow } mWhat = What::Reassign; std::vector mValueFlow; - bool mValueFlowKnown; + bool mValueFlowKnown = true; }; #endif // fwdanalysisH diff --git a/lib/importproject.cpp b/lib/importproject.cpp index c59bf288aa8..76403ff40db 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -502,7 +502,7 @@ bool ImportProject::importSln(std::istream &istr, const std::string &path, const namespace { struct ProjectConfiguration { - explicit ProjectConfiguration(const tinyxml2::XMLElement *cfg) : platform(Unknown) { + explicit ProjectConfiguration(const tinyxml2::XMLElement *cfg) { const char *a = cfg->Attribute("Include"); if (a) name = a; @@ -524,7 +524,7 @@ namespace { } std::string name; std::string configuration; - enum { Win32, x64, Unknown } platform; + enum { Win32, x64, Unknown } platform = Unknown; std::string platformStr; }; diff --git a/lib/importproject.h b/lib/importproject.h index 704722edc19..1d7bb9ba72c 100644 --- a/lib/importproject.h +++ b/lib/importproject.h @@ -63,7 +63,6 @@ class CPPCHECKLIB ImportProject { /** File settings. Multiple configurations for a file is allowed. */ struct CPPCHECKLIB FileSettings { - FileSettings() : platformType(cppcheck::Platform::Type::Unspecified), msc(false), useMfc(false) {} std::string cfg; std::string filename; std::string defines; @@ -74,9 +73,9 @@ class CPPCHECKLIB ImportProject { std::list includePaths; std::list systemIncludePaths; std::string standard; - cppcheck::Platform::Type platformType; - bool msc; - bool useMfc; + cppcheck::Platform::Type platformType = cppcheck::Platform::Type::Unspecified; + bool msc{}; + bool useMfc{}; void parseCommand(const std::string& command); void setDefines(std::string defs); diff --git a/lib/library.cpp b/lib/library.cpp index 3744f455235..4142dcd8ae1 100644 --- a/lib/library.cpp +++ b/lib/library.cpp @@ -64,9 +64,6 @@ static void gettokenlistfromvalid(const std::string& valid, TokenList& tokenList } } -Library::Library() : mAllocId(0) -{} - Library::Error Library::load(const char exename[], const char path[]) { if (std::strchr(path,',') != nullptr) { diff --git a/lib/library.h b/lib/library.h index 2e38a7332b0..300382d9fc7 100644 --- a/lib/library.h +++ b/lib/library.h @@ -58,7 +58,7 @@ class CPPCHECKLIB Library { friend class TestProcessExecutor; // For testing only public: - Library(); + Library() = default; enum class ErrorCode { OK, FILE_NOT_FOUND, BAD_XML, UNKNOWN_ELEMENT, MISSING_ATTRIBUTE, BAD_ATTRIBUTE_VALUE, UNSUPPORTED_FORMAT, DUPLICATE_PLATFORM_TYPE, PLATFORM_TYPE_REDEFINED }; @@ -210,18 +210,7 @@ class CPPCHECKLIB Library { class Container { public: - Container() - : type_templateArgNo(-1), - size_templateArgNo(-1), - arrayLike_indexOp(false), - stdStringLike(false), - stdAssociativeLike(false), - opLessAllowed(true), - hasInitializerListConstructor(false), - unstableErase(false), - unstableInsert(false), - view(false) - {} + Container() = default; enum class Action { RESIZE, @@ -259,17 +248,17 @@ class CPPCHECKLIB Library { }; std::string startPattern, startPattern2, endPattern, itEndPattern; std::map functions; - int type_templateArgNo; + int type_templateArgNo = -1; std::vector rangeItemRecordType; - int size_templateArgNo; - bool arrayLike_indexOp; - bool stdStringLike; - bool stdAssociativeLike; - bool opLessAllowed; - bool hasInitializerListConstructor; - bool unstableErase; - bool unstableInsert; - bool view; + int size_templateArgNo = -1; + bool arrayLike_indexOp{}; + bool stdStringLike{}; + bool stdAssociativeLike{}; + bool opLessAllowed = true; + bool hasInitializerListConstructor{}; + bool unstableErase{}; + bool unstableInsert{}; + bool view{}; Action getAction(const std::string& function) const { const std::map::const_iterator i = functions.find(function); @@ -298,47 +287,31 @@ class CPPCHECKLIB Library { const Container* detectIterator(const Token* typeStart) const; const Container* detectContainerOrIterator(const Token* typeStart, bool* isIterator = nullptr, bool withoutStd = false) const; - class ArgumentChecks { - public: - ArgumentChecks() : - notbool(false), - notnull(false), - notuninit(-1), - formatstr(false), - strz(false), - optional(false), - variadic(false), - iteratorInfo(), - direction(Direction::DIR_UNKNOWN) {} - - bool notbool; - bool notnull; - int notuninit; - bool formatstr; - bool strz; - bool optional; - bool variadic; + struct ArgumentChecks { + bool notbool{}; + bool notnull{}; + int notuninit = -1; + bool formatstr{}; + bool strz{}; + bool optional{}; + bool variadic{}; std::string valid; - class IteratorInfo { - public: - IteratorInfo() : container(0), it(false), first(false), last(false) {} - - int container; - bool it; - bool first; - bool last; + struct IteratorInfo { + int container{}; + bool it{}; + bool first{}; + bool last{}; }; IteratorInfo iteratorInfo; - class MinSize { - public: + struct MinSize { enum class Type { NONE, STRLEN, ARGVALUE, SIZEOF, MUL, VALUE }; - MinSize(Type t, int a) : type(t), arg(a), arg2(0), value(0) {} + MinSize(Type t, int a) : type(t), arg(a) {} Type type; int arg; - int arg2; - long long value; + int arg2 = 0; + long long value = 0; std::string baseType; }; std::vector minsizes; @@ -349,36 +322,23 @@ class CPPCHECKLIB Library { DIR_INOUT, ///< Input to called function, and output to caller. Data is passed by reference or address and is potentially modified. DIR_UNKNOWN ///< direction not known / specified }; - Direction direction; + Direction direction = Direction::DIR_UNKNOWN; }; struct Function { std::map argumentChecks; // argument nr => argument data - bool use; - bool leakignore; - bool isconst; - bool ispure; - UseRetValType useretval; - bool ignore; // ignore functions/macros from a library (gtk, qt etc) - bool formatstr; - bool formatstr_scan; - bool formatstr_secure; - Container::Action containerAction; - Container::Yield containerYield; + bool use{}; + bool leakignore{}; + bool isconst{}; + bool ispure{}; + UseRetValType useretval = UseRetValType::NONE; + bool ignore{}; // ignore functions/macros from a library (gtk, qt etc) + bool formatstr{}; + bool formatstr_scan{}; + bool formatstr_secure{}; + Container::Action containerAction = Container::Action::NO_ACTION; + Container::Yield containerYield = Container::Yield::NO_YIELD; std::string returnType; - Function() - : use(false), - leakignore(false), - isconst(false), - ispure(false), - useretval(UseRetValType::NONE), - ignore(false), - formatstr(false), - formatstr_scan(false), - formatstr_secure(false), - containerAction(Container::Action::NO_ACTION), - containerYield(Container::Yield::NO_YIELD) - {} }; const Function *getFunction(const Token *ftok) const; @@ -505,13 +465,6 @@ class CPPCHECKLIB Library { } struct PlatformType { - PlatformType() - : mSigned(false) - , mUnsigned(false) - , mLong(false) - , mPointer(false) - , mPtrPtr(false) - , mConstPtr(false) {} bool operator == (const PlatformType & type) const { return (mSigned == type.mSigned && mUnsigned == type.mUnsigned && @@ -525,12 +478,12 @@ class CPPCHECKLIB Library { return !(*this == type); } std::string mType; - bool mSigned; - bool mUnsigned; - bool mLong; - bool mPointer; - bool mPtrPtr; - bool mConstPtr; + bool mSigned{}; + bool mUnsigned{}; + bool mLong{}; + bool mPointer{}; + bool mPtrPtr{}; + bool mConstPtr{}; }; struct Platform { @@ -594,7 +547,7 @@ class CPPCHECKLIB Library { }; class CodeBlock { public: - CodeBlock() : mOffset(0) {} + CodeBlock() = default; void setStart(const char* s) { mStart = s; @@ -624,11 +577,11 @@ class CPPCHECKLIB Library { private: std::string mStart; std::string mEnd; - int mOffset; + int mOffset{}; std::set mBlocks; }; enum class FalseTrueMaybe { False, True, Maybe }; - int mAllocId; + int mAllocId{}; std::set mFiles; std::map mAlloc; // allocation functions std::map mDealloc; // deallocation functions diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 501b6805b8f..7feef1f8c57 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -37,8 +37,7 @@ const int MathLib::bigint_bits = 64; -MathLib::value::value(const std::string &s) : - mIntValue(0), mDoubleValue(0), mIsUnsigned(false) +MathLib::value::value(const std::string &s) { if (MathLib::isFloat(s)) { mType = MathLib::value::Type::FLOAT; diff --git a/lib/mathlib.h b/lib/mathlib.h index 709fb0e0bf9..9bab55a8d82 100644 --- a/lib/mathlib.h +++ b/lib/mathlib.h @@ -37,10 +37,10 @@ class CPPCHECKLIB MathLib { /** @brief value class */ class value { private: - long long mIntValue; - double mDoubleValue; + long long mIntValue{}; + double mDoubleValue{}; enum class Type { INT, LONG, LONGLONG, FLOAT } mType; - bool mIsUnsigned; + bool mIsUnsigned{}; void promote(const value &v); diff --git a/lib/programmemory.cpp b/lib/programmemory.cpp index 6c4261eafd6..05c42c461ca 100644 --- a/lib/programmemory.cpp +++ b/lib/programmemory.cpp @@ -429,7 +429,7 @@ static ProgramMemory getInitialProgramState(const Token* tok, return pm; } -ProgramMemoryState::ProgramMemoryState(const Settings* s) : state(), origins(), settings(s) {} +ProgramMemoryState::ProgramMemoryState(const Settings* s) : settings(s) {} void ProgramMemoryState::insert(const ProgramMemory &pm, const Token* origin) { diff --git a/lib/settings.cpp b/lib/settings.cpp index 3e40ef7c752..1efc55c9015 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -36,44 +36,6 @@ const char Settings::SafeChecks::XmlInternalFunctions[] = "internal-functions"; const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables"; Settings::Settings() - : checkAllConfigurations(true), - checkConfiguration(false), - checkHeaders(true), - checkLibrary(false), - checksMaxTime(0), - checkUnusedTemplates(true), - clang(false), - clangExecutable("clang"), - clangTidy(false), - clearIncludeCache(false), - daca(false), - debugnormal(false), - debugSimplified(false), - debugtemplate(false), - debugwarnings(false), - dump(false), - enforcedLang(Language::None), - exceptionHandling(false), - exitCode(0), - force(false), - inlineSuppressions(false), - jobs(1), - loadAverage(0), - maxConfigs(12), - maxCtuDepth(2), - maxTemplateRecursion(100), - performanceValueFlowMaxTime(-1), - preprocessOnly(false), - quiet(false), - relativePaths(false), - reportProgress(false), - showtime(SHOWTIME_MODES::SHOWTIME_NONE), - templateMaxTime(0), - typedefMaxTime(0), - valueFlowMaxIterations(4), - verbose(false), - xml(false), - xml_version(2) { severity.setEnabled(Severity::error, true); certainty.setEnabled(Certainty::normal, true); diff --git a/lib/settings.h b/lib/settings.h index c77ad2392cc..38c7111fbfb 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -114,39 +114,39 @@ class CPPCHECKLIB Settings { std::string buildDir; /** @brief check all configurations (false if -D or --max-configs is used */ - bool checkAllConfigurations; + bool checkAllConfigurations = true; /** Is the 'configuration checking' wanted? */ - bool checkConfiguration; + bool checkConfiguration{}; /** * Check code in the headers, this is on by default but can * be turned off to save CPU */ - bool checkHeaders; + bool checkHeaders = true; /** Check for incomplete info in library files? */ - bool checkLibrary; + bool checkLibrary{}; /** @brief The maximum time in seconds for the checks of a single file */ - int checksMaxTime; + int checksMaxTime{}; /** @brief check unknown function return values */ std::set checkUnknownFunctionReturn; /** Check unused/uninstantiated templates */ - bool checkUnusedTemplates; + bool checkUnusedTemplates = true; /** Use Clang */ - bool clang; + bool clang{}; /** Custom Clang executable */ - std::string clangExecutable; + std::string clangExecutable = "clang"; /** Use clang-tidy */ - bool clangTidy; + bool clangTidy{}; /** Internal: Clear the simplecpp non-existing include cache */ - bool clearIncludeCache; + bool clearIncludeCache{}; /** @brief include paths excluded from checking the configuration */ std::set configExcludePaths; @@ -158,22 +158,22 @@ class CPPCHECKLIB Settings { std::string cppcheckCfgAbout; /** @brief Are we running from DACA script? */ - bool daca; + bool daca{}; /** @brief Is --debug-normal given? */ - bool debugnormal; + bool debugnormal{}; /** @brief Is --debug-simplified given? */ - bool debugSimplified; + bool debugSimplified{}; /** @brief Is --debug-template given? */ - bool debugtemplate; + bool debugtemplate{}; /** @brief Is --debug-warnings given? */ - bool debugwarnings; + bool debugwarnings{}; /** @brief Is --dump given? */ - bool dump; + bool dump{}; std::string dumpFile; enum Language { @@ -181,34 +181,34 @@ class CPPCHECKLIB Settings { }; /** @brief Name of the language that is enforced. Empty per default. */ - Language enforcedLang; + Language enforcedLang{}; /** @brief Is --exception-handling given */ - bool exceptionHandling; + bool exceptionHandling{}; // argv[0] std::string exename; /** @brief If errors are found, this value is returned from main(). Default value is 0. */ - int exitCode; + int exitCode{}; /** @brief List of --file-filter for analyzing special files */ std::vector fileFilters; /** @brief Force checking the files with "too many" configurations (--force). */ - bool force; + bool force{}; /** @brief List of include paths, e.g. "my/includes/" which should be used for finding include files inside source files. (-I) */ std::list includePaths; /** @brief Is --inline-suppr given? */ - bool inlineSuppressions; + bool inlineSuppressions{}; /** @brief How many processes/threads should do checking at the same time. Default is 1. (-j N) */ - unsigned int jobs; + unsigned int jobs = 1; /** @brief --library= */ std::list libraries; @@ -217,17 +217,17 @@ class CPPCHECKLIB Settings { Library library; /** @brief Load average value */ - int loadAverage; + int loadAverage{}; /** @brief Maximum number of configurations to check before bailing. Default is 12. (--max-configs=N) */ - int maxConfigs; + int maxConfigs = 12; /** @brief --max-ctu-depth */ - int maxCtuDepth; + int maxCtuDepth = 2; /** @brief max template recursion */ - int maxTemplateRecursion; + int maxTemplateRecursion = 100; /** @brief suppress exitcode */ Suppressions nofail; @@ -241,7 +241,7 @@ class CPPCHECKLIB Settings { cppcheck::Platform platform; /** @brief Experimental: --performance-valueflow-max-time=T */ - int performanceValueFlowMaxTime; + int performanceValueFlowMaxTime = -1; /** @brief --performance-valueflow-max-if-count=C */ int performanceValueFlowMaxIfCount; @@ -256,33 +256,26 @@ class CPPCHECKLIB Settings { std::string premiumArgs; /** @brief Using -E for debugging purposes */ - bool preprocessOnly; + bool preprocessOnly{}; ImportProject project; /** @brief Is --quiet given? */ - bool quiet; + bool quiet{}; /** @brief Use relative paths in output. */ - bool relativePaths; + bool relativePaths{}; /** @brief --report-progress */ - bool reportProgress; + bool reportProgress{}; /** Rule */ - class CPPCHECKLIB Rule { - public: - Rule() - : tokenlist("normal") // use normal tokenlist - , id("rule") // default id - , severity(Severity::style) { // default severity - } - - std::string tokenlist; + struct CPPCHECKLIB Rule { + std::string tokenlist = "normal"; // use normal tokenlist std::string pattern; - std::string id; + std::string id = "rule"; // default id std::string summary; - Severity::SeverityType severity; + Severity::SeverityType severity = Severity::style; // default severity }; #ifdef HAVE_RULES @@ -293,9 +286,7 @@ class CPPCHECKLIB Settings { #endif /** Do not only check how interface is used. Also check that interface is safe. */ - class CPPCHECKLIB SafeChecks { - public: - SafeChecks() : classes(false), externalFunctions(false), internalFunctions(false), externalVariables(false) {} + struct CPPCHECKLIB SafeChecks { static const char XmlRootName[]; static const char XmlClasses[]; @@ -313,26 +304,26 @@ class CPPCHECKLIB Settings { * - public functions can be called in any order * - public variables can have any value */ - bool classes; + bool classes{}; /** * External functions * - external functions can be called in any order * - function parameters can have any values */ - bool externalFunctions; + bool externalFunctions{}; /** * Experimental: assume that internal functions can be used in any way * This is only available in the GUI. */ - bool internalFunctions; + bool internalFunctions{}; /** * Global variables that can be modified outside the TU. * - Such variable can have "any" value */ - bool externalVariables; + bool externalVariables{}; }; SafeChecks safeChecks; @@ -342,7 +333,7 @@ class CPPCHECKLIB Settings { SimpleEnableGroup checks; /** @brief show timing information (--showtime=file|summary|top5) */ - SHOWTIME_MODES showtime; + SHOWTIME_MODES showtime{}; /** Struct contains standards settings */ Standards standards; @@ -356,10 +347,10 @@ class CPPCHECKLIB Settings { std::string templateLocation; /** @brief The maximum time in seconds for the template instantiation */ - std::size_t templateMaxTime; + std::size_t templateMaxTime{}; /** @brief The maximum time in seconds for the typedef simplification */ - std::size_t typedefMaxTime; + std::size_t typedefMaxTime{}; /** @brief defines given by the user */ std::string userDefines; @@ -371,16 +362,16 @@ class CPPCHECKLIB Settings { std::list userIncludes; /** @brief the maximum iterations of valueflow (--valueflow-max-iterations=T) */ - std::size_t valueFlowMaxIterations; + std::size_t valueFlowMaxIterations = 4; /** @brief Is --verbose given? */ - bool verbose; + bool verbose{}; /** @brief write XML results (--xml) */ - bool xml; + bool xml{}; /** @brief XML version (--xml-version=..) */ - int xml_version; + int xml_version = 2; /** * @brief return true if a included file is to be excluded in Preprocessor::getConfigs diff --git a/lib/standards.h b/lib/standards.h index e92656287ad..ee56d88816c 100644 --- a/lib/standards.h +++ b/lib/standards.h @@ -35,17 +35,14 @@ */ struct Standards { /** C code standard */ - enum cstd_t { C89, C99, C11, CLatest=C11 } c; + enum cstd_t { C89, C99, C11, CLatest = C11 } c = CLatest; /** C++ code standard */ - enum cppstd_t { CPP03, CPP11, CPP14, CPP17, CPP20, CPP23, CPPLatest=CPP23 } cpp; + enum cppstd_t { CPP03, CPP11, CPP14, CPP17, CPP20, CPP23, CPPLatest = CPP23 } cpp = CPPLatest; /** --std value given on command line */ std::string stdValue; - /** This constructor clear all the variables **/ - Standards() : c(CLatest), cpp(CPPLatest) {} - bool setC(const std::string& str) { stdValue = str; if (str == "c89" || str == "C89") { diff --git a/lib/suppressions.h b/lib/suppressions.h index 2f0b339ed81..cc64ee51cef 100644 --- a/lib/suppressions.h +++ b/lib/suppressions.h @@ -55,8 +55,8 @@ class CPPCHECKLIB Suppressions { }; struct CPPCHECKLIB Suppression { - Suppression() : lineNumber(NO_LINE), hash(0), thisAndNextLine(false), matched(false), checked(false) {} - Suppression(std::string id, std::string file, int line=NO_LINE) : errorId(std::move(id)), fileName(std::move(file)), lineNumber(line), hash(0), thisAndNextLine(false), matched(false), checked(false) {} + Suppression() = default; + Suppression(std::string id, std::string file, int line=NO_LINE) : errorId(std::move(id)), fileName(std::move(file)), lineNumber(line) {} bool operator<(const Suppression &other) const { if (errorId != other.errorId) @@ -103,12 +103,12 @@ class CPPCHECKLIB Suppressions { std::string errorId; std::string fileName; - int lineNumber; + int lineNumber = NO_LINE; std::string symbolName; - std::size_t hash; - bool thisAndNextLine; // Special case for backwards compatibility: { // cppcheck-suppress something - bool matched; - bool checked; // for inline suppressions, checked or not + std::size_t hash{}; + bool thisAndNextLine{}; // Special case for backwards compatibility: { // cppcheck-suppress something + bool matched{}; + bool checked{}; // for inline suppressions, checked or not enum { NO_LINE = -1 }; }; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 97f644f4c0f..005d0dc2218 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2086,8 +2086,7 @@ Variable::Variable(const Token *name_, const std::string &clangType, const Token mAccess(access_), mFlags(0), mType(type_), - mScope(scope_), - mValueType(nullptr) + mScope(scope_) { if (!mTypeStartToken && mTypeEndToken) { mTypeStartToken = mTypeEndToken; @@ -2135,14 +2134,12 @@ Variable::Variable(const Token *name_, const std::string &clangType, const Token } Variable::Variable(const Variable &var, const Scope *scope) - : mValueType(nullptr) { *this = var; mScope = scope; } Variable::Variable(const Variable &var) - : mValueType(nullptr) { *this = var; } @@ -2401,20 +2398,7 @@ Function::Function(const Tokenizer *mTokenizer, const Token *tokArgDef) : tokenDef(tokDef), argDef(tokArgDef), - token(nullptr), - arg(nullptr), - retDef(nullptr), - retType(nullptr), - functionScope(nullptr), - nestedIn(scope), - initArgCount(0), - type(eFunction), - noexceptArg(nullptr), - throwArg(nullptr), - templateDef(nullptr), - functionPointerUsage(nullptr), - access(AccessControl::Public), - mFlags(0) + nestedIn(scope) { // operator function if (::isOperator(tokenDef)) { @@ -2519,22 +2503,7 @@ Function::Function(const Tokenizer *mTokenizer, } Function::Function(const Token *tokenDef, const std::string &clangType) - : tokenDef(tokenDef), - argDef(nullptr), - token(nullptr), - arg(nullptr), - retDef(nullptr), - retType(nullptr), - functionScope(nullptr), - nestedIn(nullptr), - initArgCount(0), - type(eFunction), - noexceptArg(nullptr), - throwArg(nullptr), - templateDef(nullptr), - functionPointerUsage(nullptr), - access(AccessControl::Public), - mFlags(0) + : tokenDef(tokenDef) { // operator function if (::isOperator(tokenDef)) { @@ -4461,14 +4430,7 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope * check(check_), classDef(classDef_), nestedIn(nestedIn_), - numConstructors(0), - numCopyOrMoveConstructors(0), - type(type_), - definedType(nullptr), - functionOf(nullptr), - function(nullptr), - enumType(nullptr), - enumClass(false) + type(type_) { setBodyStartEnd(start_); } @@ -4476,16 +4438,7 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope * Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_) : check(check_), classDef(classDef_), - bodyStart(nullptr), - bodyEnd(nullptr), - nestedIn(nestedIn_), - numConstructors(0), - numCopyOrMoveConstructors(0), - definedType(nullptr), - functionOf(nullptr), - function(nullptr), - enumType(nullptr), - enumClass(false) + nestedIn(nestedIn_) { const Token *nameTok = classDef; if (!classDef) { diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index aa7d644a69a..d7c50ee7a2a 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -60,11 +60,9 @@ enum class AccessControl { Public, Protected, Private, Global, Namespace, Argume * @brief Array dimension information. */ struct Dimension { - Dimension() : tok(nullptr), num(0), known(true) {} - - const Token *tok; ///< size token - MathLib::bigint num; ///< (assumed) dimension length when size is a number, 0 if not known - bool known; ///< Known size + const Token* tok{}; ///< size token + MathLib::bigint num{}; ///< (assumed) dimension length when size is a number, 0 if not known + bool known = true; ///< Known size }; /** @brief Information about a class type. */ @@ -75,18 +73,14 @@ class CPPCHECKLIB Type { const Scope* enclosingScope; enum class NeedInitialization { Unknown, True, False - } needInitialization; - - class BaseInfo { - public: - BaseInfo() : - type(nullptr), nameTok(nullptr), access(AccessControl::Public), isVirtual(false) {} + } needInitialization = NeedInitialization::Unknown; + struct BaseInfo { std::string name; - const Type* type; - const Token* nameTok; - AccessControl access; // public/protected/private - bool isVirtual; + const Type* type{}; + const Token* nameTok{}; + AccessControl access{}; // public/protected/private + bool isVirtual{}; // allow ordering within containers bool operator<(const BaseInfo& rhs) const { return this->type < rhs.type; @@ -94,29 +88,22 @@ class CPPCHECKLIB Type { }; struct FriendInfo { - FriendInfo() : - nameStart(nullptr), nameEnd(nullptr), type(nullptr) {} - - const Token* nameStart; - const Token* nameEnd; - const Type* type; + const Token* nameStart{}; + const Token* nameEnd{}; + const Type* type{}; }; std::vector derivedFrom; std::vector friendList; - const Token * typeStart; - const Token * typeEnd; - MathLib::bigint sizeOf; + const Token* typeStart{}; + const Token* typeEnd{}; + MathLib::bigint sizeOf{}; explicit Type(const Token* classDef_ = nullptr, const Scope* classScope_ = nullptr, const Scope* enclosingScope_ = nullptr) : classDef(classDef_), classScope(classScope_), - enclosingScope(enclosingScope_), - needInitialization(NeedInitialization::Unknown), - typeStart(nullptr), - typeEnd(nullptr), - sizeOf(0) { + enclosingScope(enclosingScope_) { if (classDef_ && classDef_->str() == "enum") needInitialization = NeedInitialization::True; else if (classDef_ && classDef_->str() == "using") { @@ -167,15 +154,14 @@ class CPPCHECKLIB Type { bool isDerivedFrom(const std::string & ancestor) const; }; -class CPPCHECKLIB Enumerator { -public: - explicit Enumerator(const Scope * scope_) : scope(scope_), name(nullptr), value(0), start(nullptr), end(nullptr), value_known(false) {} +struct CPPCHECKLIB Enumerator { + explicit Enumerator(const Scope * scope_) : scope(scope_) {} const Scope * scope; - const Token * name; - MathLib::bigint value; - const Token * start; - const Token * end; - bool value_known; + const Token* name{}; + MathLib::bigint value{}; + const Token* start{}; + const Token* end{}; + bool value_known{}; }; /** @brief Information about a member variable. */ @@ -238,8 +224,7 @@ class CPPCHECKLIB Variable { mAccess(access_), mFlags(0), mType(type_), - mScope(scope_), - mValueType(nullptr) { + mScope(scope_) { evaluate(settings); } @@ -699,7 +684,7 @@ class CPPCHECKLIB Variable { /** @brief pointer to scope this variable is in */ const Scope *mScope; - const ValueType *mValueType; + const ValueType* mValueType{}; /** @brief array dimensions */ std::vector mDimensions; @@ -914,22 +899,22 @@ class CPPCHECKLIB Function { } bool isSafe(const Settings *settings) const; - const Token *tokenDef; ///< function name token in class definition - const Token *argDef; ///< function argument start '(' in class definition - const Token *token; ///< function name token in implementation - const Token *arg; ///< function argument start '(' - const Token *retDef; ///< function return type token - const ::Type *retType; ///< function return type - const Scope *functionScope; ///< scope of function body - const Scope* nestedIn; ///< Scope the function is declared in + const Token* tokenDef{}; ///< function name token in class definition + const Token* argDef{}; ///< function argument start '(' in class definition + const Token* token{}; ///< function name token in implementation + const Token* arg{}; ///< function argument start '(' + const Token* retDef{}; ///< function return type token + const ::Type* retType{}; ///< function return type + const Scope* functionScope{}; ///< scope of function body + const Scope* nestedIn{}; ///< Scope the function is declared in std::vector argumentList; ///< argument list - nonneg int initArgCount; ///< number of args with default values - Type type; ///< constructor, destructor, ... - const Token *noexceptArg; ///< noexcept token - const Token *throwArg; ///< throw token - const Token *templateDef; ///< points to 'template <' before function - const Token *functionPointerUsage; ///< function pointer usage - AccessControl access; ///< public/protected/private + nonneg int initArgCount{}; ///< number of args with default values + Type type = eFunction; ///< constructor, destructor, ... + const Token* noexceptArg{}; ///< noexcept token + const Token* throwArg{}; ///< throw token + const Token* templateDef{}; ///< points to 'template <' before function + const Token* functionPointerUsage{}; ///< function pointer usage + AccessControl access{}; ///< public/protected/private bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length) const; @@ -959,7 +944,7 @@ class CPPCHECKLIB Function { /** Recursively determine if this function overrides a virtual function in a base class */ const Function * getOverriddenFunctionRecursive(const ::Type* baseType, bool *foundAllBaseClasses) const; - unsigned int mFlags; + unsigned int mFlags{}; void isInline(bool state) { setFlag(fIsInline, state); @@ -1039,31 +1024,31 @@ class CPPCHECKLIB Scope { Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_); Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_, ScopeType type_, const Token *start_); - const SymbolDatabase *check; + const SymbolDatabase* check{}; std::string className; - const Token *classDef; ///< class/struct/union/namespace token - const Token *bodyStart; ///< '{' token - const Token *bodyEnd; ///< '}' token + const Token* classDef{}; ///< class/struct/union/namespace token + const Token* bodyStart{}; ///< '{' token + const Token* bodyEnd{}; ///< '}' token std::list functionList; std::multimap functionMap; std::list varlist; - const Scope *nestedIn; + const Scope* nestedIn{}; std::vector nestedList; - nonneg int numConstructors; - nonneg int numCopyOrMoveConstructors; + nonneg int numConstructors{}; + nonneg int numCopyOrMoveConstructors{}; std::vector usingList; - ScopeType type; - Type* definedType; + ScopeType type{}; + Type* definedType{}; std::map definedTypesMap; std::vector bodyStartList; // function specific fields - const Scope *functionOf; ///< scope this function belongs to - Function *function; ///< function info for this function + const Scope* functionOf{}; ///< scope this function belongs to + Function* function{}; ///< function info for this function // enum specific fields - const Token * enumType; - bool enumClass; + const Token* enumType{}; + bool enumClass{}; std::vector enumeratorList; @@ -1224,7 +1209,7 @@ enum class Reference { /** Value type */ class CPPCHECKLIB ValueType { public: - enum Sign { UNKNOWN_SIGN, SIGNED, UNSIGNED } sign; + enum Sign { UNKNOWN_SIGN, SIGNED, UNSIGNED } sign = UNKNOWN_SIGN; enum Type { UNKNOWN_TYPE, POD, @@ -1245,80 +1230,42 @@ class CPPCHECKLIB ValueType { FLOAT, DOUBLE, LONGDOUBLE - } type; - nonneg int bits; ///< bitfield bitcount - nonneg int pointer; ///< 0=>not pointer, 1=>*, 2=>**, 3=>***, etc - nonneg int constness; ///< bit 0=data, bit 1=*, bit 2=** + } type = UNKNOWN_TYPE; + nonneg int bits{}; ///< bitfield bitcount + nonneg int pointer{}; ///< 0=>not pointer, 1=>*, 2=>**, 3=>***, etc + nonneg int constness{}; ///< bit 0=data, bit 1=*, bit 2=** Reference reference = Reference::None; ///< Is the outermost indirection of this type a reference or rvalue ///< reference or not? pointer=2, Reference=LValue would be a T**& - const Scope* typeScope; ///< if the type definition is seen this point out the type scope - const ::Type* smartPointerType; ///< Smart pointer type - const Token* smartPointerTypeToken; ///< Smart pointer type token - const Library::SmartPointer* smartPointer; ///< Smart pointer - const Library::Container* container; ///< If the type is a container defined in a cfg file, this is the used + const Scope* typeScope{}; ///< if the type definition is seen this point out the type scope + const ::Type* smartPointerType{}; ///< Smart pointer type + const Token* smartPointerTypeToken{}; ///< Smart pointer type token + const Library::SmartPointer* smartPointer{}; ///< Smart pointer + const Library::Container* container{}; ///< If the type is a container defined in a cfg file, this is the used ///< container - const Token* containerTypeToken; ///< The container type token. the template argument token that defines the + const Token* containerTypeToken{}; ///< The container type token. the template argument token that defines the ///< container element type. std::string originalTypeName; ///< original type name as written in the source code. eg. this might be "uint8_t" ///< when type is CHAR. ErrorPath debugPath; ///< debug path to the type - ValueType() - : sign(UNKNOWN_SIGN), - type(UNKNOWN_TYPE), - bits(0), - pointer(0U), - constness(0U), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr), - debugPath() - {} + ValueType() = default; ValueType(enum Sign s, enum Type t, nonneg int p) : sign(s), type(t), - bits(0), - pointer(p), - constness(0U), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr), - debugPath() + pointer(p) {} ValueType(enum Sign s, enum Type t, nonneg int p, nonneg int c) : sign(s), type(t), - bits(0), pointer(p), - constness(c), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr), - debugPath() + constness(c) {} ValueType(enum Sign s, enum Type t, nonneg int p, nonneg int c, std::string otn) : sign(s), type(t), - bits(0), pointer(p), constness(c), - typeScope(nullptr), - smartPointerType(nullptr), - smartPointerTypeToken(nullptr), - smartPointer(nullptr), - container(nullptr), - containerTypeToken(nullptr), - originalTypeName(std::move(otn)), - debugPath() + originalTypeName(std::move(otn)) {} static ValueType parseDecl(const Token *type, const Settings &settings, bool isCpp); diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 3ff539ae067..e551790a461 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -281,7 +281,7 @@ bool TemplateSimplifier::TokenAndName::isAliasToken(const Token *tok) const TemplateSimplifier::TemplateSimplifier(Tokenizer &tokenizer) : mTokenizer(tokenizer), mTokenList(mTokenizer.list), mSettings(*mTokenizer.mSettings), - mErrorLogger(mTokenizer.mErrorLogger), mChanged(false) + mErrorLogger(mTokenizer.mErrorLogger) {} TemplateSimplifier::~TemplateSimplifier() diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index 23dad621bdd..763962ea24c 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -500,7 +500,7 @@ class CPPCHECKLIB TemplateSimplifier { TokenList &mTokenList; const Settings &mSettings; ErrorLogger *mErrorLogger; - bool mChanged; + bool mChanged{}; std::list mTemplateDeclarations; std::list mTemplateForwardDeclarations; diff --git a/lib/timer.cpp b/lib/timer.cpp index c5d3dfd1282..4e04b58190a 100644 --- a/lib/timer.cpp +++ b/lib/timer.cpp @@ -101,9 +101,6 @@ Timer::Timer(std::string str, SHOWTIME_MODES showtimeMode, TimerResultsIntf* tim Timer::Timer(bool fileTotal, std::string filename) : mStr(std::move(filename)) - , mTimerResults(nullptr) - , mStart(std::clock()) - , mShowTimeMode(SHOWTIME_MODES::SHOWTIME_FILE_TOTAL) , mStopped(!fileTotal) {} diff --git a/lib/timer.h b/lib/timer.h index 4bd8884c242..1fe246f417d 100644 --- a/lib/timer.h +++ b/lib/timer.h @@ -43,12 +43,8 @@ class CPPCHECKLIB TimerResultsIntf { }; struct TimerResultsData { - std::clock_t mClocks; - long mNumberOfResults; - - TimerResultsData() - : mClocks(0) - , mNumberOfResults(0) {} + std::clock_t mClocks{}; + long mNumberOfResults{}; double seconds() const { const double ret = (double)((unsigned long)mClocks) / (double)CLOCKS_PER_SEC; @@ -81,10 +77,10 @@ class CPPCHECKLIB Timer { private: const std::string mStr; - TimerResultsIntf* mTimerResults; - std::clock_t mStart; - const SHOWTIME_MODES mShowTimeMode; - bool mStopped; + TimerResultsIntf* mTimerResults{}; + std::clock_t mStart = std::clock(); + const SHOWTIME_MODES mShowTimeMode = SHOWTIME_MODES::SHOWTIME_FILE_TOTAL; + bool mStopped{}; }; //--------------------------------------------------------------------------- #endif // timerH diff --git a/lib/token.cpp b/lib/token.cpp index 390490e8637..0e9184626f3 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -56,12 +56,7 @@ namespace { const std::list TokenImpl::mEmptyValueList; Token::Token(TokensFrontBack *tokensFrontBack) : - mTokensFrontBack(tokensFrontBack), - mNext(nullptr), - mPrevious(nullptr), - mLink(nullptr), - mTokType(eNone), - mFlags(0) + mTokensFrontBack(tokensFrontBack) { mImpl = new TokenImpl(); } diff --git a/lib/token.h b/lib/token.h index 66016f33bf1..d04d365d445 100644 --- a/lib/token.h +++ b/lib/token.h @@ -39,7 +39,7 @@ #include #include -class Enumerator; +struct Enumerator; class Function; class Scope; class Settings; @@ -54,48 +54,48 @@ class Token; * @brief This struct stores pointers to the front and back tokens of the list this token is in. */ struct TokensFrontBack { - Token *front; - Token *back; - const TokenList* list; + Token *front{}; + Token* back{}; + const TokenList* list{}; }; struct ScopeInfo2 { ScopeInfo2(std::string name_, const Token *bodyEnd_, std::set usingNamespaces_ = std::set()) : name(std::move(name_)), bodyEnd(bodyEnd_), usingNamespaces(std::move(usingNamespaces_)) {} std::string name; - const Token * const bodyEnd; + const Token* const bodyEnd{}; std::set usingNamespaces; }; enum class TokenDebug { None, ValueFlow, ValueType }; struct TokenImpl { - nonneg int mVarId; - nonneg int mFileIndex; - nonneg int mLineNumber; - nonneg int mColumn; - nonneg int mExprId; + nonneg int mVarId{}; + nonneg int mFileIndex{}; + nonneg int mLineNumber{}; + nonneg int mColumn{}; + nonneg int mExprId{}; /** * A value from 0-100 that provides a rough idea about where in the token * list this token is located. */ - nonneg int mProgressValue; + nonneg int mProgressValue{}; /** * Token index. Position in token list */ - nonneg int mIndex; + nonneg int mIndex{}; /** Bitfield bit count. */ - unsigned char mBits; + unsigned char mBits{}; // AST.. - Token *mAstOperand1; - Token *mAstOperand2; - Token *mAstParent; + Token* mAstOperand1{}; + Token* mAstOperand2{}; + Token* mAstParent{}; // symbol database information - const Scope *mScope; + const Scope* mScope{}; union { const Function *mFunction; const Variable *mVariable; @@ -104,60 +104,38 @@ struct TokenImpl { }; // original name like size_t - std::string* mOriginalName; + std::string* mOriginalName{}; // ValueType - ValueType *mValueType; + ValueType* mValueType{}; // ValueFlow - std::list* mValues; + std::list* mValues{}; static const std::list mEmptyValueList; // Pointer to a template in the template simplifier - std::set* mTemplateSimplifierPointers; + std::set* mTemplateSimplifierPointers{}; // Pointer to the object representing this token's scope std::shared_ptr mScopeInfo; // __cppcheck_in_range__ struct CppcheckAttributes { - enum Type {LOW,HIGH} type; - MathLib::bigint value; - struct CppcheckAttributes *next; + enum Type { LOW, HIGH } type = LOW; + MathLib::bigint value{}; + CppcheckAttributes* next{}; }; - struct CppcheckAttributes *mCppcheckAttributes; + CppcheckAttributes* mCppcheckAttributes{}; // For memoization, to speed up parsing of huge arrays #8897 - enum class Cpp11init {UNKNOWN, CPP11INIT, NOINIT} mCpp11init; + enum class Cpp11init { UNKNOWN, CPP11INIT, NOINIT } mCpp11init = Cpp11init::UNKNOWN; - TokenDebug mDebug; + TokenDebug mDebug{}; void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value); bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint &value) const; - TokenImpl() - : mVarId(0), - mFileIndex(0), - mLineNumber(0), - mColumn(0), - mExprId(0), - mProgressValue(0), - mIndex(0), - mBits(0), - mAstOperand1(nullptr), - mAstOperand2(nullptr), - mAstParent(nullptr), - mScope(nullptr), - mFunction(nullptr), // Initialize whole union - mOriginalName(nullptr), - mValueType(nullptr), - mValues(nullptr), - mTemplateSimplifierPointers(nullptr), - mScopeInfo(nullptr), - mCppcheckAttributes(nullptr), - mCpp11init(Cpp11init::UNKNOWN), - mDebug(TokenDebug::None) - {} + TokenImpl() : mFunction(nullptr) {} ~TokenImpl(); }; @@ -177,7 +155,7 @@ struct TokenImpl { */ class CPPCHECKLIB Token { private: - TokensFrontBack* mTokensFrontBack; + TokensFrontBack* mTokensFrontBack{}; public: Token(const Token &) = delete; @@ -1301,9 +1279,9 @@ class CPPCHECKLIB Token { std::string mStr; - Token *mNext; - Token *mPrevious; - Token *mLink; + Token* mNext{}; + Token* mPrevious{}; + Token* mLink{}; enum : uint64_t { fIsUnsigned = (1ULL << 0), @@ -1355,11 +1333,11 @@ class CPPCHECKLIB Token { efIsUnique = efMaxSize - 2, }; - Token::Type mTokType; + Token::Type mTokType = eNone; - uint64_t mFlags; + uint64_t mFlags{}; - TokenImpl *mImpl; + TokenImpl* mImpl{}; /** * Get specified flag state. diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index deb580111a3..656db082f3f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -64,15 +64,14 @@ namespace { // local struct used in setVarId // in order to store information about the scope struct VarIdScopeInfo { - VarIdScopeInfo() - : isExecutable(false), isStructInit(false), isEnum(false), startVarid(0) {} + VarIdScopeInfo() = default; VarIdScopeInfo(bool isExecutable, bool isStructInit, bool isEnum, nonneg int startVarid) : isExecutable(isExecutable), isStructInit(isStructInit), isEnum(isEnum), startVarid(startVarid) {} - const bool isExecutable; - const bool isStructInit; - const bool isEnum; - const nonneg int startVarid; + const bool isExecutable{}; + const bool isStructInit{}; + const bool isEnum{}; + const nonneg int startVarid{}; }; } @@ -162,12 +161,7 @@ Tokenizer::Tokenizer(const Settings *settings, ErrorLogger *errorLogger, const P list(settings), mSettings(settings), mErrorLogger(errorLogger), - mSymbolDatabase(nullptr), mTemplateSimplifier(new TemplateSimplifier(*this)), - mVarId(0), - mUnnamedCount(0), - mCodeWithTemplates(false), //is there any templates? - mTimerResults(nullptr), mPreprocessor(preprocessor) { // make sure settings are specified @@ -405,11 +399,10 @@ Token * Tokenizer::deleteInvalidTypedef(Token *typeDef) namespace { struct Space { - Space() : bodyEnd(nullptr), bodyEnd2(nullptr), isNamespace(false) {} std::string className; - const Token * bodyEnd; // for body contains typedef define - const Token * bodyEnd2; // for body contains typedef using - bool isNamespace; + const Token* bodyEnd{}; // for body contains typedef define + const Token* bodyEnd2{}; // for body contains typedef using + bool isNamespace{}; std::set recordTypes; }; } @@ -4022,9 +4015,9 @@ class VariableMap { std::map mVariableId; std::map mVariableId_global; std::stack>> mScopeInfo; - mutable nonneg int mVarId; + mutable nonneg int mVarId{}; public: - VariableMap() : mVarId(0) {} + VariableMap() = default; void enterScope(); bool leaveScope(); void addVariable(const std::string& varname, bool globalNamespace); diff --git a/lib/tokenize.h b/lib/tokenize.h index f296f10ae04..cea8e513238 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -698,7 +698,7 @@ class CPPCHECKLIB Tokenizer { ErrorLogger* const mErrorLogger; /** Symbol database that all checks etc can use */ - SymbolDatabase *mSymbolDatabase; + SymbolDatabase* mSymbolDatabase{}; TemplateSimplifier * const mTemplateSimplifier; @@ -719,21 +719,21 @@ class CPPCHECKLIB Tokenizer { std::vector mTypedefInfo; /** variable count */ - nonneg int mVarId; + nonneg int mVarId{}; /** unnamed count "Unnamed0", "Unnamed1", "Unnamed2", ... */ - nonneg int mUnnamedCount; + nonneg int mUnnamedCount{}; /** * was there any templates? templates that are "unused" are * removed from the token list */ - bool mCodeWithTemplates; + bool mCodeWithTemplates{}; /** * TimerResults */ - TimerResults *mTimerResults; + TimerResults* mTimerResults{}; const Preprocessor * const mPreprocessor; }; diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 6a8a5edc858..2e023d54841 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -49,10 +49,7 @@ static const int AST_MAX_DEPTH = 150; TokenList::TokenList(const Settings* settings) : - mTokensFrontBack(), - mSettings(settings), - mIsC(false), - mIsCpp(false) + mSettings(settings) { mTokensFrontBack.list = this; } @@ -396,14 +393,14 @@ std::size_t TokenList::calculateHash() const struct AST_state { std::stack op; - int depth; - int inArrayAssignment; + int depth{}; + int inArrayAssignment{}; bool cpp; - int assign; - bool inCase; // true from case to : - bool stopAtColon; // help to properly parse ternary operators - const Token *functionCallEndPar; - explicit AST_state(bool cpp) : depth(0), inArrayAssignment(0), cpp(cpp), assign(0), inCase(false),stopAtColon(false), functionCallEndPar(nullptr) {} + int assign{}; + bool inCase{}; // true from case to : + bool stopAtColon{}; // help to properly parse ternary operators + const Token* functionCallEndPar{}; + explicit AST_state(bool cpp) : cpp(cpp) {} }; static Token* skipDecl(Token* tok, std::vector* inner = nullptr) diff --git a/lib/tokenlist.h b/lib/tokenlist.h index 68b14523d8e..a150d36f360 100644 --- a/lib/tokenlist.h +++ b/lib/tokenlist.h @@ -205,11 +205,11 @@ class CPPCHECKLIB TokenList { std::vector mOrigFiles; /** settings */ - const Settings* mSettings; + const Settings* mSettings{}; /** File is known to be C/C++ code */ - bool mIsC; - bool mIsCpp; + bool mIsC{}; + bool mIsCpp{}; }; /// @} diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index dcadeaee973..2b2b7423efd 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3113,18 +3113,14 @@ struct SingleValueFlowAnalyzer : ValueFlowAnalyzer { struct ExpressionAnalyzer : SingleValueFlowAnalyzer { const Token* expr; - bool local; - bool unknown; - bool dependOnThis; - bool uniqueExprId; + bool local = true; + bool unknown{}; + bool dependOnThis{}; + bool uniqueExprId{}; ExpressionAnalyzer(const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s) : SingleValueFlowAnalyzer(std::move(val), t, s), - expr(e), - local(true), - unknown(false), - dependOnThis(false), - uniqueExprId(false) + expr(e) { assert(e && e->exprId() != 0 && "Not a valid expression"); @@ -3240,7 +3236,7 @@ struct SameExpressionAnalyzer : ExpressionAnalyzer { }; struct OppositeExpressionAnalyzer : ExpressionAnalyzer { - bool isNot; + bool isNot{}; OppositeExpressionAnalyzer(bool pIsNot, const Token* e, ValueFlow::Value val, const TokenList& t, const Settings* s) : ExpressionAnalyzer(e, std::move(val), t, s), isNot(pIsNot) @@ -3942,23 +3938,21 @@ static void valueFlowForwardLifetime(Token * tok, TokenList &tokenlist, ErrorLog } struct LifetimeStore { - const Token *argtok; + const Token* argtok{}; std::string message; - ValueFlow::Value::LifetimeKind type; + ValueFlow::Value::LifetimeKind type = ValueFlow::Value::LifetimeKind::Object; ErrorPath errorPath; - bool inconclusive; - bool forward; + bool inconclusive{}; + bool forward = true; struct Context { - Token* tok; - TokenList* tokenlist; - ErrorLogger* errorLogger; - const Settings* settings; + Token* tok{}; + TokenList* tokenlist{}; + ErrorLogger* errorLogger{}; + const Settings* settings{}; }; - LifetimeStore() - : argtok(nullptr), message(), type(), errorPath(), inconclusive(false), forward(true), mContext(nullptr) - {} + LifetimeStore() = default; LifetimeStore(const Token* argtok, std::string message, @@ -3967,10 +3961,7 @@ struct LifetimeStore { : argtok(argtok), message(std::move(message)), type(type), - errorPath(), - inconclusive(inconclusive), - forward(true), - mContext(nullptr) + inconclusive(inconclusive) {} template @@ -4055,7 +4046,7 @@ struct LifetimeStore { update = true; } if (update && forward) - forwardLifetime(tok, tokenlist, errorLogger, settings); + forwardLifetime(tok, &tokenlist, errorLogger, settings); return update; } @@ -4150,7 +4141,7 @@ struct LifetimeStore { } } if (update && forward) - forwardLifetime(tok, tokenlist, errorLogger, settings); + forwardLifetime(tok, &tokenlist, errorLogger, settings); return update; } @@ -4226,15 +4217,15 @@ struct LifetimeStore { } private: - Context* mContext; - void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings) const { + Context* mContext{}; + void forwardLifetime(Token* tok, TokenList* tokenlist, ErrorLogger* errorLogger, const Settings* settings) const { if (mContext) { mContext->tok = tok; - mContext->tokenlist = &tokenlist; + mContext->tokenlist = tokenlist; mContext->errorLogger = errorLogger; mContext->settings = settings; } - valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); + valueFlowForwardLifetime(tok, *tokenlist, errorLogger, settings); } }; @@ -4660,12 +4651,6 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList& tokenlist, Error struct Lambda { explicit Lambda(const Token* tok) - : capture(nullptr), - arguments(nullptr), - returnTok(nullptr), - bodyTok(nullptr), - explicitCaptures(), - implicitCapture(LifetimeCapture::Undefined) { if (!Token::simpleMatch(tok, "[") || !tok->link()) return; @@ -4701,12 +4686,12 @@ struct Lambda { } } - const Token * capture; - const Token * arguments; - const Token * returnTok; - const Token * bodyTok; + const Token* capture{}; + const Token* arguments{}; + const Token* returnTok{}; + const Token* bodyTok{}; std::unordered_map> explicitCaptures; - LifetimeCapture implicitCapture; + LifetimeCapture implicitCapture = LifetimeCapture::Undefined; std::vector getCaptures() const { return getArguments(capture); @@ -6047,7 +6032,7 @@ static void insertNegateKnown(std::list& values, const std::li struct ConditionHandler { struct Condition { - const Token *vartok; + const Token* vartok{}; std::list true_values; std::list false_values; bool inverted = false; @@ -6109,8 +6094,6 @@ struct ConditionHandler { return ctx; } - - Condition() : vartok(nullptr), true_values(), false_values(), inverted(false), impossible(true) {} }; virtual std::vector parse(const Token* tok, const Settings* settings) const = 0; @@ -7168,7 +7151,7 @@ struct MultiValueFlowAnalyzer : ValueFlowAnalyzer { std::unordered_map vars; MultiValueFlowAnalyzer(const std::unordered_map& args, const TokenList& t, const Settings* set) - : ValueFlowAnalyzer(t, set), values(), vars() { + : ValueFlowAnalyzer(t, set) { for (const auto& p:args) { values[p.first->declarationId()] = p.second; vars[p.first->declarationId()] = p.first; diff --git a/lib/valueflow.h b/lib/valueflow.h index 0c0395a37ef..02e81e6609c 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -72,19 +72,19 @@ namespace ValueFlow { bool isContainerSizeChanged(const Token* tok, int indirect, const Settings* settings = nullptr, int depth = 20); struct LifetimeToken { - const Token* token; + const Token* token{}; Value::ErrorPath errorPath; - bool addressOf; - bool inconclusive; + bool addressOf{}; + bool inconclusive{}; - LifetimeToken() : token(nullptr), errorPath(), addressOf(false), inconclusive(false) {} + LifetimeToken() = default; LifetimeToken(const Token* token, Value::ErrorPath errorPath) - : token(token), errorPath(std::move(errorPath)), addressOf(false), inconclusive(false) + : token(token), errorPath(std::move(errorPath)) {} LifetimeToken(const Token* token, bool addressOf, Value::ErrorPath errorPath) - : token(token), errorPath(std::move(errorPath)), addressOf(addressOf), inconclusive(false) + : token(token), errorPath(std::move(errorPath)), addressOf(addressOf) {} static std::vector setAddressOf(std::vector v, bool b) { diff --git a/lib/vfvalue.cpp b/lib/vfvalue.cpp index 2c1da06cfbc..6a1ba6f3b9d 100644 --- a/lib/vfvalue.cpp +++ b/lib/vfvalue.cpp @@ -26,27 +26,10 @@ namespace ValueFlow { Value::Value(const Token *c, long long val, Bound b) - : valueType(ValueType::INT), - bound(b), + : bound(b), intvalue(val), - tokvalue(nullptr), - floatValue(0.0), varvalue(val), - condition(c), - varId(0), - safe(false), - conditional(false), - macro(false), - defaultArg(false), - indirect(0), - moveKind(MoveKind::NonMovedVariable), - path(0), - wideintvalue(0), - subexpressions(), - capturetok(nullptr), - lifetimeKind(LifetimeKind::Object), - lifetimeScope(LifetimeScope::Local), - valueKind(ValueKind::Possible) { + condition(c) { errorPath.emplace_back(c, "Assuming that condition '" + c->expressionString() + "' is not redundant"); } diff --git a/lib/vfvalue.h b/lib/vfvalue.h index a32f86e990a..7f7089845a5 100644 --- a/lib/vfvalue.h +++ b/lib/vfvalue.h @@ -43,28 +43,11 @@ namespace ValueFlow using ErrorPath = std::list; enum class Bound { Upper, Lower, Point }; - explicit Value(long long val = 0, Bound b = Bound::Point) - : valueType(ValueType::INT), + explicit Value(long long val = 0, Bound b = Bound::Point) : bound(b), intvalue(val), - tokvalue(nullptr), - floatValue(0.0), varvalue(val), - condition(nullptr), - varId(0U), - safe(false), - conditional(false), - macro(false), - defaultArg(false), - indirect(0), - moveKind(MoveKind::NonMovedVariable), - path(0), - wideintvalue(val), - subexpressions(), - capturetok(nullptr), - lifetimeKind(LifetimeKind::Object), - lifetimeScope(LifetimeScope::Local), - valueKind(ValueKind::Possible) + wideintvalue(val) {} Value(const Token* c, long long val, Bound b = Bound::Point); @@ -220,7 +203,7 @@ namespace ValueFlow ITERATOR_START, ITERATOR_END, SYMBOLIC - } valueType; + } valueType = ValueType::INT; bool isIntValue() const { return valueType == ValueType::INT; } @@ -275,57 +258,57 @@ namespace ValueFlow } /** The value bound */ - Bound bound; + Bound bound = Bound::Point; /** int value (or sometimes bool value?) */ - long long intvalue; + long long intvalue{}; /** token value - the token that has the value. this is used for pointer aliases, strings, etc. */ - const Token *tokvalue; + const Token* tokvalue{}; /** float value */ - double floatValue; + double floatValue{}; /** For calculated values - variable value that calculated value depends on */ - long long varvalue; + long long varvalue{}; /** Condition that this value depends on */ - const Token *condition; + const Token* condition{}; ErrorPath errorPath; ErrorPath debugPath; /** For calculated values - varId that calculated value depends on */ - nonneg int varId; + nonneg int varId{}; /** value relies on safe checking */ - bool safe; + bool safe{}; /** Conditional value */ - bool conditional; + bool conditional{}; /** Value is is from an expanded macro */ - bool macro; + bool macro{}; /** Is this value passed as default parameter to the function? */ - bool defaultArg; + bool defaultArg{}; - int indirect; + int indirect{}; /** kind of moved */ - enum class MoveKind {NonMovedVariable, MovedVariable, ForwardedVariable} moveKind; + enum class MoveKind { NonMovedVariable, MovedVariable, ForwardedVariable } moveKind = MoveKind::NonMovedVariable; /** Path id */ - MathLib::bigint path; + MathLib::bigint path{}; /** int value before implicit truncation */ - long long wideintvalue; + long long wideintvalue{}; std::vector subexpressions; // Set to where a lifetime is captured by value - const Token* capturetok; + const Token* capturetok{}; enum class LifetimeKind { // Pointer points to a member of lifetime @@ -338,9 +321,9 @@ namespace ValueFlow Iterator, // A pointer that holds the address of the lifetime Address - } lifetimeKind; + } lifetimeKind = LifetimeKind::Object; - enum class LifetimeScope { Local, Argument, SubFunction, ThisPointer, ThisValue } lifetimeScope; + enum class LifetimeScope { Local, Argument, SubFunction, ThisPointer, ThisValue } lifetimeScope = LifetimeScope::Local; static const char* toString(MoveKind moveKind); static const char* toString(LifetimeKind lifetimeKind); @@ -357,7 +340,7 @@ namespace ValueFlow Inconclusive, /** Listed values are impossible */ Impossible - } valueKind; + } valueKind = ValueKind::Possible; void setKnown() { valueKind = ValueKind::Known; diff --git a/test/fixture.cpp b/test/fixture.cpp index 0f7c99bf398..64b1471c4f9 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -79,10 +79,7 @@ std::size_t TestFixture::todos_counter = 0; std::size_t TestFixture::succeeded_todos_counter = 0; TestFixture::TestFixture(const char * const _name) - : mVerbose(false), - exename(), - quiet_tests(false), - classname(_name) + : classname(_name) { TestRegistry::theInstance().addTest(this); } diff --git a/test/fixture.h b/test/fixture.h index dd8264c8cd5..2a3c26eca87 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -47,7 +47,7 @@ class TestFixture : public ErrorLogger { static std::size_t fails_counter; static std::size_t todos_counter; static std::size_t succeeded_todos_counter; - bool mVerbose; + bool mVerbose{}; std::string mTemplateFormat; std::string mTemplateLocation; std::string mTestname; @@ -55,7 +55,7 @@ class TestFixture : public ErrorLogger { protected: std::string exename; std::string testToRun; - bool quiet_tests; + bool quiet_tests{}; virtual void run() = 0; diff --git a/test/testtoken.cpp b/test/testtoken.cpp index f6c408ad03e..60f03db1a57 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -481,7 +481,7 @@ class TestToken : public TestFixture { } void deleteLast() const { - TokensFrontBack listEnds{ nullptr }; + TokensFrontBack listEnds; Token ** const tokensBack = &(listEnds.back); Token tok(&listEnds); tok.insertToken("aba"); @@ -491,7 +491,7 @@ class TestToken : public TestFixture { } void deleteFirst() const { - TokensFrontBack listEnds{ nullptr }; + TokensFrontBack listEnds; Token ** const tokensFront = &(listEnds.front); Token tok(&listEnds); From 09962a6bcffde1ec70cadbb86605de66068e81c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Pol=C3=A1=C4=8Dek?= Date: Tue, 8 Aug 2023 15:11:39 +0200 Subject: [PATCH 10/18] Edit verbose warning message for uninitVarError (#5301) I think that context needs to be provided as to why it is an issue that a variable is not initialized. --- lib/checkclass.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 781b04e2cea..662a6707619 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1055,12 +1055,9 @@ void CheckClass::initializeVarList(const Function &func, std::list Date: Tue, 8 Aug 2023 17:50:08 +0200 Subject: [PATCH 11/18] Restore references (#5303) --- lib/valueflow.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 2b2b7423efd..6f04d7ff6be 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4046,7 +4046,7 @@ struct LifetimeStore { update = true; } if (update && forward) - forwardLifetime(tok, &tokenlist, errorLogger, settings); + forwardLifetime(tok, tokenlist, errorLogger, settings); return update; } @@ -4141,7 +4141,7 @@ struct LifetimeStore { } } if (update && forward) - forwardLifetime(tok, &tokenlist, errorLogger, settings); + forwardLifetime(tok, tokenlist, errorLogger, settings); return update; } @@ -4218,14 +4218,14 @@ struct LifetimeStore { private: Context* mContext{}; - void forwardLifetime(Token* tok, TokenList* tokenlist, ErrorLogger* errorLogger, const Settings* settings) const { + void forwardLifetime(Token* tok, TokenList& tokenlist, ErrorLogger* errorLogger, const Settings* settings) const { if (mContext) { mContext->tok = tok; - mContext->tokenlist = tokenlist; + mContext->tokenlist = &tokenlist; mContext->errorLogger = errorLogger; mContext->settings = settings; } - valueFlowForwardLifetime(tok, *tokenlist, errorLogger, settings); + valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings); } }; From c3d7c91e88f8ac372640df20518bada0d5cd850c Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 8 Aug 2023 22:54:27 +0200 Subject: [PATCH 12/18] Additional call to setValueTypeInTokenList() (#5300) --- lib/symboldatabase.cpp | 7 ++----- lib/tokenize.cpp | 2 ++ test/testsymboldatabase.cpp | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 005d0dc2218..4712e646ec8 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3850,12 +3850,9 @@ void SymbolDatabase::printOut(const char *title) const } std::cout << " retType: " << func->retType << std::endl; - if (func->tokenDef->next()->valueType()) { - const ValueType * valueType = func->tokenDef->next()->valueType(); + if (const ValueType* valueType = func->tokenDef->next()->valueType()) { std::cout << " valueType: " << valueType << std::endl; - if (valueType) { - std::cout << " " << valueType->str() << std::endl; - } + std::cout << " " << valueType->str() << std::endl; } if (func->hasBody()) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 656db082f3f..1138285abf7 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -3339,8 +3339,10 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) if (mTimerResults) { Timer t("Tokenizer::simplifyTokens1::setValueType", mSettings->showtime, mTimerResults); + mSymbolDatabase->setValueTypeInTokenList(false); mSymbolDatabase->setValueTypeInTokenList(true); } else { + mSymbolDatabase->setValueTypeInTokenList(false); mSymbolDatabase->setValueTypeInTokenList(true); } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 4171f68a75c..3ca63283168 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -510,6 +510,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(auto17); // #11163 TEST_CASE(auto18); TEST_CASE(auto19); + TEST_CASE(auto20); TEST_CASE(unionWithConstructor); @@ -9437,6 +9438,22 @@ class TestSymbolDatabase : public TestFixture { } } + void auto20() { + GET_SYMBOL_DB("enum A { A0 };\n" + "enum B { B0 };\n" + "const int& g(A a);\n" + "const int& g(B b);\n" + "void f() {\n" + " const auto& r = g(B::B0);\n" + "}\n"); + const Token* a = Token::findsimplematch(tokenizer.tokens(), "auto"); + ASSERT(a && a->valueType()); + ASSERT_EQUALS(a->valueType()->type, ValueType::INT); + const Token* g = Token::findsimplematch(a, "g ( B ::"); + ASSERT(g && g->function()); + ASSERT_EQUALS(g->function()->tokenDef->linenr(), 4); + } + void unionWithConstructor() { GET_SYMBOL_DB("union Fred {\n" " Fred(int x) : i(x) { }\n" From 5ea1bca99fe4ba2342d747721b855766594ace7a Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Tue, 8 Aug 2023 22:55:55 +0200 Subject: [PATCH 13/18] Fix argument direction in windows.cfg, missing Qt macros (#5302) --- cfg/qt.cfg | 3 +++ cfg/windows.cfg | 18 +++++++++--------- test/cfg/windows.cpp | 4 ++++ 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cfg/qt.cfg b/cfg/qt.cfg index ee0d314ce9b..cae153acf1e 100644 --- a/cfg/qt.cfg +++ b/cfg/qt.cfg @@ -5097,6 +5097,9 @@ + + + diff --git a/cfg/windows.cfg b/cfg/windows.cfg index b4d4d003907..48c1e9f2f84 100644 --- a/cfg/windows.cfg +++ b/cfg/windows.cfg @@ -2960,7 +2960,7 @@ HFONT CreateFont( - + @@ -2985,7 +2985,7 @@ HFONT CreateFont( - + @@ -3023,7 +3023,7 @@ HFONT CreateFont( _In_ LPARAM lParam); --> false - + @@ -3044,7 +3044,7 @@ HFONT CreateFont( _In_ LPARAM lParam); --> false - + @@ -3306,7 +3306,7 @@ HFONT CreateFont( false - + @@ -3315,10 +3315,10 @@ HFONT CreateFont( false - + - + @@ -3327,7 +3327,7 @@ HFONT CreateFont( false - + @@ -3339,7 +3339,7 @@ HFONT CreateFont( false - + diff --git a/test/cfg/windows.cpp b/test/cfg/windows.cpp index e09e9f073a8..55eb21ecda2 100644 --- a/test/cfg/windows.cpp +++ b/test/cfg/windows.cpp @@ -1113,4 +1113,8 @@ void invalidPrintfArgType_StructMember(double d) { // #9672 my_struct_t my_struct; // cppcheck-suppress invalidPrintfArgType_sint my_struct.st.Format("%d", d); +} + +BOOL MyEnableWindow(HWND hWnd, BOOL bEnable) { + return EnableWindow(hWnd, bEnable); } \ No newline at end of file From f1749ab7adb5653d37cafa5bf59d11c1cc858447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Tue, 8 Aug 2023 22:58:02 +0200 Subject: [PATCH 14/18] CppcheckExecutor: use dedicated ErrorLogger for printing error messages XML (#4985) This starts to untangle the `ErrorLogger` implementation in `CppcheckExecutor` which handles three different cases and makes things unnecessarily complicated. --- cli/cppcheckexecutor.cpp | 26 ++++++++++++++++++-------- cli/cppcheckexecutor.h | 5 ----- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 38c365d17f8..eabf0582022 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -67,8 +67,23 @@ #include #endif -// TODO: do not directly write to stdout +class XMLErrorMessagesLogger : public ErrorLogger +{ + void reportOut(const std::string & outmsg, Color /*c*/ = Color::Reset) override + { + std::cout << outmsg << std::endl; + } + + void reportErr(const ErrorMessage &msg) override + { + reportOut(msg.toXML()); + } + + void reportProgress(const std::string & /*filename*/, const char /*stage*/[], const std::size_t /*value*/) override + {} +}; +// TODO: do not directly write to stdout /*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout; @@ -97,9 +112,9 @@ bool CppCheckExecutor::parseFromArgs(Settings &settings, int argc, const char* c } if (parser.getShowErrorMessages()) { - mShowAllErrors = true; + XMLErrorMessagesLogger xmlLogger; std::cout << ErrorMessage::getXMLHeader(settings.cppcheckCfgProductName); - CppCheck::getErrorMessages(*this); + CppCheck::getErrorMessages(xmlLogger); std::cout << ErrorMessage::getXMLFooter() << std::endl; } @@ -409,11 +424,6 @@ void CppCheckExecutor::reportProgress(const std::string &filename, const char st void CppCheckExecutor::reportErr(const ErrorMessage &msg) { - if (mShowAllErrors) { - reportOut(msg.toXML()); - return; - } - assert(mSettings != nullptr); // Alert only about unique errors diff --git a/cli/cppcheckexecutor.h b/cli/cppcheckexecutor.h index 9b73eb5d7e6..23e845e0e6f 100644 --- a/cli/cppcheckexecutor.h +++ b/cli/cppcheckexecutor.h @@ -180,11 +180,6 @@ class CppCheckExecutor : public ErrorLogger { * Error output */ std::ofstream* mErrorOutput{}; - - /** - * Has --errorlist been given? - */ - bool mShowAllErrors{}; }; #endif // CPPCHECKEXECUTOR_H From 037bed5b3c06d4254ebaf87dea5d7594290a08c8 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Tue, 8 Aug 2023 16:55:07 -0500 Subject: [PATCH 15/18] testrunner: fix clang compile error related to `dinit` (#5297) This fixes the compile error introduced in 5d201c4. --- test/helpers.h | 19 +++++++++---------- test/testprocessexecutor.cpp | 4 ++-- test/testsingleexecutor.cpp | 4 ++-- test/testthreadexecutor.cpp | 4 ++-- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/test/helpers.h b/test/helpers.h index 9699d6b1f84..113668141f3 100644 --- a/test/helpers.h +++ b/test/helpers.h @@ -106,17 +106,16 @@ class PreprocessorHelper #define dinit(T, ...) \ ([&] { T ${}; __VA_ARGS__; return $; }()) -#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__) -// work around Clang compilation error +// Default construct object to avoid bug in clang // error: default member initializer for 'y' needed within definition of enclosing class 'X' outside of member functions -// work around GCC compilation error -// error: default member initializer for ‘x::y::z’ required before the end of its enclosing class // see https://stackoverflow.com/questions/53408962 -#define DINIT_NOEXCEPT noexcept -#else -// work around GCC 4.8 compilation error -// error: function 'x()' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'x()' -#define DINIT_NOEXCEPT -#endif +struct make_default_obj +{ + template + operator T() const // NOLINT + { + return T{}; + } +}; #endif // helpersH diff --git a/test/testprocessexecutor.cpp b/test/testprocessexecutor.cpp index ecf9a5f070c..bda5f0a3cd4 100644 --- a/test/testprocessexecutor.cpp +++ b/test/testprocessexecutor.cpp @@ -48,7 +48,7 @@ class TestProcessExecutor : public TestFixture { struct CheckOptions { - CheckOptions() DINIT_NOEXCEPT = default; + CheckOptions() = default; SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; const char* plistOutput = nullptr; std::vector filesList; @@ -58,7 +58,7 @@ class TestProcessExecutor : public TestFixture { * Execute check using n jobs for y files which are have * identical data, given within data. */ - void check(unsigned int jobs, int files, int result, const std::string &data, const CheckOptions &opt = {}) { + void check(unsigned int jobs, int files, int result, const std::string &data, const CheckOptions& opt = make_default_obj{}) { errout.str(""); output.str(""); diff --git a/test/testsingleexecutor.cpp b/test/testsingleexecutor.cpp index 56e5e847823..f80530f82c4 100644 --- a/test/testsingleexecutor.cpp +++ b/test/testsingleexecutor.cpp @@ -63,7 +63,7 @@ class TestSingleExecutorBase : public TestFixture { struct CheckOptions { - CheckOptions() DINIT_NOEXCEPT = default; + CheckOptions() = default; SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; const char* plistOutput = nullptr; std::vector filesList; @@ -72,7 +72,7 @@ class TestSingleExecutorBase : public TestFixture { std::vector args; }; - void check(int files, int result, const std::string &data, const CheckOptions &opt = {}) { + void check(int files, int result, const std::string &data, const CheckOptions& opt = make_default_obj{}) { errout.str(""); output.str(""); settings.project.fileSettings.clear(); diff --git a/test/testthreadexecutor.cpp b/test/testthreadexecutor.cpp index 08cfccfda67..e05eff6d50a 100644 --- a/test/testthreadexecutor.cpp +++ b/test/testthreadexecutor.cpp @@ -48,7 +48,7 @@ class TestThreadExecutor : public TestFixture { struct CheckOptions { - CheckOptions() DINIT_NOEXCEPT = default; + CheckOptions() = default; SHOWTIME_MODES showtime = SHOWTIME_MODES::SHOWTIME_NONE; const char* plistOutput = nullptr; std::vector filesList; @@ -58,7 +58,7 @@ class TestThreadExecutor : public TestFixture { * Execute check using n jobs for y files which are have * identical data, given within data. */ - void check(unsigned int jobs, int files, int result, const std::string &data, const CheckOptions &opt = {}) { + void check(unsigned int jobs, int files, int result, const std::string &data, const CheckOptions& opt = make_default_obj{}) { errout.str(""); output.str(""); From 8166bfc7b823242c87b17cb62fac015e5720fa3c Mon Sep 17 00:00:00 2001 From: Maksim Derbasov Date: Wed, 9 Aug 2023 17:26:46 +0900 Subject: [PATCH 16/18] Do not crash on GUI shutdown (#5288) Seems current code for worker threads termination is too brutal which leads to crash on termination: ``` QThread::start: Thread termination error: No such process Segmentation fault (core dumped) ``` Seems better to use `quit()` and `wait()`, like in an example: https://doc.qt.io/qt-6/qthread.html#details tested: Ubuntu Linux 20 --- gui/checkthread.h | 6 ++++-- gui/threadhandler.cpp | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/gui/checkthread.h b/gui/checkthread.h index 9a1fea3e628..d74ec2514a9 100644 --- a/gui/checkthread.h +++ b/gui/checkthread.h @@ -24,6 +24,8 @@ #include "importproject.h" #include "suppressions.h" +#include + #include #include #include @@ -118,9 +120,9 @@ class CheckThread : public QThread { }; /** - * @brief Thread's current execution state. + * @brief Thread's current execution state. Can be changed from outside */ - State mState = Ready; + std::atomic mState{Ready}; ThreadResult &mResult; /** diff --git a/gui/threadhandler.cpp b/gui/threadhandler.cpp index 43faf2aea27..6e99afe0488 100644 --- a/gui/threadhandler.cpp +++ b/gui/threadhandler.cpp @@ -148,7 +148,10 @@ void ThreadHandler::setThreadCount(const int count) void ThreadHandler::removeThreads() { for (CheckThread* thread : mThreads) { - thread->terminate(); + if (thread->isRunning()) { + thread->terminate(); + thread->wait(); + } disconnect(thread, &CheckThread::done, this, &ThreadHandler::threadDone); disconnect(thread, &CheckThread::fileChecked, From 2502897265d4b0ee533e082d77d83f745142bc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Wed, 9 Aug 2023 12:43:55 +0200 Subject: [PATCH 17/18] avoid some redundant and unused settings in tests among other cleanups / added and used `WARN_UNUSED` attribute (#5284) --- lib/config.h | 7 +++++++ lib/settings.h | 2 +- test/fixture.cpp | 7 +++++++ test/fixture.h | 25 ++++++++++++++++++++++++- test/testbufferoverrun.cpp | 2 +- test/testclass.cpp | 2 +- test/testcondition.cpp | 6 +++--- test/testexceptionsafety.cpp | 4 ++-- test/testfunctions.cpp | 24 +++++++++++++----------- test/testleakautovar.cpp | 9 ++++----- test/testprocessexecutor.cpp | 9 +++++---- test/testsimplifytemplate.cpp | 2 +- test/testsimplifytokens.cpp | 9 ++++----- test/testsimplifytypedef.cpp | 8 +++----- test/testsimplifyusing.cpp | 5 +---- test/testsymboldatabase.cpp | 5 ++--- test/testtokenize.cpp | 12 +++++------- test/testvarid.cpp | 2 +- 18 files changed, 85 insertions(+), 55 deletions(-) diff --git a/lib/config.h b/lib/config.h index a0cbee51685..2f45debe005 100644 --- a/lib/config.h +++ b/lib/config.h @@ -79,6 +79,13 @@ # define UNUSED #endif +// warn_unused +#if (defined(__clang__) && (__clang_major__ >= 15)) +# define WARN_UNUSED [[gnu::warn_unused]] +#else +# define WARN_UNUSED +#endif + #define REQUIRES(msg, ...) class=typename std::enable_if<__VA_ARGS__::value>::type #include diff --git a/lib/settings.h b/lib/settings.h index 38c7111fbfb..ab27b1dbd4d 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -90,7 +90,7 @@ class SimpleEnableGroup { * to pass individual values to functions or constructors now or in the * future when we might have even more detailed settings. */ -class CPPCHECKLIB Settings { +class CPPCHECKLIB WARN_UNUSED Settings { private: /** @brief terminate checking */ diff --git a/test/fixture.cpp b/test/fixture.cpp index 64b1471c4f9..e332fbf7aaf 100644 --- a/test/fixture.cpp +++ b/test/fixture.cpp @@ -399,6 +399,8 @@ void TestFixture::setTemplateFormat(const std::string &templateFormat) } TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::library(const char lib[]) { + if (REDUNDANT_CHECK && std::find(settings.libraries.cbegin(), settings.libraries.cend(), lib) != settings.libraries.cend()) + throw std::runtime_error("redundant setting: libraries (" + std::string(lib) + ")"); // TODO: exename is not yet set LOAD_LIB_2_EXE(settings.library, lib, fixture.exename.c_str()); // strip extension @@ -414,6 +416,11 @@ TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::library(const char l TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::platform(cppcheck::Platform::Type type) { const std::string platformStr = cppcheck::Platform::toString(type); + + // TODO: the default platform differs between Windows and Linux + //if (REDUNDANT_CHECK && settings.platform.type == type) + // throw std::runtime_error("redundant setting: platform (" + platformStr + ")"); + std::string errstr; // TODO: exename is not yet set if (!settings.platform.set(platformStr, errstr, {fixture.exename})) diff --git a/test/fixture.h b/test/fixture.h index 2a3c26eca87..a09a193f0e6 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -130,7 +130,6 @@ class TestFixture : public ErrorLogger { check.runChecks(tokenizer, settings, errorLogger); } - // TODO: bail out on redundant settings class SettingsBuilder { public: @@ -138,41 +137,59 @@ class TestFixture : public ErrorLogger { SettingsBuilder(const TestFixture &fixture, Settings settings) : fixture(fixture), settings(std::move(settings)) {} SettingsBuilder& severity(Severity::SeverityType sev, bool b = true) { + if (REDUNDANT_CHECK && settings.severity.isEnabled(sev) == b) + throw std::runtime_error("redundant setting: severity"); settings.severity.setEnabled(sev, b); return *this; } SettingsBuilder& certainty(Certainty cert, bool b = true) { + if (REDUNDANT_CHECK && settings.certainty.isEnabled(cert) == b) + throw std::runtime_error("redundant setting: certainty"); settings.certainty.setEnabled(cert, b); return *this; } SettingsBuilder& clang() { + if (REDUNDANT_CHECK && settings.clang) + throw std::runtime_error("redundant setting: clang"); settings.clang = true; return *this; } SettingsBuilder& checkLibrary() { + if (REDUNDANT_CHECK && settings.checkLibrary) + throw std::runtime_error("redundant setting: checkLibrary"); settings.checkLibrary = true; return *this; } SettingsBuilder& checkUnusedTemplates(bool b = true) { + if (REDUNDANT_CHECK && settings.checkUnusedTemplates == b) + throw std::runtime_error("redundant setting: checkUnusedTemplates"); settings.checkUnusedTemplates = b; return *this; } SettingsBuilder& debugwarnings(bool b = true) { + if (REDUNDANT_CHECK && settings.debugwarnings == b) + throw std::runtime_error("redundant setting: debugwarnings"); settings.debugwarnings = b; return *this; } SettingsBuilder& c(Standards::cstd_t std) { + // TODO: CLatest and C11 are the same - handle differently + //if (REDUNDANT_CHECK && settings.standards.c == std) + // throw std::runtime_error("redundant setting: standards.c"); settings.standards.c = std; return *this; } SettingsBuilder& cpp(Standards::cppstd_t std) { + // TODO: CPPLatest and CPP20 are the same - handle differently + //if (REDUNDANT_CHECK && settings.standards.cpp == std) + // throw std::runtime_error("redundant setting: standards.cpp"); settings.standards.cpp = std; return *this; } @@ -184,11 +201,15 @@ class TestFixture : public ErrorLogger { SettingsBuilder& platform(cppcheck::Platform::Type type); SettingsBuilder& checkConfiguration() { + if (REDUNDANT_CHECK && settings.checkConfiguration) + throw std::runtime_error("redundant setting: checkConfiguration"); settings.checkConfiguration = true; return *this; } SettingsBuilder& checkHeaders(bool b = true) { + if (REDUNDANT_CHECK && settings.checkHeaders == b) + throw std::runtime_error("redundant setting: checkHeaders"); settings.checkHeaders = b; return *this; } @@ -199,6 +220,8 @@ class TestFixture : public ErrorLogger { private: const TestFixture &fixture; Settings settings; + + const bool REDUNDANT_CHECK = false; }; SettingsBuilder settingsBuilder() const { diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 97841f45a7c..862add41981 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -76,7 +76,7 @@ class TestBufferOverrun : public TestFixture { // Clear the error buffer.. errout.str(""); - const Settings settings = settingsBuilder(settings0).severity(Severity::style).severity(Severity::warning).severity(Severity::portability).severity(Severity::performance) + const Settings settings = settingsBuilder(settings0).severity(Severity::performance) .c(Standards::CLatest).cpp(Standards::CPPLatest).certainty(Certainty::inconclusive).build(); // Raw tokens.. diff --git a/test/testclass.cpp b/test/testclass.cpp index 430fb6c0984..b2a343a4446 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -39,7 +39,7 @@ class TestClass : public TestFixture { private: Settings settings0 = settingsBuilder().severity(Severity::style).library("std.cfg").build(); - Settings settings1 = settingsBuilder().severity(Severity::warning).library("std.cfg").build(); + const Settings settings1 = settingsBuilder().severity(Severity::warning).library("std.cfg").build(); void run() override { TEST_CASE(virtualDestructor1); // Base class not found => no error diff --git a/test/testcondition.cpp b/test/testcondition.cpp index b9a7d6e5c34..96212fef676 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -127,7 +127,7 @@ class TestCondition : public TestFixture { TEST_CASE(knownConditionIncrementLoop); // #9808 } - void check(const char code[], Settings &settings, const char* filename = "test.cpp") { + void check(const char code[], const Settings &settings, const char* filename = "test.cpp") { // Clear the error buffer.. errout.str(""); @@ -154,7 +154,7 @@ class TestCondition : public TestFixture { } void check(const char code[], const char* filename = "test.cpp", bool inconclusive = false) { - Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).build(); + const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).build(); check(code, settings, filename); } @@ -5645,7 +5645,7 @@ class TestCondition : public TestFixture { } void compareOutOfTypeRange() { - Settings settingsUnix64 = settingsBuilder().severity(Severity::style).platform(cppcheck::Platform::Type::Unix64).build(); + const Settings settingsUnix64 = settingsBuilder().severity(Severity::style).platform(cppcheck::Platform::Type::Unix64).build(); check("void f(unsigned char c) {\n" " if (c == 256) {}\n" diff --git a/test/testexceptionsafety.cpp b/test/testexceptionsafety.cpp index 274a895a6cb..97df8227547 100644 --- a/test/testexceptionsafety.cpp +++ b/test/testexceptionsafety.cpp @@ -63,7 +63,7 @@ class TestExceptionSafety : public TestFixture { // Clear the error buffer.. errout.str(""); - Settings settings1 = settingsBuilder(s ? *s : settings).certainty(Certainty::inconclusive, inconclusive).build(); + const Settings settings1 = settingsBuilder(s ? *s : settings).certainty(Certainty::inconclusive, inconclusive).build(); // Tokenize.. Tokenizer tokenizer(&settings1, this); @@ -397,7 +397,7 @@ class TestExceptionSafety : public TestFixture { ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:1]: (style, inconclusive) Unhandled exception specification when calling function f().\n" "[test.cpp:6] -> [test.cpp:1]: (style, inconclusive) Unhandled exception specification when calling function f().\n", errout.str()); - const Settings s = settingsBuilder(settings).library("gnu.cfg").build(); + const Settings s = settingsBuilder().library("gnu.cfg").build(); check(code, true, &s); ASSERT_EQUALS("", errout.str()); } diff --git a/test/testfunctions.cpp b/test/testfunctions.cpp index 418f3613078..9d895dcecba 100644 --- a/test/testfunctions.cpp +++ b/test/testfunctions.cpp @@ -1562,18 +1562,21 @@ class TestFunctions : public TestFixture { { const char code[] = "int main(void) {}"; - Settings s; + { + const Settings s = settingsBuilder().c(Standards::C89).build(); - s.standards.c = Standards::C89; - check(code, "test.c", &s); // c code (c89) - ASSERT_EQUALS("[test.c:1]: (error) Found an exit path from function with non-void return type that has missing return statement\n", errout.str()); + check(code, "test.c", &s); // c code (c89) + ASSERT_EQUALS("[test.c:1]: (error) Found an exit path from function with non-void return type that has missing return statement\n", errout.str()); + } - s.standards.c = Standards::C99; - check(code, "test.c", &s); // c code (c99) - ASSERT_EQUALS("", errout.str()); + { + const Settings s = settingsBuilder().c(Standards::C99).build(); + check(code, "test.c", &s); // c code (c99) + ASSERT_EQUALS("", errout.str()); - check(code, "test.cpp", &s); // c++ code - ASSERT_EQUALS("", errout.str()); + check(code, "test.cpp", &s); // c++ code + ASSERT_EQUALS("", errout.str()); + } } check("F(A,B) { x=1; }"); @@ -1825,9 +1828,8 @@ class TestFunctions : public TestFixture { } void checkLibraryMatchFunctions() { - Settings s = settingsBuilder(settings).checkLibrary().build(); + Settings s = settingsBuilder(settings).checkLibrary().debugwarnings().build(); s.daca = true; - s.debugwarnings = true; check("void f() {\n" " lib_func();" diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 11eca62d325..c5e2dca4fbd 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -474,7 +474,7 @@ class TestLeakAutoVar : public TestFixture { } void assign23() { - const Settings s = settingsBuilder(settings).library("posix.cfg").build(); + const Settings s = settingsBuilder().library("posix.cfg").build(); check("void f() {\n" " int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14;\n" " *&n1 = open(\"xx.log\", O_RDONLY);\n" @@ -2764,8 +2764,6 @@ class TestLeakAutoVar : public TestFixture { } void functionCallCastConfig() { // #9652 - Settings settingsFunctionCall = settings; - const char xmldata[] = "\n" "\n" " \n" @@ -2778,7 +2776,8 @@ class TestLeakAutoVar : public TestFixture { " \n" " \n" ""; - ASSERT(settingsFunctionCall.library.loadxmldata(xmldata, sizeof(xmldata))); + const Settings settingsFunctionCall = settingsBuilder(settings).libraryxml(xmldata, sizeof(xmldata)).build(); + check("void test_func()\n" "{\n" " char * buf = malloc(4);\n" @@ -2810,7 +2809,7 @@ class TestLeakAutoVar : public TestFixture { " \n" " \n" "\n"; - const Settings settingsLeakIgnore = settingsBuilder(settings).libraryxml(xmldata, sizeof(xmldata)).build(); + const Settings settingsLeakIgnore = settingsBuilder().libraryxml(xmldata, sizeof(xmldata)).build(); check("void f() {\n" " double* a = new double[1024];\n" " SomeClass::someMethod(a);\n" diff --git a/test/testprocessexecutor.cpp b/test/testprocessexecutor.cpp index bda5f0a3cd4..5bd701eab58 100644 --- a/test/testprocessexecutor.cpp +++ b/test/testprocessexecutor.cpp @@ -77,12 +77,13 @@ class TestProcessExecutor : public TestFixture { } } - settings.jobs = jobs; - settings.showtime = opt.showtime; + Settings s = settings; + s.jobs = jobs; + s.showtime = opt.showtime; if (opt.plistOutput) - settings.plistOutput = opt.plistOutput; + s.plistOutput = opt.plistOutput; // TODO: test with settings.project.fileSettings; - ProcessExecutor executor(filemap, settings, settings.nomsg, *this); + ProcessExecutor executor(filemap, s, s.nomsg, *this); std::vector> scopedfiles; scopedfiles.reserve(filemap.size()); for (std::map::const_iterator i = filemap.cbegin(); i != filemap.cend(); ++i) diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 92e66e36fdd..73b851991a3 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -38,7 +38,7 @@ class TestSimplifyTemplate : public TestFixture { private: // If there are unused templates, keep those - const Settings settings = settingsBuilder().severity(Severity::portability).checkUnusedTemplates().build(); + const Settings settings = settingsBuilder().severity(Severity::portability).build(); void run() override { TEST_CASE(template1); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 574e364e6bd..1e633a0f0b2 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -34,11 +34,10 @@ class TestSimplifyTokens : public TestFixture { private: - // If there are unused templates, keep those - const Settings settings0 = settingsBuilder().severity(Severity::portability).checkUnusedTemplates().build(); - const Settings settings1 = settingsBuilder().severity(Severity::style).checkUnusedTemplates().build(); - const Settings settings_std = settingsBuilder().library("std.cfg").checkUnusedTemplates().build(); - const Settings settings_windows = settingsBuilder().library("windows.cfg").severity(Severity::portability).checkUnusedTemplates().build(); + const Settings settings0 = settingsBuilder().severity(Severity::portability).build(); + const Settings settings1 = settingsBuilder().severity(Severity::style).build(); + const Settings settings_std = settingsBuilder().library("std.cfg").build(); + const Settings settings_windows = settingsBuilder().library("windows.cfg").severity(Severity::portability).build(); void run() override { TEST_CASE(combine_strings); diff --git a/test/testsimplifytypedef.cpp b/test/testsimplifytypedef.cpp index 55b3c085c0f..a87595e3e87 100644 --- a/test/testsimplifytypedef.cpp +++ b/test/testsimplifytypedef.cpp @@ -40,10 +40,8 @@ class TestSimplifyTypedef : public TestFixture { private: - // If there are unused templates, keep those - const Settings settings0 = settingsBuilder().severity(Severity::style).checkUnusedTemplates().build(); - const Settings settings1 = settingsBuilder().severity(Severity::portability).checkUnusedTemplates().build(); - const Settings settings2 = settingsBuilder().severity(Severity::style).checkUnusedTemplates().build(); + const Settings settings0 = settingsBuilder().severity(Severity::style).build(); + const Settings settings1 = settingsBuilder().severity(Severity::portability).build(); void run() override { TEST_CASE(c1); @@ -285,7 +283,7 @@ class TestSimplifyTypedef : public TestFixture { errout.str(""); // Tokenize.. // show warnings about unhandled typedef - const Settings settings = settingsBuilder(settings2).certainty(Certainty::inconclusive).debugwarnings().build(); + const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive).debugwarnings().build(); Tokenizer tokenizer(&settings, this); std::istringstream istr(code); ASSERT_LOC(tokenizer.tokenize(istr, "test.cpp"), file, line); diff --git a/test/testsimplifyusing.cpp b/test/testsimplifyusing.cpp index fb6c92bb9ce..32287681a7c 100644 --- a/test/testsimplifyusing.cpp +++ b/test/testsimplifyusing.cpp @@ -39,10 +39,7 @@ class TestSimplifyUsing : public TestFixture { private: - // If there are unused templates, keep those - const Settings settings0 = settingsBuilder().severity(Severity::style).checkUnusedTemplates().build(); - const Settings settings1 = settingsBuilder().checkUnusedTemplates().build(); - const Settings settings2 = settingsBuilder().severity(Severity::style).checkUnusedTemplates().build(); + const Settings settings0 = settingsBuilder().severity(Severity::style).build(); void run() override { TEST_CASE(simplifyUsing1); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 3ca63283168..13e719e46c6 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -68,9 +68,8 @@ class TestSymbolDatabase : public TestFixture { private: const Token* vartok{nullptr}; const Token* typetok{nullptr}; - // If there are unused templates, keep those - Settings settings1 = settingsBuilder().library("std.cfg").checkUnusedTemplates().build(); - const Settings settings2 = settingsBuilder().checkUnusedTemplates().platform(cppcheck::Platform::Type::Unspecified).build(); + Settings settings1 = settingsBuilder().library("std.cfg").build(); + const Settings settings2 = settingsBuilder().platform(cppcheck::Platform::Type::Unspecified).build(); void reset() { vartok = nullptr; diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 2e0972d07b8..e5814f6e5fc 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -44,11 +44,9 @@ class TestTokenizer : public TestFixture { TestTokenizer() : TestFixture("TestTokenizer") {} private: - // If there are unused templates, keep those - const Settings settings0 = settingsBuilder().library("qt.cfg").checkUnusedTemplates().build(); - const Settings settings1 = settingsBuilder().library("qt.cfg").library("std.cfg").checkUnusedTemplates().build(); - const Settings settings2 = settingsBuilder().library("qt.cfg").checkUnusedTemplates().build(); - const Settings settings_windows = settingsBuilder().library("windows.cfg").checkUnusedTemplates().build(); + const Settings settings0 = settingsBuilder().library("qt.cfg").build(); + const Settings settings1 = settingsBuilder().library("qt.cfg").library("std.cfg").build(); + const Settings settings_windows = settingsBuilder().library("windows.cfg").build(); void run() override { TEST_CASE(tokenize1); @@ -522,7 +520,7 @@ class TestTokenizer : public TestFixture { std::string tokenizeDebugListing_(const char* file, int line, const char code[], const char filename[] = "test.cpp") { errout.str(""); - const Settings settings = settingsBuilder(settings2).c(Standards::C89).cpp(Standards::CPP03).build(); + const Settings settings = settingsBuilder(settings0).c(Standards::C89).cpp(Standards::CPP03).build(); Tokenizer tokenizer(&settings, this); std::istringstream istr(code); @@ -946,7 +944,7 @@ class TestTokenizer : public TestFixture { } { - const Settings s = settingsBuilder().checkUnusedTemplates().build(); + const Settings s; ASSERT_EQUALS("; template < typename T , u_int uBAR = 0 >\n" "class Foo {\n" "public:\n" diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 90dfeafe604..341c24c2d9c 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -34,7 +34,7 @@ class TestVarID : public TestFixture { TestVarID() : TestFixture("TestVarID") {} private: - Settings settings = settingsBuilder().c(Standards::C89).cpp(Standards::CPPLatest).checkUnusedTemplates().platform(cppcheck::Platform::Type::Unix64).build(); + const Settings settings = settingsBuilder().c(Standards::C89).cpp(Standards::CPPLatest).platform(cppcheck::Platform::Type::Unix64).build(); void run() override { TEST_CASE(varid1); TEST_CASE(varid2); From 4e8c2401291eeeb7657e4bcdd0fec9049c415e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=B6neberg?= Date: Wed, 9 Aug 2023 12:45:15 +0200 Subject: [PATCH 18/18] updated CI to Clang 17 (#4797) --- .clang-tidy | 6 ++ .github/workflows/asan.yml | 6 +- .github/workflows/clang-tidy.yml | 10 +-- .github/workflows/tsan.yml | 6 +- .github/workflows/ubsan.yml | 6 +- clang-tidy.md | 141 +++++++++++++++++-------------- cmake/clang_tidy.cmake | 2 +- lib/tokenlist.cpp | 8 +- 8 files changed, 105 insertions(+), 80 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index fc451fb3c9a..e1bae2cd255 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -20,12 +20,15 @@ Checks: > -zircon-*, cert-err34-c, google-explicit-constructor, + cppcoreguidelines-rvalue-reference-param-not-moved, -bugprone-assignment-in-if-condition, -bugprone-branch-clone, -bugprone-easily-swappable-parameters, + -bugprone-empty-catch, -bugprone-macro-parentheses, -bugprone-narrowing-conversions, -bugprone-signed-char-misuse, + -bugprone-switch-missing-default-case, -bugprone-unchecked-optional-access, -clang-analyzer-*, -concurrency-mt-unsafe, @@ -36,6 +39,7 @@ Checks: > -misc-use-anonymous-namespace, -modernize-avoid-c-arrays, -modernize-deprecated-ios-base-aliases, + -misc-include-cleaner, -modernize-loop-convert, -modernize-raw-string-literal, -modernize-replace-auto-ptr, @@ -43,8 +47,10 @@ Checks: > -modernize-use-auto, -modernize-use-equals-default, -modernize-use-trailing-return-type, + -performance-avoid-endl, -performance-inefficient-string-concatenation, -performance-no-automatic-move, + -performance-noexcept-swap, -portability-simd-intrinsics, -portability-std-allocator-const, -readability-avoid-const-params-in-decls, diff --git a/.github/workflows/asan.yml b/.github/workflows/asan.yml index fdc029ad9f8..fe7c5a95a77 100644 --- a/.github/workflows/asan.yml +++ b/.github/workflows/asan.yml @@ -42,7 +42,7 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 16 + sudo ./llvm.sh 17 - name: Install Qt ${{ env.QT_VERSION }} if: false @@ -56,8 +56,8 @@ jobs: run: | cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_ADDRESS=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache env: - CC: clang-16 - CXX: clang++-16 + CC: clang-17 + CXX: clang++-17 - name: Build cppcheck run: | diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index c8546db9ab2..7bcd8bd8e31 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -30,8 +30,8 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 16 - sudo apt-get install -y clang-tidy-16 + sudo ./llvm.sh 17 + sudo apt-get install -y clang-tidy-17 - name: Install Qt ${{ env.QT_VERSION }} uses: jurplel/install-qt-action@v3 @@ -42,14 +42,14 @@ jobs: - name: Verify clang-tidy configuration run: | - clang-tidy-16 --verify-config + clang-tidy-17 --verify-config - name: Prepare CMake run: | cmake -S . -B cmake.output -G "Unix Makefiles" -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=On -DWITH_QCHART=On -DENABLE_CHECK_INTERNAL=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DCPPCHK_GLIBCXX_DEBUG=Off env: - CC: clang-16 - CXX: clang++-16 + CC: clang-17 + CXX: clang++-17 - name: Prepare CMake dependencies run: | diff --git a/.github/workflows/tsan.yml b/.github/workflows/tsan.yml index 5a5aaa2c900..6114817c194 100644 --- a/.github/workflows/tsan.yml +++ b/.github/workflows/tsan.yml @@ -42,7 +42,7 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 16 + sudo ./llvm.sh 17 - name: Install Qt ${{ env.QT_VERSION }} if: false @@ -56,8 +56,8 @@ jobs: run: | cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=Off -DWITH_QCHART=Off -DUSE_MATCHCOMPILER=Verify -DANALYZE_THREAD=On -DUSE_THREADS=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=Off -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache env: - CC: clang-16 - CXX: clang++-16 + CC: clang-17 + CXX: clang++-17 - name: Build cppcheck run: | diff --git a/.github/workflows/ubsan.yml b/.github/workflows/ubsan.yml index ed6d4e61f6c..3076801002e 100644 --- a/.github/workflows/ubsan.yml +++ b/.github/workflows/ubsan.yml @@ -42,7 +42,7 @@ jobs: sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 wget https://apt.llvm.org/llvm.sh chmod +x llvm.sh - sudo ./llvm.sh 16 + sudo ./llvm.sh 17 - name: Install Qt ${{ env.QT_VERSION }} uses: jurplel/install-qt-action@v3 @@ -55,8 +55,8 @@ jobs: run: | cmake -S . -B cmake.output -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHAVE_RULES=On -DBUILD_TESTS=On -DBUILD_GUI=ON -DWITH_QCHART=ON -DUSE_MATCHCOMPILER=Verify -DANALYZE_UNDEFINED=On -DENABLE_CHECK_INTERNAL=On -DUSE_BOOST=On -DCPPCHK_GLIBCXX_DEBUG=Off -DCMAKE_DISABLE_PRECOMPILE_HEADERS=On -DCMAKE_GLOBAL_AUTOGEN_TARGET=On -DDISABLE_DMAKE=On -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache env: - CC: clang-16 - CXX: clang++-16 + CC: clang-17 + CXX: clang++-17 - name: Build cppcheck run: | diff --git a/clang-tidy.md b/clang-tidy.md index 8d1de3c83aa..2311d2d3a97 100644 --- a/clang-tidy.md +++ b/clang-tidy.md @@ -8,156 +8,169 @@ We do not perform static analysis of the source of the external libraries. `simp ## Disabled Checks -`abseil-*`
-`altera-*`
-`android-*`
-`boost-*`
-`darwin-*`
-`fuchsia-*`
-`linuxkernel-*`
-`llvm-*`
-`llvmlibc-*`
-`mpi-*`
-`objc-*`
-`openmp-*`
-`zircon-*`
+`abseil-*`
+`altera-*`
+`android-*`
+`boost-*`
+`darwin-*`
+`fuchsia-*`
+`linuxkernel-*`
+`llvm-*`
+`llvmlibc-*`
+`mpi-*`
+`objc-*`
+`openmp-*`
+`zircon-*`
These are disabled since the platforms/libraries in question are not targeted by us. -`cert-*`
-`cppcoreguidelines-*`
-`google-*`
-`hicpp-*`
+`cert-*`
+`cppcoreguidelines-*`
+`google-*`
+`hicpp-*`
These are coding guidelines we do not follow. Some of the checks might be explicitly enabled though. -`readability-braces-around-statements`
-`readability-isolate-declaration`
-`modernize-use-trailing-return-type`
-`modernize-use-auto`
-`readability-uppercase-literal-suffix`
-`readability-else-after-return`
-`readability-identifier-length`
+`readability-braces-around-statements`
+`readability-isolate-declaration`
+`modernize-use-trailing-return-type`
+`modernize-use-auto`
+`readability-uppercase-literal-suffix`
+`readability-else-after-return`
+`readability-identifier-length`
These do not reflect the style we are (currently) enforcing. -`readability-function-size`
-`readability-function-cognitive-complexity`
+`readability-function-size`
+`readability-function-cognitive-complexity`
We are not interested in the size/complexity of a function. -`readability-magic-numbers`
+`readability-magic-numbers`
These do not (always) increase readability. -`bugprone-macro-parentheses`
+`bugprone-macro-parentheses`
To be documented. -`readability-implicit-bool-conversion`
+`readability-implicit-bool-conversion`
This does not appear to be useful as it is reported on very common code. -`bugprone-narrowing-conversions`
-`performance-no-automatic-move`
+`bugprone-narrowing-conversions`
+`performance-no-automatic-move`
It was decided not to apply these. -`modernize-use-equals-default`
-`modernize-loop-convert`
+`modernize-use-equals-default`
+`modernize-loop-convert`
These might change the behavior of code which might not be intended (need to file an upstream issue) -`modernize-raw-string-literal`
+`modernize-raw-string-literal`
This leads to a mismatch of raw string literals and regular ones and does reduce the readability. -`readability-convert-member-functions-to-static`
+`readability-convert-member-functions-to-static`
Disabled because of false positives with Qt `slot` methods (see https://github.com/llvm/llvm-project/issues/57520). -`-clang-analyzer-*`
+`-clang-analyzer-*`
Disabled because of false positives (needs to file an upstream bug report). -`misc-non-private-member-variables-in-classes`
+`misc-non-private-member-variables-in-classes`
We intentionally use this. -`misc-no-recursion`
+`misc-no-recursion`
Leads to lots of "false positives". This seem to enforce a coding guidelines of certain codebases. -`readability-use-anyofallof`
+`readability-use-anyofallof`
We currently don't even apply our own `useStlAlgorithm` findings. -`bugprone-easily-swappable-parameters`
+`bugprone-easily-swappable-parameters`
This produces a lot of noise and they are not fixable that easily. -`readability-container-data-pointer`
+`readability-container-data-pointer`
Disable because of false positives and inconsistent warnings (need to file an upstream bug report). -`misc-const-correctness`
+`misc-const-correctness`
Work in progress. -`bugprone-assignment-in-if-condition`
+`bugprone-assignment-in-if-condition`
Is reported for valid patterns we are using. -`readability-suspicious-call-argument`
+`readability-suspicious-call-argument`
Produces a lot of false positives since it is too vague in its analysis. -`performance-inefficient-string-concatenation`
+`performance-inefficient-string-concatenation`
Produces warnings which might be considered false positives starting with C++11 - see https://github.com/llvm/llvm-project/issues/54526. -`readability-redundant-access-specifiers`
+`readability-redundant-access-specifiers`
Reports warning with the Qt ` slots:` syntax in class declarations - see https://github.com/llvm/llvm-project/issues/60055. -`modernize-avoid-c-arrays`
+`modernize-avoid-c-arrays`
Produces warnings when `const char[]` is being used which is quite common in our code. Does not make sense to enable before C++17 when `std::string_view` becomes available. Also reports a false positive about templates which deduce the array length: https://github.com/llvm/llvm-project/issues/60053. -`readability-container-size-empty`
-`bugprone-branch-clone`
-`readability-const-return-type`
-`modernize-return-braced-init-list`
-`misc-throw-by-value-catch-by-reference`
-`readability-avoid-const-params-in-decls`
-`bugprone-signed-char-misuse`
-`readability-redundant-access-specifiers`
-`concurrency-mt-unsafe`
-`misc-use-anonymous-namespace`
+`misc-include-cleaner`
-To be evaluated. +We run this separately via `clang-include-cleaner` in the `iwyu.yml` workflow as the findings of the include checkers still need to be reviewed manually before applying them. -`portability-std-allocator-const`
+`readability-container-size-empty`
+`bugprone-branch-clone`
+`readability-const-return-type`
+`modernize-return-braced-init-list`
+`misc-throw-by-value-catch-by-reference`
+`readability-avoid-const-params-in-decls`
+`bugprone-signed-char-misuse`
+`readability-redundant-access-specifiers`
+`concurrency-mt-unsafe`
+`misc-use-anonymous-namespace`
+`performance-avoid-endl`
+`performance-noexcept-swap`
+`bugprone-switch-missing-default-case`
+`bugprone-empty-catch`
+ +To be evaluated (need to remove exclusion). + +`cppcoreguidelines-missing-std-forward`
+`cppcoreguidelines-avoid-const-or-ref-data-members`
+ +To be evaluated (need to enable explicitly). + +`portability-std-allocator-const`
Only necessary for code which is exclusively compiled with `libc++`. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. -`modernize-deprecated-ios-base-aliases`
+`modernize-deprecated-ios-base-aliases`
Warns about aliases which are removed in C++20. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. -`bugprone-unchecked-optional-access`
+`bugprone-unchecked-optional-access`
We are not using any `optional` implementation. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. -`modernize-replace-auto-ptr`
+`modernize-replace-auto-ptr`
Still available until C++17. It is unlikely such code will ever be introduced. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. -`readability-identifier-naming`
+`readability-identifier-naming`
We are currently using our own `naming.json` to enforce naming schemes. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. -`portability-simd-intrinsics`
+`portability-simd-intrinsics`
We are not using SIMD instructions and it suggests to use `std::experiemental::` features which might not be commonly available. Also disabled for performance reasons - see https://github.com/llvm/llvm-project/issues/57527#issuecomment-1237935132. diff --git a/cmake/clang_tidy.cmake b/cmake/clang_tidy.cmake index 07134ddaa9d..679c14cdb1b 100644 --- a/cmake/clang_tidy.cmake +++ b/cmake/clang_tidy.cmake @@ -9,7 +9,7 @@ if (NOT CMAKE_DISABLE_PRECOMPILE_HEADERS) message(STATUS "Cannot use non-Clang compiler with clang-tidy when precompiled headers are enabled - skipping 'run-clang-tidy' target generation") endif() else() - set(RUN_CLANG_TIDY_NAMES run-clang-tidy run-clang-tidy-16 run-clang-tidy-15 run-clang-tidy-14 run-clang-tidy-13 run-clang-tidy-12 run-clang-tidy-11 run-clang-tidy-10 run-clang-tidy-9 run-clang-tidy-8) + set(RUN_CLANG_TIDY_NAMES run-clang-tidy run-clang-tidy-17 run-clang-tidy-16 run-clang-tidy-15 run-clang-tidy-14 run-clang-tidy-13 run-clang-tidy-12 run-clang-tidy-11 run-clang-tidy-10 run-clang-tidy-9 run-clang-tidy-8) endif() if (RUN_CLANG_TIDY_NAMES) diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 2e023d54841..31077d831f5 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -330,10 +330,15 @@ bool TokenList::createTokens(std::istream &code, const std::string& file0) //--------------------------------------------------------------------------- +// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved) void TokenList::createTokens(simplecpp::TokenList&& tokenList) { - if (tokenList.cfront()) + if (tokenList.cfront()) { + // this is a copy + // TODO: the same as TokenList.files - move that instead + // TODO: this points to mFiles when called from createTokens(std::istream &, const std::string&) mOrigFiles = mFiles = tokenList.cfront()->location.files; + } else mFiles.clear(); @@ -341,6 +346,7 @@ void TokenList::createTokens(simplecpp::TokenList&& tokenList) for (const simplecpp::Token *tok = tokenList.cfront(); tok;) { + // TODO: move from TokenList std::string str = tok->str(); // Float literal