Fix #11497 debug: CheckClass::isMemberVar found used member variable 'x' with varid 0 (inconclusive) (#4736)

This commit is contained in:
chrchr-github 2023-01-26 22:19:51 +01:00 committed by GitHub
parent a0f51d1e21
commit b5a06d045e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 20 deletions

View File

@ -2173,6 +2173,9 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) const
} }
} while (again); } while (again);
if (tok->isKeyword() || tok->isStandardType())
return false;
for (const Variable& var : scope->varlist) { for (const Variable& var : scope->varlist) {
if (var.name() == tok->str()) { if (var.name() == tok->str()) {
if (Token::Match(tok, "%name% ::")) if (Token::Match(tok, "%name% ::"))

View File

@ -1208,6 +1208,8 @@ void SymbolDatabase::fixVarId(VarIdMap & varIds, const Token * vartok, Token * m
membertok->varId(memberId->second); membertok->varId(memberId->second);
} }
static bool isContainerYieldElement(Library::Container::Yield yield);
void SymbolDatabase::createSymbolDatabaseSetVariablePointers() void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
{ {
VarIdMap varIds; VarIdMap varIds;
@ -1222,6 +1224,8 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
// Set variable pointers // Set variable pointers
for (const Token* tok = mTokenizer->list.front(); tok != mTokenizer->list.back(); tok = tok->next()) { for (const Token* tok = mTokenizer->list.front(); tok != mTokenizer->list.back(); tok = tok->next()) {
if (!tok->isName() || tok->isKeyword() || tok->isStandardType())
continue;
if (tok->varId()) if (tok->varId())
const_cast<Token*>(tok)->variable(getVariableFromVarId(tok->varId())); const_cast<Token*>(tok)->variable(getVariableFromVarId(tok->varId()));
@ -1310,6 +1314,16 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
} }
} }
} }
else if (Token::simpleMatch(tok->astParent(), ".") && tok->next()->str() == "(" &&
astIsContainer(tok->astParent()->astOperand1()) && Token::Match(tok->next()->link(), ") . %name% !!(")) {
const ValueType* vt = tok->astParent()->astOperand1()->valueType();
const Library::Container* cont = vt->container;
auto it = cont->functions.find(tok->str());
if (it != cont->functions.end() && isContainerYieldElement(it->second.yield) && vt->containerTypeToken && vt->containerTypeToken->scope()) {
Token* memberTok = tok->next()->link()->tokAt(2);
setMemberVar(vt->containerTypeToken->scope()->getVariable(memberTok->str()), memberTok, vt->containerTypeToken);
}
}
} }
} }
@ -6052,7 +6066,7 @@ static void setAutoTokenProperties(Token * const autoTok)
autoTok->isStandardType(true); autoTok->isStandardType(true);
} }
static bool isContainerYieldElement(Library::Container::Yield yield) bool isContainerYieldElement(Library::Container::Yield yield)
{ {
return yield == Library::Container::Yield::ITEM || yield == Library::Container::Yield::AT_INDEX || return yield == Library::Container::Yield::ITEM || yield == Library::Container::Yield::AT_INDEX ||
yield == Library::Container::Yield::BUFFER || yield == Library::Container::Yield::BUFFER_NT; yield == Library::Container::Yield::BUFFER || yield == Library::Container::Yield::BUFFER_NT;

View File

@ -32,9 +32,15 @@ struct InternalError;
class TestVarID : public TestFixture { class TestVarID : public TestFixture {
public: public:
TestVarID() : TestFixture("TestVarID") {} TestVarID() : TestFixture("TestVarID") {
settings.platform(Settings::Unix64);
settings.standards.c = Standards::C89;
settings.standards.cpp = Standards::CPPLatest;
settings.checkUnusedTemplates = true;
}
private: private:
Settings settings;
void run() override { void run() override {
TEST_CASE(varid1); TEST_CASE(varid1);
TEST_CASE(varid2); TEST_CASE(varid2);
@ -137,6 +143,7 @@ private:
TEST_CASE(varid_in_class22); // #10872 TEST_CASE(varid_in_class22); // #10872
TEST_CASE(varid_in_class23); // #11293 TEST_CASE(varid_in_class23); // #11293
TEST_CASE(varid_in_class24); TEST_CASE(varid_in_class24);
TEST_CASE(varid_in_class25);
TEST_CASE(varid_namespace_1); // #7272 TEST_CASE(varid_namespace_1); // #7272
TEST_CASE(varid_namespace_2); // #7000 TEST_CASE(varid_namespace_2); // #7000
TEST_CASE(varid_namespace_3); // #8627 TEST_CASE(varid_namespace_3); // #8627
@ -235,12 +242,6 @@ private:
std::string tokenize_(const char* file, int line, const char code[], const char filename[] = "test.cpp") { std::string tokenize_(const char* file, int line, const char code[], const char filename[] = "test.cpp") {
errout.str(""); errout.str("");
Settings settings;
settings.platform(Settings::Unix64);
settings.standards.c = Standards::C89;
settings.standards.cpp = Standards::CPPLatest;
settings.checkUnusedTemplates = true;
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
std::istringstream istr(code); std::istringstream istr(code);
ASSERT_LOC((tokenizer.tokenize)(istr, filename), file, line); ASSERT_LOC((tokenizer.tokenize)(istr, filename), file, line);
@ -255,12 +256,6 @@ private:
std::string tokenizeExpr_(const char* file, int line, const char code[], const char filename[] = "test.cpp") { std::string tokenizeExpr_(const char* file, int line, const char code[], const char filename[] = "test.cpp") {
errout.str(""); errout.str("");
Settings settings;
settings.platform(Settings::Unix64);
settings.standards.c = Standards::C89;
settings.standards.cpp = Standards::CPPLatest;
settings.checkUnusedTemplates = true;
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
std::istringstream istr(code); std::istringstream istr(code);
ASSERT_LOC((tokenizer.tokenize)(istr, filename), file, line); ASSERT_LOC((tokenizer.tokenize)(istr, filename), file, line);
@ -275,12 +270,6 @@ private:
std::string compareVaridsForVariable_(const char* file, int line, const char code[], const char varname[], const char filename[] = "test.cpp") { std::string compareVaridsForVariable_(const char* file, int line, const char code[], const char varname[], const char filename[] = "test.cpp") {
errout.str(""); errout.str("");
Settings settings;
settings.platform(Settings::Unix64);
settings.standards.c = Standards::C89;
settings.standards.cpp = Standards::CPP11;
settings.checkUnusedTemplates = true;
Tokenizer tokenizer(&settings, this); Tokenizer tokenizer(&settings, this);
std::istringstream istr(code); std::istringstream istr(code);
ASSERT_LOC((tokenizer.tokenize)(istr, filename), file, line); ASSERT_LOC((tokenizer.tokenize)(istr, filename), file, line);
@ -2015,6 +2004,27 @@ private:
ASSERT_EQUALS(expected, tokenize(code, "test.cpp")); ASSERT_EQUALS(expected, tokenize(code, "test.cpp"));
} }
void varid_in_class25() { // #11497
const char *code{}, *expected{};
Settings oldSettings = settings;
LOAD_LIB_2(settings.library, "std.cfg");
code = "struct F {\n"
" int i;\n"
" void f(const std::vector<F>&v) {\n"
" if (v.front().i) {}\n"
" }\n"
"};\n";
expected = "1: struct F {\n"
"2: int i@1 ;\n"
"3: void f ( const std :: vector < F > & v@2 ) {\n"
"4: if ( v@2 . front ( ) . i@3 ) { }\n"
"5: }\n"
"6: } ;\n";
ASSERT_EQUALS(expected, tokenize(code, "test.cpp"));
settings = oldSettings;
}
void varid_namespace_1() { // #7272 void varid_namespace_1() { // #7272
const char code[] = "namespace Blah {\n" const char code[] = "namespace Blah {\n"
" struct foo { int x;};\n" " struct foo { int x;};\n"