diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index e648252df..52d2ee51b 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -80,6 +80,15 @@ static const Token *getAstParentSkipPossibleCastAndAddressOf(const Token *vartok return parent; } +bool CheckUninitVar::diag(const Token* tok) +{ + if (!tok) + return true; + while (Token::Match(tok->astParent(), "*|&|.")) + tok = tok->astParent(); + return !mUninitDiags.insert(tok).second; +} + void CheckUninitVar::check() { const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); @@ -1496,12 +1505,21 @@ void CheckUninitVar::uninitdataError(const Token *tok, const std::string &varnam void CheckUninitVar::uninitvarError(const Token *tok, const std::string &varname, ErrorPath errorPath) { + if (diag(tok)) + return; errorPath.emplace_back(tok, ""); - reportError(errorPath, Severity::error, "uninitvar", "$symbol:" + varname + "\nUninitialized variable: $symbol", CWE_USE_OF_UNINITIALIZED_VARIABLE, Certainty::normal); + reportError(errorPath, + Severity::error, + "legacyUninitvar", + "$symbol:" + varname + "\nUninitialized variable: $symbol", + CWE_USE_OF_UNINITIALIZED_VARIABLE, + Certainty::normal); } void CheckUninitVar::uninitvarError(const Token* tok, const ValueFlow::Value& v) { + if (diag(tok)) + return; const Token* ltok = tok; if (tok && Token::simpleMatch(tok->astParent(), ".") && astIsRHS(tok)) ltok = tok->astParent(); @@ -1666,10 +1684,6 @@ void CheckUninitVar::valueFlowUninit() ids.insert(tok->exprId()); if (v->tokvalue) ids.insert(v->tokvalue->exprId()); - const Token* nextTok = nextAfterAstRightmostLeaf(parent); - if (nextTok == scope->bodyEnd) - break; - tok = nextTok ? nextTok : tok; } } } diff --git a/lib/checkuninitvar.h b/lib/checkuninitvar.h index ef9c2c766..efa93a4a1 100644 --- a/lib/checkuninitvar.h +++ b/lib/checkuninitvar.h @@ -71,10 +71,11 @@ public: /** @brief Run checks against the normal token list */ void runChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) override { CheckUninitVar checkUninitVar(tokenizer, settings, errorLogger); - checkUninitVar.check(); checkUninitVar.valueFlowUninit(); + checkUninitVar.check(); } + bool diag(const Token* tok); /** Check for uninitialized variables */ void check(); void checkScope(const Scope* scope, const std::set &arrayTypeDefs); @@ -131,10 +132,12 @@ public: void uninitStructMemberError(const Token *tok, const std::string &membername); private: - Check::FileInfo *getFileInfo() const; - bool isUnsafeFunction(const Scope *scope, int argnr, const Token **tok) const; + std::set mUninitDiags; + Check::FileInfo* getFileInfo() const; + bool isUnsafeFunction(const Scope* scope, int argnr, const Token** tok) const; - void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const override { + void getErrorMessages(ErrorLogger* errorLogger, const Settings* settings) const override + { CheckUninitVar c(nullptr, settings, errorLogger); ValueFlow::Value v{}; diff --git a/releasenotes.txt b/releasenotes.txt index 6281c4c30..dc4903f05 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -14,3 +14,4 @@ release notes for cppcheck-2.8 - Improvements to unreadVariable - Detect more instances of C style casts - Warn if the return value of new is discarded +- The pre-ValueFlow uninitialized checker now uses a different ID as legacyUninitvar