Fixed #4698 (False positive: Uninitialized member variable warning with confusing namespaces)

This commit is contained in:
Daniel Marjamäki 2016-01-30 14:04:48 +01:00
parent f3f9ea2d09
commit 0e89620212
3 changed files with 49 additions and 21 deletions

View File

@ -2959,7 +2959,7 @@ static const Token* skipPointers(const Token* tok)
return tok; return tok;
} }
bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const bool Scope::isVariableDeclaration(const Token* const tok, const Token*& vartok, const Token*& typetok) const
{ {
if (check && check->_tokenizer->isCPP() && Token::Match(tok, "throw|new")) if (check && check->_tokenizer->isCPP() && Token::Match(tok, "throw|new"))
return false; return false;
@ -3023,31 +3023,48 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
for (type = typeList.begin(); type != typeList.end(); ++type) { for (type = typeList.begin(); type != typeList.end(); ++type) {
// do the names match? // do the names match?
if (type->name() == typeTok->str()) { if (type->name() != typeTok->str())
// check if type does not have a namespace continue;
if (typeTok->strAt(-1) != "::") {
const Scope *parent = start;
// check if in same namespace // check if type does not have a namespace
while (parent) { if (typeTok->strAt(-1) != "::") {
// out of line class function belongs to class const Scope *parent = start;
if (parent->type == Scope::eFunction && parent->functionOf)
parent = parent->functionOf;
else if (parent != type->enclosingScope)
parent = parent->nestedIn;
else
break;
}
if (type->enclosingScope == parent) // check if in same namespace
return &(*type); while (parent) {
// out of line class function belongs to class
if (parent->type == Scope::eFunction && parent->functionOf)
parent = parent->functionOf;
else if (parent != type->enclosingScope)
parent = parent->nestedIn;
else
break;
} }
// type has a namespace if (type->enclosingScope == parent)
else {
// FIXME check if namespace path matches supplied path
return &(*type); return &(*type);
}
// type has a namespace
else {
bool match = true;
const Scope *scope = type->enclosingScope;
const Token *typeTok2 = typeTok->tokAt(-2);
while (match && scope && Token::Match(typeTok2, "%any% ::")) {
// A::B..
if (typeTok2->isName() && typeTok2->str().find(":") == std::string::npos) {
match &= bool(scope->className == typeTok2->str());
typeTok2 = typeTok2->tokAt(-2);
scope = scope->nestedIn;
} else {
// ::A..
match &= bool(scope->type == Scope::eGlobal);
break;
}
} }
if (match)
return &(*type);
} }
} }

View File

@ -953,7 +953,7 @@ private:
* @param typetok populated with pointer to the type token, if found * @param typetok populated with pointer to the type token, if found
* @return true if tok points to a variable declaration, false otherwise * @return true if tok points to a variable declaration, false otherwise
*/ */
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const; bool isVariableDeclaration(const Token* const tok, const Token*& vartok, const Token*& typetok) const;
void findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const; void findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const;
}; };

View File

@ -181,6 +181,7 @@ private:
TEST_CASE(namespaces1); TEST_CASE(namespaces1);
TEST_CASE(namespaces2); TEST_CASE(namespaces2);
TEST_CASE(namespaces3); // #3854 - unknown macro TEST_CASE(namespaces3); // #3854 - unknown macro
TEST_CASE(namespaces4);
TEST_CASE(tryCatch1); TEST_CASE(tryCatch1);
@ -1537,6 +1538,16 @@ private:
ASSERT_EQUALS(Scope::eNamespace, db->scopeList.back().type); ASSERT_EQUALS(Scope::eNamespace, db->scopeList.back().type);
} }
void namespaces4() { // #4698 - type lookup
GET_SYMBOL_DB("struct A { int a; };\n"
"namespace fred { struct A {}; }\n"
"fred::A fredA;");
const Variable *fredA = db->getVariableFromVarId(2U);
ASSERT_EQUALS("fredA", fredA->name());
const Type *fredAType = fredA->type();
ASSERT_EQUALS(2U, fredAType->classDef->linenr());
}
void tryCatch1() { void tryCatch1() {
const char str[] = "void foo() {\n" const char str[] = "void foo() {\n"
" try { }\n" " try { }\n"