Fixed #4386 (False positive: ctor not detected)

This commit is contained in:
Robert Reif 2012-12-05 20:31:17 +01:00 committed by Daniel Marjamäki
parent b99d3f0767
commit 63b585424d
3 changed files with 55 additions and 4 deletions

View File

@ -54,7 +54,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// find all scopes // find all scopes
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
// Locate next class // Locate next class
if (Token::Match(tok, "class|struct|union|namespace ::| %var% {|:|::")) { if (Token::Match(tok, "class|struct|union|namespace ::| %var% {|:|::") &&
tok->strAt(-1) != "friend") {
const Token *tok2 = tok->tokAt(2); const Token *tok2 = tok->tokAt(2);
if (tok->strAt(1) == "::") if (tok->strAt(1) == "::")
@ -429,10 +430,25 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
} }
// friend class declaration? // friend class declaration?
else if (Token::Match(tok, "friend class| %any% ;")) { else if (Token::Match(tok, "friend class| ::| %any% ;|::")) {
Scope::FriendInfo friendInfo; Scope::FriendInfo friendInfo;
friendInfo.name = tok->strAt(1) == "class" ? tok->strAt(2) : tok->strAt(1); // save the name start
friendInfo.nameStart = tok->strAt(1) == "class" ? tok->tokAt(2) : tok->tokAt(1);
friendInfo.nameEnd = friendInfo.nameStart;
// skip leading "::"
if (friendInfo.nameEnd->str() == "::")
friendInfo.nameEnd = friendInfo.nameEnd->next();
// skip qualification "name ::"
while (friendInfo.nameEnd && friendInfo.nameEnd->strAt(1) == "::")
friendInfo.nameEnd = friendInfo.nameEnd->tokAt(2);
// save the name
if (friendInfo.nameEnd)
friendInfo.name = friendInfo.nameEnd->str();
// fill this in after parsing is complete // fill this in after parsing is complete
friendInfo.scope = 0; friendInfo.scope = 0;
@ -641,7 +657,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
for (std::list<Scope::FriendInfo>::iterator i = it->friendList.begin(); i != it->friendList.end(); ++i) { for (std::list<Scope::FriendInfo>::iterator i = it->friendList.begin(); i != it->friendList.end(); ++i) {
for (std::list<Scope>::iterator j = scopeList.begin(); j != scopeList.end(); ++j) { for (std::list<Scope>::iterator j = scopeList.begin(); j != scopeList.end(); ++j) {
// check scope for match // check scope for match
scope = const_cast<Scope*>(j->findQualifiedScope(i->name)); scope = findScope(i->nameStart, it->nestedIn);
// found match? // found match?
if (scope && scope->isClassOrStruct()) { if (scope && scope->isClassOrStruct()) {
@ -1574,6 +1590,24 @@ void SymbolDatabase::printOut(const char *title) const
std::cout << " )" << std::endl; std::cout << " )" << std::endl;
std::cout << " friendList[" << scope->friendList.size() << "] = (";
std::list<Scope::FriendInfo>::const_iterator fii;
count = scope->friendList.size();
for (fii = scope->friendList.begin(); fii != scope->friendList.end(); ++fii) {
if (fii->scope)
std::cout << fii->scope->type;
else
std::cout << " Unknown";
std::cout << " " << fii->name;
if (count-- > 1)
std::cout << ",";
}
std::cout << " )" << std::endl;
std::cout << " nestedIn: " << scope->nestedIn; std::cout << " nestedIn: " << scope->nestedIn;
if (scope->nestedIn) { if (scope->nestedIn) {
std::cout << " " << scope->nestedIn->type << " " std::cout << " " << scope->nestedIn->type << " "

View File

@ -445,6 +445,8 @@ public:
}; };
struct FriendInfo { struct FriendInfo {
const Token *nameStart;
const Token *nameEnd;
std::string name; std::string name;
Scope *scope; Scope *scope;
}; };

View File

@ -50,6 +50,7 @@ private:
TEST_CASE(noConstructor3); TEST_CASE(noConstructor3);
TEST_CASE(noConstructor4); TEST_CASE(noConstructor4);
TEST_CASE(noConstructor5); TEST_CASE(noConstructor5);
TEST_CASE(noConstructor6); // ticket #4386
TEST_CASE(operatorEq1); TEST_CASE(operatorEq1);
TEST_CASE(operatorEq2); TEST_CASE(operatorEq2);
@ -1881,6 +1882,20 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void noConstructor6() {
// ticket #4386
checkNoConstructor("class Ccpucycles {\n"
" friend class foo::bar;\n"
" Ccpucycles() :\n"
" m_v(0), m_b(true)\n"
" {}\n"
"private:\n"
" cpucyclesT m_v;\n"
" bool m_b;\n"
"};\n");
ASSERT_EQUALS("", errout.str());
}
void checkNoMemset(const char code[]) { void checkNoMemset(const char code[]) {
// Clear the error log // Clear the error log
errout.str(""); errout.str("");