Remove duplicate uninit warnings (#3478)
This commit is contained in:
parent
eb50d19657
commit
2ca2abdf0e
2
Makefile
2
Makefile
|
@ -515,7 +515,7 @@ $(libcppdir)/errortypes.o: lib/errortypes.cpp lib/config.h lib/errortypes.h
|
|||
$(libcppdir)/exprengine.o: lib/exprengine.cpp lib/astutils.h lib/bughuntingchecks.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/exprengine.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/exprengine.o $(libcppdir)/exprengine.cpp
|
||||
|
||||
$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/analyzer.h lib/astutils.h lib/check.h lib/checknullpointer.h lib/color.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h
|
||||
$(libcppdir)/forwardanalyzer.o: lib/forwardanalyzer.cpp lib/analyzer.h lib/astutils.h lib/config.h lib/errortypes.h lib/forwardanalyzer.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h lib/valueptr.h
|
||||
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/forwardanalyzer.o $(libcppdir)/forwardanalyzer.cpp
|
||||
|
||||
$(libcppdir)/importproject.o: lib/importproject.cpp externals/picojson/picojson.h externals/tinyxml2/tinyxml2.h lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
|
||||
|
|
|
@ -1508,57 +1508,70 @@ void CheckUninitVar::valueFlowUninit()
|
|||
{
|
||||
const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
|
||||
|
||||
// check every executable scope
|
||||
for (const Scope *scope : symbolDatabase->functionScopes) {
|
||||
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
|
||||
if (isSizeOfEtc(tok)) {
|
||||
tok = tok->linkAt(1);
|
||||
continue;
|
||||
std::unordered_set<nonneg int> ids;
|
||||
for (bool subfunction : {false, true}) {
|
||||
// check every executable scope
|
||||
for (const Scope* scope : symbolDatabase->functionScopes) {
|
||||
for (const Token* tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) {
|
||||
if (isSizeOfEtc(tok)) {
|
||||
tok = tok->linkAt(1);
|
||||
continue;
|
||||
}
|
||||
if (ids.count(tok->exprId()) > 0)
|
||||
continue;
|
||||
if (!tok->variable() && !tok->isUnaryOp("*"))
|
||||
continue;
|
||||
if (Token::Match(tok, "%name% ("))
|
||||
continue;
|
||||
const Token* parent = tok->astParent();
|
||||
while (Token::simpleMatch(parent, "."))
|
||||
parent = parent->astParent();
|
||||
if (parent && parent->isUnaryOp("&"))
|
||||
continue;
|
||||
if (isVoidCast(parent))
|
||||
continue;
|
||||
auto v = std::find_if(
|
||||
tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isUninitValue));
|
||||
if (v == tok->values().end())
|
||||
continue;
|
||||
if (v->tokvalue && ids.count(v->tokvalue->exprId()) > 0)
|
||||
continue;
|
||||
if (subfunction == (v->path == 0))
|
||||
continue;
|
||||
if (v->isInconclusive())
|
||||
continue;
|
||||
if (v->indirect > 1 || v->indirect < 0)
|
||||
continue;
|
||||
bool uninitderef = false;
|
||||
if (tok->variable()) {
|
||||
bool unknown;
|
||||
const bool isarray = !tok->variable() || tok->variable()->isArray();
|
||||
const bool ispointer = astIsPointer(tok) && !isarray;
|
||||
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
||||
if (ispointer && v->indirect == 1 && !deref)
|
||||
continue;
|
||||
if (isarray && !deref)
|
||||
continue;
|
||||
uninitderef = deref && v->indirect == 0;
|
||||
const bool isleaf = isLeafDot(tok) || uninitderef;
|
||||
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
||||
continue;
|
||||
}
|
||||
if (!(Token::Match(tok->astParent(), ". %name% (") && uninitderef) &&
|
||||
isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
||||
continue;
|
||||
bool inconclusive = false;
|
||||
if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive)
|
||||
continue;
|
||||
uninitvarError(tok, tok->expressionString(), v->errorPath);
|
||||
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;
|
||||
}
|
||||
if (!tok->variable() && !tok->isUnaryOp("*"))
|
||||
continue;
|
||||
if (Token::Match(tok, "%name% ("))
|
||||
continue;
|
||||
const Token* parent = tok->astParent();
|
||||
while (Token::simpleMatch(parent, "."))
|
||||
parent = parent->astParent();
|
||||
if (parent && parent->isUnaryOp("&"))
|
||||
continue;
|
||||
if (isVoidCast(parent))
|
||||
continue;
|
||||
auto v = std::find_if(tok->values().begin(), tok->values().end(), std::mem_fn(&ValueFlow::Value::isUninitValue));
|
||||
if (v == tok->values().end())
|
||||
continue;
|
||||
if (v->isInconclusive())
|
||||
continue;
|
||||
if (v->indirect > 1 || v->indirect < 0)
|
||||
continue;
|
||||
bool uninitderef = false;
|
||||
if (tok->variable()) {
|
||||
bool unknown;
|
||||
const bool isarray = !tok->variable() || tok->variable()->isArray();
|
||||
const bool ispointer = astIsPointer(tok) && !isarray;
|
||||
const bool deref = CheckNullPointer::isPointerDeRef(tok, unknown, mSettings);
|
||||
if (ispointer && v->indirect == 1 && !deref)
|
||||
continue;
|
||||
if (isarray && !deref)
|
||||
continue;
|
||||
uninitderef = deref && v->indirect == 0;
|
||||
const bool isleaf = isLeafDot(tok) || uninitderef;
|
||||
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
||||
continue;
|
||||
}
|
||||
if (!(Token::Match(tok->astParent(), ". %name% (") && uninitderef) &&
|
||||
isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
||||
continue;
|
||||
bool inconclusive = false;
|
||||
if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive)
|
||||
continue;
|
||||
uninitvarError(tok, tok->expressionString(), v->errorPath);
|
||||
const Token* nextTok = nextAfterAstRightmostLeaf(parent);
|
||||
if (nextTok == scope->bodyEnd)
|
||||
break;
|
||||
tok = nextTok ? nextTok : tok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "symboldatabase.h"
|
||||
#include "token.h"
|
||||
#include "valueptr.h"
|
||||
#include "checknullpointer.h" // UninitValue => isPointerDeref
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
|
@ -193,21 +192,8 @@ 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 (tok->valueType() && tok->valueType()->pointer > 0) {
|
||||
bool unknown = false;
|
||||
if (CheckNullPointer::isPointerDeRef(tok, unknown, settings))
|
||||
return Break(Analyzer::Terminate::Modified);
|
||||
}
|
||||
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())
|
||||
|
|
|
@ -4563,8 +4563,7 @@ private:
|
|||
" arc << p;\n" // <- TODO initialization?
|
||||
" return *p;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: p\n"
|
||||
"[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: p\n", errout.str());
|
||||
|
||||
// #4320
|
||||
valueFlowUninit("void f() {\n"
|
||||
|
@ -4572,9 +4571,7 @@ private:
|
|||
" a << 1;\n"
|
||||
" return a;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n"
|
||||
"[test.cpp:4]: (error) Uninitialized variable: a\n",
|
||||
errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
|
||||
|
||||
// #9750
|
||||
valueFlowUninit("struct S {\n"
|
||||
|
|
Loading…
Reference in New Issue