From 4ceb24630d11fe66ee57169e934a8247312ee25a Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 9 Apr 2015 21:01:47 +0200 Subject: [PATCH] Fixed #6568: Scope for template class member function missing in symboldatabase --- lib/symboldatabase.cpp | 29 +++++++++++++++++++++++------ test/testnullpointer.cpp | 16 ++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 409cc058c..8261fca01 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1301,7 +1301,6 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const (tok->previous()->isName() || tok->strAt(-1) == ">" || tok->strAt(-1) == "&" || tok->strAt(-1) == "*" || // Either a return type in front of tok tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok outerScope->isClassOrStruct())) { // or a ctor/dtor - const Token* tok1 = tok->previous(); // skip over destructor "~" @@ -1312,6 +1311,8 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const while (Token::simpleMatch(tok1, "::")) { if (Token::Match(tok1->tokAt(-1), "%name%")) tok1 = tok1->tokAt(-2); + else if (tok1->strAt(-1) == ">" && tok1->linkAt(-1) && Token::Match(tok1->linkAt(-1)->previous(), "%name%")) + tok1 = tok1->linkAt(-1)->tokAt(-2); else tok1 = tok1->tokAt(-1); } @@ -1717,6 +1718,8 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To // skip class/struct name if (destructor) tok1 = (*tok)->tokAt(-3); + else if ((*tok)->strAt(-2) == ">" && (*tok)->linkAt(-2)) + tok1 = (*tok)->linkAt(-2)->previous(); else tok1 = (*tok)->tokAt(-2); @@ -1730,11 +1733,25 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To // back up to head of path while (tok1 && tok1->previous() && tok1->previous()->str() == "::" && - tok1->tokAt(-2) && tok1->tokAt(-2)->isName()) { - path = tok1->str() + " :: " + path; - tok1 = tok1->tokAt(-2); - count++; - path_length++; + tok1->tokAt(-2) && (tok1->tokAt(-2)->isName() || (tok1->strAt(-2) == ">" && tok1->linkAt(-2)))) { + if (tok1->strAt(-2) == ">") { + tok1 = tok1->tokAt(-2); + const Token * tok2 = tok1->previous(); + path = ":: " + path; + if (tok2) { + do { + path = tok1->str() + " " + path; + tok1 = tok1->previous(); + count++; + path_length++; + } while (tok1 != tok2); + } + } else { + path = tok1->str() + " :: " + path; + tok1 = tok1->tokAt(-2); + count++; + path_length++; + } } if (tok1 && count) { diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index e126a9d10..e19bb59f9 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -69,6 +69,7 @@ private: TEST_CASE(nullpointer24); // #5082 fp: chained assignment TEST_CASE(nullpointer25); // #5061 TEST_CASE(nullpointer26); // #3589 + TEST_CASE(nullpointer27); // #6568 TEST_CASE(nullpointer_addressOf); // address of TEST_CASE(nullpointerSwitch); // #2626 TEST_CASE(nullpointer_cast); // #4692 @@ -1280,6 +1281,21 @@ private: ASSERT_EQUALS("", errout.str()); } + void nullpointer27() { // #6568 + check("template\n" + "class Foo {\n" + " Foo& operator = ( Type* );\n" + "};\n" + "template\n" + "Foo& Foo::operator = ( Type* pointer_ ) {\n" + " pointer_=NULL;\n" + " *pointer_=0;\n" + " return *this;\n" + "}", false, "test.cpp", false); + ASSERT_EQUALS("[test.cpp:8]: (error) Possible null pointer dereference: pointer_\n" + "[test.cpp:8]: (error) Null pointer dereference\n", errout.str()); + } + void nullpointer_addressOf() { // address of check("void f() {\n" " struct X *x = 0;\n"