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
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
// 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);
if (tok->strAt(1) == "::")
@ -429,10 +430,25 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
}
// friend class declaration?
else if (Token::Match(tok, "friend class| %any% ;")) {
else if (Token::Match(tok, "friend class| ::| %any% ;|::")) {
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
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>::iterator j = scopeList.begin(); j != scopeList.end(); ++j) {
// check scope for match
scope = const_cast<Scope*>(j->findQualifiedScope(i->name));
scope = findScope(i->nameStart, it->nestedIn);
// found match?
if (scope && scope->isClassOrStruct()) {
@ -1574,6 +1590,24 @@ void SymbolDatabase::printOut(const char *title) const
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;
if (scope->nestedIn) {
std::cout << " " << scope->nestedIn->type << " "

View File

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

View File

@ -50,6 +50,7 @@ private:
TEST_CASE(noConstructor3);
TEST_CASE(noConstructor4);
TEST_CASE(noConstructor5);
TEST_CASE(noConstructor6); // ticket #4386
TEST_CASE(operatorEq1);
TEST_CASE(operatorEq2);
@ -1881,6 +1882,20 @@ private:
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[]) {
// Clear the error log
errout.str("");