From 0e89620212f0e42f255f0caacaf4da70ad0881a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 30 Jan 2016 14:04:48 +0100 Subject: [PATCH] Fixed #4698 (False positive: Uninitialized member variable warning with confusing namespaces) --- lib/symboldatabase.cpp | 57 ++++++++++++++++++++++++------------- lib/symboldatabase.h | 2 +- test/testsymboldatabase.cpp | 11 +++++++ 3 files changed, 49 insertions(+), 21 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 7ee98ca8b..ce92a4aa3 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2959,7 +2959,7 @@ static const Token* skipPointers(const Token* 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")) return false; @@ -3023,31 +3023,48 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty for (type = typeList.begin(); type != typeList.end(); ++type) { // do the names match? - if (type->name() == typeTok->str()) { - // check if type does not have a namespace - if (typeTok->strAt(-1) != "::") { - const Scope *parent = start; + if (type->name() != typeTok->str()) + continue; - // check if in same namespace - 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; - } + // check if type does not have a namespace + if (typeTok->strAt(-1) != "::") { + const Scope *parent = start; - if (type->enclosingScope == parent) - return &(*type); + // check if in same namespace + 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 - else { - // FIXME check if namespace path matches supplied path + if (type->enclosingScope == parent) 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); } } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index ef50ca3a8..e5930f5e7 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -953,7 +953,7 @@ private: * @param typetok populated with pointer to the type token, if found * @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 & matches) const; }; diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index ca739c5cd..a955e44a7 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -181,6 +181,7 @@ private: TEST_CASE(namespaces1); TEST_CASE(namespaces2); TEST_CASE(namespaces3); // #3854 - unknown macro + TEST_CASE(namespaces4); TEST_CASE(tryCatch1); @@ -1537,6 +1538,16 @@ private: 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() { const char str[] = "void foo() {\n" " try { }\n"