Fix #11497 debug: CheckClass::isMemberVar found used member variable 'x' with varid 0 (inconclusive) (#4736)
This commit is contained in:
parent
a0f51d1e21
commit
b5a06d045e
|
@ -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% ::"))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Reference in New Issue