Fixed #11102 (False positive: unreadVariable when union in derived struct is used)
This commit is contained in:
parent
ca9747cf7d
commit
2a81388c95
|
@ -1002,24 +1002,24 @@ void SymbolDatabase::createSymbolDatabaseVariableSymbolTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill in missing variables if possible
|
// fill in missing variables if possible
|
||||||
const std::size_t functions = functionScopes.size();
|
for (const Scope *func: functionScopes) {
|
||||||
for (std::size_t i = 0; i < functions; ++i) {
|
|
||||||
const Scope *func = functionScopes[i];
|
|
||||||
for (const Token *tok = func->bodyStart->next(); tok && tok != func->bodyEnd; tok = tok->next()) {
|
for (const Token *tok = func->bodyStart->next(); tok && tok != func->bodyEnd; tok = tok->next()) {
|
||||||
// check for member variable
|
// check for member variable
|
||||||
if (tok->varId() && tok->next() &&
|
if (!Token::Match(tok, "%var% .|["))
|
||||||
(tok->next()->str() == "." ||
|
continue;
|
||||||
(tok->next()->str() == "[" && tok->linkAt(1)->strAt(1) == "."))) {
|
const Token* tokDot = tok->next();
|
||||||
const Token *tok1 = tok->next()->str() == "." ? tok->tokAt(2) : tok->linkAt(1)->tokAt(2);
|
while (Token::simpleMatch(tokDot, "["))
|
||||||
if (tok1 && tok1->varId() && mVariableList[tok1->varId()] == nullptr) {
|
tokDot = tokDot->link()->next();
|
||||||
const Variable *var = mVariableList[tok->varId()];
|
if (!Token::Match(tokDot, ". %var%"))
|
||||||
if (var && var->typeScope()) {
|
continue;
|
||||||
// find the member variable of this variable
|
const Token *member = tokDot->next();
|
||||||
const Variable *var1 = var->typeScope()->getVariable(tok1->str());
|
if (mVariableList[member->varId()] == nullptr) {
|
||||||
if (var1) {
|
const Variable *var1 = mVariableList[tok->varId()];
|
||||||
// add this variable to the look up table
|
if (var1 && var1->typeScope()) {
|
||||||
mVariableList[tok1->varId()] = var1;
|
const Variable* memberVar = var1->typeScope()->getVariable(member->str());
|
||||||
}
|
if (memberVar) {
|
||||||
|
// add this variable to the look up table
|
||||||
|
mVariableList[member->varId()] = memberVar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4442,7 +4442,6 @@ void Scope::getVariableList(const Settings* settings, const Token* start, const
|
||||||
|
|
||||||
// Is it a function?
|
// Is it a function?
|
||||||
else if (tok->str() == "{") {
|
else if (tok->str() == "{") {
|
||||||
|
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4614,13 +4613,18 @@ const Token *Scope::checkVariable(const Token *tok, AccessControl varaccess, con
|
||||||
|
|
||||||
const Variable *Scope::getVariable(const std::string &varname) const
|
const Variable *Scope::getVariable(const std::string &varname) const
|
||||||
{
|
{
|
||||||
std::list<Variable>::const_iterator iter;
|
for (const Variable& var: varlist) {
|
||||||
|
if (var.name() == varname)
|
||||||
for (iter = varlist.begin(); iter != varlist.end(); ++iter) {
|
return &var;
|
||||||
if (iter->name() == varname)
|
}
|
||||||
return &*iter;
|
if (definedType) {
|
||||||
|
for (const Type::BaseInfo& baseInfo: definedType->derivedFrom) {
|
||||||
|
if (baseInfo.type && baseInfo.type->classScope) {
|
||||||
|
if (const Variable* var = baseInfo.type->classScope->getVariable(varname))
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,7 +352,7 @@ private:
|
||||||
ASSERT_EQUALS("lib/", s.includePaths.front());
|
ASSERT_EQUALS("lib/", s.includePaths.front());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ignorePaths() {
|
void ignorePaths() const {
|
||||||
ImportProject::FileSettings fs1, fs2;
|
ImportProject::FileSettings fs1, fs2;
|
||||||
fs1.filename = "foo/bar";
|
fs1.filename = "foo/bar";
|
||||||
fs2.filename = "qwe/rty";
|
fs2.filename = "qwe/rty";
|
||||||
|
|
|
@ -184,6 +184,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(rangeBasedFor);
|
TEST_CASE(rangeBasedFor);
|
||||||
|
|
||||||
|
TEST_CASE(memberVar1);
|
||||||
TEST_CASE(arrayMemberVar1);
|
TEST_CASE(arrayMemberVar1);
|
||||||
TEST_CASE(arrayMemberVar2);
|
TEST_CASE(arrayMemberVar2);
|
||||||
TEST_CASE(arrayMemberVar3);
|
TEST_CASE(arrayMemberVar3);
|
||||||
|
@ -1417,6 +1418,22 @@ private:
|
||||||
ASSERT_EQUALS("signed int *", c->valueType()->str());
|
ASSERT_EQUALS("signed int *", c->valueType()->str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memberVar1() {
|
||||||
|
GET_SYMBOL_DB("struct Foo {\n"
|
||||||
|
" int x;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct Bar : public Foo {};\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" struct Bar bar;\n"
|
||||||
|
" bar.x = 123;\n" // <- x should get a variable() pointer
|
||||||
|
"}");
|
||||||
|
|
||||||
|
ASSERT(db != nullptr);
|
||||||
|
const Token *tok = Token::findsimplematch(tokenizer.tokens(), "x =");
|
||||||
|
ASSERT(tok->variable());
|
||||||
|
ASSERT(Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;"));
|
||||||
|
}
|
||||||
|
|
||||||
void arrayMemberVar1() {
|
void arrayMemberVar1() {
|
||||||
GET_SYMBOL_DB("struct Foo {\n"
|
GET_SYMBOL_DB("struct Foo {\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
|
|
Loading…
Reference in New Issue