* Format * Fix #11016 FP unusedStructMember when used through iterator (regression) * Format * Fix test * Format * Nullptr check
This commit is contained in:
parent
f644938eb0
commit
457a0cff87
|
@ -1205,14 +1205,23 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
|
|||
{
|
||||
VarIdMap varIds;
|
||||
|
||||
auto setMemberVar = [&](const Variable* membervar, Token* membertok, const Token* vartok) -> void {
|
||||
if (membervar) {
|
||||
membertok->variable(membervar);
|
||||
if (vartok && (membertok->varId() == 0 || mVariableList[membertok->varId()] == nullptr))
|
||||
fixVarId(varIds, vartok, membertok, membervar);
|
||||
}
|
||||
};
|
||||
|
||||
// Set variable pointers
|
||||
for (const Token* tok = mTokenizer->list.front(); tok != mTokenizer->list.back(); tok = tok->next()) {
|
||||
if (tok->varId())
|
||||
const_cast<Token *>(tok)->variable(getVariableFromVarId(tok->varId()));
|
||||
const_cast<Token*>(tok)->variable(getVariableFromVarId(tok->varId()));
|
||||
|
||||
// Set Token::variable pointer for array member variable
|
||||
// Since it doesn't point at a fixed location it doesn't have varid
|
||||
const bool isVar = tok->variable() && (tok->variable()->typeScope() || tok->variable()->isSmartPointer() || (tok->valueType() && tok->valueType()->type == ValueType::CONTAINER));
|
||||
const bool isVar = tok->variable() && (tok->variable()->typeScope() || tok->variable()->isSmartPointer() ||
|
||||
(tok->valueType() && (tok->valueType()->type == ValueType::CONTAINER || tok->valueType()->type == ValueType::ITERATOR)));
|
||||
const bool isArrayAccess = isVar && Token::simpleMatch(tok->astParent(), "[");
|
||||
const bool isDirectAccess = isVar && !isArrayAccess && Token::simpleMatch(tok->astParent(), ".");
|
||||
const bool isDerefAccess = isVar && !isDirectAccess && Token::simpleMatch(tok->astParent(), "*") && Token::simpleMatch(tok->astParent()->astParent(), ".");
|
||||
|
@ -1247,19 +1256,11 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
|
|||
const Variable *var = tok->variable();
|
||||
if (var->typeScope()) {
|
||||
const Variable *membervar = var->typeScope()->getVariable(membertok->str());
|
||||
if (membervar) {
|
||||
membertok->variable(membervar);
|
||||
if (membertok->varId() == 0 || mVariableList[membertok->varId()] == nullptr)
|
||||
fixVarId(varIds, tok, const_cast<Token *>(membertok), membervar);
|
||||
}
|
||||
setMemberVar(membervar, membertok, tok);
|
||||
} else if (const ::Type *type = var->smartPointerType()) {
|
||||
const Scope *classScope = type->classScope;
|
||||
const Variable *membervar = classScope ? classScope->getVariable(membertok->str()) : nullptr;
|
||||
if (membervar) {
|
||||
membertok->variable(membervar);
|
||||
if (membertok->varId() == 0 || mVariableList[membertok->varId()] == nullptr)
|
||||
fixVarId(varIds, tok, const_cast<Token *>(membertok), membervar);
|
||||
}
|
||||
setMemberVar(membervar, membertok, tok);
|
||||
} else if (tok->valueType() && tok->valueType()->type == ValueType::CONTAINER) {
|
||||
if (Token::Match(var->typeStartToken(), "std :: %type% < %name%")) {
|
||||
const Token* type2tok = var->typeStartToken()->tokAt(4);
|
||||
|
@ -1268,13 +1269,14 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
|
|||
const Type* type2 = type2tok ? type2tok->type() : nullptr;
|
||||
if (type2 && type2->classScope && type2->classScope->definedType) {
|
||||
const Variable *membervar = type2->classScope->getVariable(membertok->str());
|
||||
if (membervar) {
|
||||
membertok->variable(membervar);
|
||||
if (membertok->varId() == 0 || mVariableList[membertok->varId()] == nullptr)
|
||||
fixVarId(varIds, tok, const_cast<Token *>(membertok), membervar);
|
||||
}
|
||||
setMemberVar(membervar, membertok, tok);
|
||||
}
|
||||
}
|
||||
} else if (const Type* iterType = var->iteratorType()) {
|
||||
if (iterType->classScope && iterType->classScope->definedType) {
|
||||
const Variable *membervar = iterType->classScope->getVariable(membertok->str());
|
||||
setMemberVar(membervar, membertok, tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1296,13 +1298,7 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
|
|||
if (!membervar) {
|
||||
if (type->classScope) {
|
||||
membervar = type->classScope->getVariable(membertok->str());
|
||||
if (membervar) {
|
||||
membertok->variable(membervar);
|
||||
if (membertok->varId() == 0 || mVariableList[membertok->varId()] == nullptr) {
|
||||
if (tok->function()->retDef)
|
||||
fixVarId(varIds, tok->function()->retDef, const_cast<Token *>(membertok), membervar);
|
||||
}
|
||||
}
|
||||
setMemberVar(membervar, membertok, tok->function()->retDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2262,6 +2258,17 @@ const Type *Variable::smartPointerType() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const Type* Variable::iteratorType() const
|
||||
{
|
||||
if (!mValueType || mValueType->type != ValueType::ITERATOR)
|
||||
return nullptr;
|
||||
|
||||
if (mValueType->containerTypeToken)
|
||||
return mValueType->containerTypeToken->type();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string Variable::getTypeName() const
|
||||
{
|
||||
std::string ret;
|
||||
|
|
|
@ -593,7 +593,8 @@ public:
|
|||
return getFlag(fIsSmartPointer);
|
||||
}
|
||||
|
||||
const Type *smartPointerType() const;
|
||||
const Type* smartPointerType() const;
|
||||
const Type* iteratorType() const;
|
||||
|
||||
/**
|
||||
* Checks if the variable is of any of the STL types passed as arguments ('std::')
|
||||
|
|
|
@ -1556,7 +1556,7 @@ private:
|
|||
void returnReference25()
|
||||
{
|
||||
check("int& f();\n" // #10983
|
||||
" auto g() -> decltype(f()) {\n"
|
||||
"auto g() -> decltype(f()) {\n"
|
||||
" return f();\n"
|
||||
"}\n"
|
||||
"int& h() {\n"
|
||||
|
@ -2252,7 +2252,7 @@ private:
|
|||
" return &it->foo;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS(
|
||||
"[test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning object that points to local variable 'v' that will be invalid when returning.\n",
|
||||
"[test.cpp:3] -> [test.cpp:4] -> [test.cpp:2] -> [test.cpp:4]: (error) Returning pointer to local variable 'v' that will be invalid when returning.\n",
|
||||
errout.str());
|
||||
|
||||
check("auto f(std::vector<int> x) {\n"
|
||||
|
|
|
@ -361,6 +361,7 @@ private:
|
|||
TEST_CASE(symboldatabase98); // #10451
|
||||
TEST_CASE(symboldatabase99); // #10864
|
||||
TEST_CASE(symboldatabase100); // #10174
|
||||
TEST_CASE(symboldatabase101);
|
||||
|
||||
TEST_CASE(createSymbolDatabaseFindAllScopes1);
|
||||
TEST_CASE(createSymbolDatabaseFindAllScopes2);
|
||||
|
@ -4974,6 +4975,19 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
void symboldatabase101() {
|
||||
GET_SYMBOL_DB("struct A { bool b; };\n"
|
||||
"void f(const std::vector<A>& v) {\n"
|
||||
" std::vector<A>::const_iterator it = b.begin();\n"
|
||||
" if (it->b) {}\n"
|
||||
"}\n");
|
||||
ASSERT(db);
|
||||
const Token* it = Token::findsimplematch(tokenizer.tokens(), "it . b");
|
||||
ASSERT(it);
|
||||
ASSERT(it->tokAt(2));
|
||||
ASSERT(it->tokAt(2)->variable());
|
||||
}
|
||||
|
||||
void createSymbolDatabaseFindAllScopes1() {
|
||||
GET_SYMBOL_DB("void f() { union {int x; char *p;} a={0}; }");
|
||||
ASSERT(db->scopeList.size() == 3);
|
||||
|
|
|
@ -69,6 +69,7 @@ private:
|
|||
TEST_CASE(structmember19); // #10826, #10848, #10852
|
||||
TEST_CASE(structmember20); // #10737
|
||||
TEST_CASE(structmember21); // #4759
|
||||
TEST_CASE(structmember22); // #11016
|
||||
|
||||
TEST_CASE(localvar1);
|
||||
TEST_CASE(localvar2);
|
||||
|
@ -1796,6 +1797,15 @@ private:
|
|||
errout.str());
|
||||
}
|
||||
|
||||
void structmember22() { // #11016
|
||||
checkStructMemberUsage("struct A { bool b; };\n"
|
||||
"void f(const std::vector<A>& v) {\n"
|
||||
" std::vector<A>::const_iterator it = b.begin();\n"
|
||||
" if (it->b) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void functionVariableUsage_(const char* file, int line, const char code[], const char filename[] = "test.cpp") {
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
|
Loading…
Reference in New Issue