diff --git a/lib/checkuninitvar.cpp b/lib/checkuninitvar.cpp index 4ff956518..579594ec6 100644 --- a/lib/checkuninitvar.cpp +++ b/lib/checkuninitvar.cpp @@ -50,7 +50,7 @@ namespace { //--------------------------------------------------------------------------- -static bool isSizeOfEtc(const Token *tok) +bool isSizeOfEtc(const Token *tok) { return Token::Match(tok, "sizeof|typeof|offsetof|decltype|__typeof__ ("); } diff --git a/lib/forwardanalyzer.cpp b/lib/forwardanalyzer.cpp index bdf648110..d050f84e3 100644 --- a/lib/forwardanalyzer.cpp +++ b/lib/forwardanalyzer.cpp @@ -12,6 +12,8 @@ #include #include +bool isSizeOfEtc(const Token *tok); + struct OnExit { std::function f; @@ -192,8 +194,16 @@ struct ForwardTraversal { Progress update(Token* tok) { Analyzer::Action action = analyzer->analyze(tok, Analyzer::Direction::Forward); actions |= action; - if (!action.isNone() && !analyzeOnly) + if (!action.isNone() && !analyzeOnly) { analyzer->update(tok, action, Analyzer::Direction::Forward); + + // uninit value => skip further analysis + auto v = std::find_if(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isUninitValue)); + if (v != tok->values().end()) { + if (Token::Match(tok->astParent(), "[,(]") && !isSizeOfEtc(tok->astParent()->previous())) + return Break(Analyzer::Terminate::Modified); + } + } if (action.isInconclusive() && !analyzer->lowerToInconclusive()) return Break(Analyzer::Terminate::Inconclusive); if (action.isInvalid()) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 12366df42..04f347782 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -120,6 +120,7 @@ private: TEST_CASE(valueFlowSameExpression); TEST_CASE(valueFlowUninit); + TEST_CASE(valueFlowUninitBreak); TEST_CASE(valueFlowConditionExpressions); @@ -4651,6 +4652,35 @@ private: ASSERT_EQUALS(0, values.size()); } + void valueFlowUninitBreak() { // break uninit analysis to avoid extra warnings + const char *code; + std::list values; + + code = "struct wcsstruct {\n" + " int *wcsprm;\n" + "};\n" + "\n" + "void copy_wcs(wcsstruct *wcsin) {\n" + " wcsstruct *x;\n" + " memcpy(wcsin, x, sizeof(wcsstruct));\n" // <- True positive + " x->wcsprm = NULL;\n" // <- False positive + "}"; + values = tokenValues(code, "x . wcsprm", ValueFlow::Value::ValueType::UNINIT); + ASSERT_EQUALS(0, values.size()); + + code = "struct wcsstruct {\n" + " int *wcsprm;\n" + "};\n" + "\n" + "void copy_wcs(wcsstruct *wcsin) {\n" + " wcsstruct *x;\n" + " sizeof(x);\n" + " x->wcsprm = NULL;\n" // <- Warn + "}"; + values = tokenValues(code, "x . wcsprm", ValueFlow::Value::ValueType::UNINIT); + ASSERT_EQUALS(1, values.size()); + } + void valueFlowConditionExpressions() { const char* code;