SymbolDatabase: improve checking of uninstantiated templates (#1196)

* SymbolDatabase: improve checking of uninstantiated templates

* Add bailout and debug warning for '>' token without a link in SymbolDatabase::findFunction()..

Don't crash on bad code simplification from tokenizer.
This commit is contained in:
IOBYTE 2018-05-01 01:32:19 -04:00 committed by Daniel Marjamäki
parent 73b41455dd
commit c3c1abd05e
3 changed files with 738 additions and 208 deletions

View File

@ -64,6 +64,22 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
createSymbolDatabaseUnknownArrayDimensions();
}
static const Token* skipScopeIdentifiers(const Token* tok)
{
if (tok && tok->str() == "::") {
tok = tok->next();
}
while (Token::Match(tok, "%name% ::") ||
(Token::Match(tok, "%name% <") && tok->linkAt(1) && tok->linkAt(1)->strAt(1) == "::")) {
if (tok->strAt(1) == "::")
tok = tok->tokAt(2);
else
tok = tok->linkAt(1)->tokAt(2);
}
return tok;
}
void SymbolDatabase::createSymbolDatabaseFindAllScopes()
{
// create global scope
@ -101,8 +117,11 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
tok2 = tok2->tokAt(2);
// skip over template args
if (tok2 && tok2->str() == "<" && tok2->link())
while (tok2 && tok2->str() == "<" && tok2->link()) {
tok2 = tok2->link()->next();
while (Token::Match(tok2, ":: %name%"))
tok2 = tok2->tokAt(2);
}
// make sure we have valid code
if (!Token::Match(tok2, "{|:")) {
@ -1420,6 +1439,8 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
tok1 = tok1->previous();
if (Token::Match(tok1, "%name%"))
tok1 = tok1->previous();
else if (tok1 && tok1->str() == ">" && tok1->link() && Token::Match(tok1->link()->previous(), "%name%"))
tok1 = tok1->link()->tokAt(-2);
}
// skip over modifiers and other stuff
@ -1788,7 +1809,7 @@ Function::Function(const Tokenizer *_tokenizer, const Token *tok, const Scope *s
}
}
bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int depth)
bool Function::argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int path_length)
{
const bool isCPP = scope->check->isCPP();
if (!isCPP) // C does not support overloads
@ -1806,9 +1827,12 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
if (Token::Match(second, "const %type% %name%|,|)"))
second = second->next();
unsigned int arg_path_length = path_length;
while (first->str() == second->str() &&
first->isLong() == second->isLong() &&
first->isUnsigned() == second->isUnsigned()) {
// at end of argument list
if (first->str() == ")") {
return true;
@ -1903,41 +1927,67 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
}
// variable with class path
else if (depth && Token::Match(first->next(), "%name%")) {
std::string param = path + first->next()->str();
else if (arg_path_length && Token::Match(first->next(), "%name%") && first->strAt(1) != "const") {
std::string param = path;
if (Token::simpleMatch(second->next(), param.c_str())) {
second = second->tokAt(int(depth) * 2);
} else if (depth > 1) {
second = second->tokAt(int(arg_path_length));
arg_path_length = 0;
}
// nested or base class variable
else if (arg_path_length <= 2 && Token::Match(first->next(), "%name%") &&
(Token::Match(second->next(), "%name% :: %name%") ||
(Token::Match(second->next(), "%name% <") &&
Token::Match(second->linkAt(1), "> :: %name%"))) &&
((second->next()->str() == scope->className) ||
(scope->definedType && scope->definedType->isDerivedFrom(second->next()->str()))) &&
(first->next()->str() == second->strAt(3))) {
if (Token::Match(second->next(), "%name% <"))
second = second->linkAt(1)->next();
else
second = second->tokAt(2);
}
// remove class name
else if (arg_path_length > 2) {
std::string short_path = path;
unsigned int short_path_length = arg_path_length;
// remove last " :: "
short_path.resize(short_path.size() - 4);
short_path_length--;
// remove last name
const std::string::size_type lastSpace = short_path.find_last_of(' ');
if (lastSpace != std::string::npos)
std::string::size_type lastSpace = short_path.find_last_of(' ');
if (lastSpace != std::string::npos) {
short_path.resize(lastSpace+1);
short_path_length--;
if (short_path[short_path.size() - 1] == '>') {
short_path.resize(short_path.size() - 3);
while (short_path[short_path.size() - 1] == '<') {
lastSpace = short_path.find_last_of(' ');
short_path.resize(lastSpace+1);
short_path_length--;
}
}
}
param = short_path + first->next()->str();
param = short_path;
if (Token::simpleMatch(second->next(), param.c_str())) {
second = second->tokAt((int(depth) - 1) * 2);
second = second->tokAt(int(short_path_length));
arg_path_length = 0;
}
}
}
// nested or base class variable
else if (depth == 0 && Token::Match(first->next(), "%name%") &&
Token::Match(second->next(), "%name% :: %name%") &&
((second->next()->str() == scope->className) ||
(scope->definedType && scope->definedType->isDerivedFrom(second->next()->str()))) &&
(first->next()->str() == second->strAt(3))) {
second = second->tokAt(2);
}
first = first->next();
second = second->next();
// reset path length
if (first->str() == "," || second->str() == ",")
arg_path_length = path_length;
// skip "struct"
if (first->str() == "struct" || first->str() == "enum")
first = first->next();
@ -2005,51 +2055,37 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
const bool has_const(argStart->link()->strAt(1) == "const");
const bool lval(argStart->link()->strAt(has_const ? 2 : 1) == "&");
const bool rval(argStart->link()->strAt(has_const ? 2 : 1) == "&&");
const Token *tok1;
// skip class/struct name
int count = 0;
std::string path;
unsigned int path_length = 0;
const Token *tok1 = (*tok);
if (destructor)
tok1 = (*tok)->tokAt(-3);
else if ((*tok)->strAt(-2) == ">" && (*tok)->linkAt(-2))
tok1 = (*tok)->linkAt(-2)->previous();
else
tok1 = (*tok)->tokAt(-2);
tok1 = tok1->previous();
// back up to head of path
while (tok1 && tok1->previous() && tok1->previous()->str() == "::" && tok1->tokAt(-2) &&
(tok1->tokAt(-2)->isName() ||
(tok1->strAt(-2) == ">" && tok1->linkAt(-2) && Token::Match(tok1->linkAt(-2)->previous(), "%name%")))) {
count++;
const Token * tok2 = tok1->tokAt(-2);
if (tok2->str() == ">")
tok2 = tok2->link()->previous();
if (tok2) {
do {
path = tok1->previous()->str() + " " + path;
tok1 = tok1->previous();
path_length++;
} while (tok1 != tok2);
} else
return; // syntax error ?
}
// syntax error?
if (!tok1)
return;
int count = 0;
std::string path;
unsigned int path_length = 0;
// back up to head of path
while (tok1 && tok1->previous() && tok1->previous()->str() == "::" &&
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) {
path = tok1->str() + " :: " + path;
path_length++;
}
std::list<Scope>::iterator it1;
// search for match
@ -2063,7 +2099,7 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
std::list<Scope::UsingInfo>::const_iterator it2;
for (it2 = scope1->usingList.begin(); it2 != scope1->usingList.end(); ++it2) {
if (it2->scope) {
Function * func = findFunctionInScope(tok1, it2->scope);
Function * func = findFunctionInScope(tok1, it2->scope, path, path_length);
if (func) {
if (!func->hasBody()) {
func->hasBody(true);
@ -2106,13 +2142,16 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
Scope *scope2 = scope1;
while (scope2 && count > 0) {
while (scope2 && count > 1) {
count--;
tok1 = tok1->tokAt(2);
if (tok1->strAt(1) == "<")
tok1 = tok1->linkAt(1)->tokAt(2);
else
tok1 = tok1->tokAt(2);
scope2 = scope2->findRecordInNestedList(tok1->str());
}
if (count == 0 && scope2) {
if (count == 1 && scope2) {
match = true;
scope1 = scope2;
}
@ -3214,10 +3253,7 @@ Scope::Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *
type = Scope::eFunction;
}
// skip over qualification if present
if (nameTok && nameTok->str() == "::")
nameTok = nameTok->next();
while (Token::Match(nameTok, "%type% ::"))
nameTok = nameTok->tokAt(2);
nameTok = skipScopeIdentifiers(nameTok);
if (nameTok && ((type == Scope::eEnum && Token::Match(nameTok, ":|{")) || nameTok->str() != "{")) // anonymous and unnamed structs/unions don't have a name
className = nameTok->str();
@ -3442,18 +3478,6 @@ const Variable *Scope::getVariable(const std::string &varname) const
return nullptr;
}
static const Token* skipScopeIdentifiers(const Token* tok)
{
if (tok && tok->str() == "::") {
tok = tok->next();
}
while (Token::Match(tok, "%type% ::")) {
tok = tok->tokAt(2);
}
return tok;
}
static const Token* skipPointers(const Token* tok)
{
while (Token::Match(tok, "*|&|&&") || (Token::Match(tok, "( [*&]") && Token::Match(tok->link()->next(), "(|["))) {
@ -3781,8 +3805,13 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
// find start of qualified function name
const Token *tok1 = typeTok;
while (Token::Match(tok1->tokAt(-2), "%type% ::"))
tok1 = tok1->tokAt(-2);
while (Token::Match(tok1->tokAt(-2), "%type% ::") ||
(Token::simpleMatch(tok1->tokAt(-2), "> ::") && Token::Match(tok1->linkAt(-2)->tokAt(-1), "%type%"))) {
if (tok1->strAt(-1) == "::")
tok1 = tok1->tokAt(-2);
else
tok1 = tok1->linkAt(-2)->tokAt(-1);
}
// check for global scope
if (tok1->strAt(-1) == "::") {
@ -3812,8 +3841,12 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
if (scope) {
// follow qualification
while (scope && Token::Match(tok1, "%type% ::")) {
tok1 = tok1->tokAt(2);
while (scope && (Token::Match(tok1, "%type% ::") ||
(Token::Match(tok1, "%type% <") && Token::simpleMatch(tok1->linkAt(1)->next(), "::")))) {
if (tok1->strAt(1) == "::")
tok1 = tok1->tokAt(2);
else
tok1 = tok1->linkAt(1)->tokAt(2);
const Scope * temp = scope->findRecordInNestedList(tok1->str());
if (!temp) {
// look in base classes
@ -4256,8 +4289,18 @@ const Function* SymbolDatabase::findFunction(const Token *tok) const
// find start of qualified function name
const Token *tok1 = tok;
while (Token::Match(tok1->tokAt(-2), "%type% ::"))
tok1 = tok1->tokAt(-2);
while (Token::Match(tok1->tokAt(-2), ">|%type% ::")) {
if (tok1->strAt(-2) == ">") {
if (tok1->linkAt(-2))
tok1 = tok1->linkAt(-2)->tokAt(-1);
else {
if (_settings->debugwarnings)
debugMessage(tok1->tokAt(-2), "SymbolDatabase::findFunction found '>' without link.");
return nullptr;
}
} else
tok1 = tok1->tokAt(-2);
}
// check for global scope
if (tok1->strAt(-1) == "::") {
@ -4284,8 +4327,12 @@ const Function* SymbolDatabase::findFunction(const Token *tok) const
}
if (currScope) {
while (currScope && !Token::Match(tok1, "%type% :: %any% (")) {
tok1 = tok1->tokAt(2);
while (currScope && !(Token::Match(tok1, "%type% :: %any% (") ||
(Token::Match(tok1, "%type% <") && Token::Match(tok1->linkAt(1), "> :: %any% (")))) {
if (tok1->strAt(1) == "::")
tok1 = tok1->tokAt(2);
else
tok1 = tok1->linkAt(1)->tokAt(2);
currScope = currScope->findRecordInNestedList(tok1->str());
}
@ -4444,6 +4491,9 @@ const Scope *SymbolDatabase::findScope(const Token *tok, const Scope *startScope
if (tok->strAt(1) == "::") {
scope = scope->findRecordInNestedList(tok->str());
tok = tok->tokAt(2);
} else if (tok->strAt(1) == "<" && tok->linkAt(1) && tok->linkAt(1)->strAt(1) == "::") {
scope = scope->findRecordInNestedList(tok->str());
tok = tok->linkAt(1)->tokAt(2);
} else
return scope->findRecordInNestedList(tok->str());
}
@ -4476,10 +4526,13 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
const Scope* scope = start_scope;
while (scope && tok && tok->isName()) {
if (tok->strAt(1) == "::") {
if (tok->strAt(1) == "::" || (tok->strAt(1) == "<" && tok->linkAt(1)->strAt(1) == "::")) {
scope = scope->findRecordInNestedList(tok->str());
if (scope) {
tok = tok->tokAt(2);
if (tok->strAt(1) == "::")
tok = tok->tokAt(2);
else
tok = tok->linkAt(1)->tokAt(2);
} else {
start_scope = start_scope->nestedIn;
if (!start_scope)
@ -4505,10 +4558,13 @@ const Type* SymbolDatabase::findType(const Token *startTok, const Scope *startSc
start_scope = startScope;
while (scope && tok && tok->isName()) {
if (tok->strAt(1) == "::") {
if (tok->strAt(1) == "::" || (tok->strAt(1) == "<" && tok->linkAt(1)->strAt(1) == "::")) {
scope = scope->findRecordInNestedList(tok->str());
if (scope) {
tok = tok->tokAt(2);
if (tok->strAt(1) == "::")
tok = tok->tokAt(2);
else
tok = tok->linkAt(1)->tokAt(2);
} else {
start_scope = start_scope->nestedIn;
if (!start_scope)
@ -4557,11 +4613,14 @@ const Type* SymbolDatabase::findTypeInNested(const Token *startTok, const Scope
const Scope* scope = startScope;
while (scope && tok && tok->isName()) {
if (tok->strAt(1) == "::") {
if (tok->strAt(1) == "::" || (tok->strAt(1) == "<" && tok->linkAt(1)->strAt(1) == "::")) {
hasPath = true;
scope = scope->findRecordInNestedList(tok->str());
if (scope) {
tok = tok->tokAt(2);
if (tok->strAt(1) == "::")
tok = tok->tokAt(2);
else
tok = tok->linkAt(1)->tokAt(2);
} else {
startScope = startScope->nestedIn;
if (!startScope)
@ -4601,7 +4660,7 @@ const Scope * SymbolDatabase::findNamespace(const Token * tok, const Scope * sco
//---------------------------------------------------------------------------
Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *ns)
Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *ns, const std::string & path, unsigned int path_length)
{
const Function * function = nullptr;
const bool destructor = func->strAt(-1) == "~";
@ -4609,7 +4668,7 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
for (std::multimap<std::string, const Function *>::const_iterator it = ns->functionMap.find(func->str());
it != ns->functionMap.end() && it->first == func->str(); ++it) {
if (Function::argsMatch(ns, func->tokAt(2), it->second->argDef->next(), emptyString, 0) &&
if (Function::argsMatch(ns, it->second->argDef->next(), func->tokAt(2), path, path_length) &&
it->second->isDestructor() == destructor) {
function = it->second;
break;
@ -4618,11 +4677,14 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
if (!function) {
const Scope * scope = ns->findRecordInNestedList(func->str());
if (scope && func->strAt(1) == "::") {
func = func->tokAt(2);
if (scope && Token::Match(func->tokAt(1), "::|<")) {
if (func->strAt(1) == "::")
func = func->tokAt(2);
else
func = func->linkAt(1)->tokAt(2);
if (func->str() == "~")
func = func->next();
function = findFunctionInScope(func, scope);
function = findFunctionInScope(func, scope, path, path_length);
}
}

View File

@ -828,7 +828,7 @@ public:
const Token *noexceptArg; ///< noexcept token
const Token *throwArg; ///< throw token
static bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int depth);
static bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, unsigned int path_length);
/**
* @return token to ":" if the function is a constructor
@ -1211,7 +1211,7 @@ private:
bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart, const Token** declEnd) const;
const Type *findTypeInNested(const Token *startTok, const Scope *startScope) const;
const Scope *findNamespace(const Token * tok, const Scope * scope) const;
Function *findFunctionInScope(const Token *func, const Scope *ns);
Function *findFunctionInScope(const Token *func, const Scope *ns, const std::string & path, unsigned int path_length);
const Type *findVariableTypeInBase(const Scope *scope, const Token *typeTok) const;
typedef std::map<unsigned int, unsigned int> MemberIdMap;

View File

@ -282,6 +282,7 @@ private:
TEST_CASE(symboldatabase62);
TEST_CASE(symboldatabase63);
TEST_CASE(symboldatabase64);
TEST_CASE(symboldatabase65);
TEST_CASE(enum1);
TEST_CASE(enum2);
@ -2383,7 +2384,7 @@ private:
// ticket #2991 - segmentation fault
check("::y(){x}");
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:1]: (debug) Executable scope 'y' with unknown function.\n", errout.str());
}
void symboldatabase20() {
@ -3030,13 +3031,14 @@ private:
" impl() { }\n"
" ~impl() { }\n"
" impl(const impl &) { }\n"
"};\n");
" void foo(const impl &, const impl &) const { }\n"
"};");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 6);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
@ -3055,6 +3057,12 @@ private:
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 5);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 6);
}
{
GET_SYMBOL_DB("class Fred { struct impl; };\n"
@ -3062,34 +3070,42 @@ private:
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"Fred::impl::impl() { }\n"
"Fred::impl::~impl() { }\n"
"Fred::impl::impl(const Fred::impl &) { }");
"Fred::impl::impl(const Fred::impl &) { }\n"
"void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 6);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 3 &&
functionToken->function()->token->linenr() == 7);
functionToken->function()->token->linenr() == 8);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 4 &&
functionToken->next()->function()->token->linenr() == 8);
functionToken->next()->function()->token->linenr() == 9);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 9);
functionToken->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 11);
}
{
GET_SYMBOL_DB("namespace NS {\n"
@ -3098,14 +3114,15 @@ private:
" impl() { }\n"
" ~impl() { }\n"
" impl(const impl &) { }\n"
" void foo(const impl &, const impl &) const { }\n"
" };\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
@ -3124,6 +3141,12 @@ private:
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 6);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 7);
}
{
GET_SYMBOL_DB("namespace NS {\n"
@ -3132,54 +3155,19 @@ private:
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
" };\n"
" Fred::impl::impl() { }\n"
" Fred::impl::~impl() { }\n"
" Fred::impl::impl(const Fred::impl &) { }\n"
" void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 4 &&
functionToken->function()->token->linenr() == 8);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 5 &&
functionToken->next()->function()->token->linenr() == 9);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 10);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" class Fred { struct impl; };\n"
" struct Fred::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" };\n"
"}\n"
"NS::Fred::impl::impl() { }\n"
"NS::Fred::impl::~impl() { }\n"
"NS::Fred::impl::impl(const NS::Fred::impl &) { }\n");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
@ -3193,11 +3181,62 @@ private:
functionToken->next()->function()->tokenDef->linenr() == 5 &&
functionToken->next()->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred :: impl & ) { }");
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 12);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" class Fred { struct impl; };\n"
" struct Fred::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
" };\n"
"}\n"
"NS::Fred::impl::impl() { }\n"
"NS::Fred::impl::~impl() { }\n"
"NS::Fred::impl::impl(const NS::Fred::impl &) { }\n"
"void NS::Fred::impl::foo(const NS::Fred::impl &, const NS::Fred::impl &) const { }");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 4 &&
functionToken->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 5 &&
functionToken->next()->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred :: impl & , const NS :: Fred :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 13);
}
{
GET_SYMBOL_DB("namespace NS {\n"
@ -3207,13 +3246,14 @@ private:
" impl() { }\n"
" ~impl() { }\n"
" impl(const impl &) { }\n"
" void foo(const impl &, const impl &) const { }\n"
"};");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
@ -3232,6 +3272,12 @@ private:
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 7);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 8);
}
{
GET_SYMBOL_DB("namespace NS {\n"
@ -3241,55 +3287,18 @@ private:
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"NS::Fred::impl::impl() { }\n"
"NS::Fred::impl::~impl() { }\n"
"NS::Fred::impl::impl(const NS::Fred::impl &) { }");
"NS::Fred::impl::impl(const NS::Fred::impl &) { }\n"
"void NS::Fred::impl::foo(const NS::Fred::impl &, const NS::Fred::impl &) const { }");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 9);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 11);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" class Fred { struct impl; };\n"
"}\n"
"struct NS::Fred::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
"};\n"
"namespace NS {\n"
" Fred::impl::impl() { }\n"
" Fred::impl::~impl() { }\n"
" Fred::impl::impl(const Fred::impl &) { }\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
@ -3303,7 +3312,274 @@ private:
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred :: impl & , const NS :: Fred :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 13);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" class Fred { struct impl; };\n"
"}\n"
"struct NS::Fred::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"namespace NS {\n"
" Fred::impl::impl() { }\n"
" Fred::impl::~impl() { }\n"
" Fred::impl::impl(const Fred::impl &) { }\n"
" void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 13);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 14);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" class Fred { struct impl; };\n"
"}\n"
"struct NS::Fred::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"using namespace NS;\n"
"Fred::impl::impl() { }\n"
"Fred::impl::~impl() { }\n"
"Fred::impl::impl(const Fred::impl &) { }\n"
"void Fred::impl::foo(const Fred::impl &, const Fred::impl &) const { }");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 13);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred :: impl & , const Fred :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 14);
}
{
GET_SYMBOL_DB("template <typename A> class Fred { struct impl; };\n"
"template <typename A> struct Fred<A>::impl {\n"
" impl() { }\n"
" ~impl() { }\n"
" impl(const impl &) { }\n"
" void foo(const impl &, const impl &) const { }\n"
"};\n");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 3 &&
functionToken->function()->token->linenr() == 3);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 4 &&
functionToken->next()->function()->token->linenr() == 4);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 5);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 6);
}
{
GET_SYMBOL_DB("template <typename A> class Fred { struct impl; };\n"
"template <typename A> struct Fred<A>::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"template <typename A> Fred<A>::impl::impl() { }\n"
"template <typename A> Fred<A>::impl::~impl() { }\n"
"template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
"template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }\n");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 3 &&
functionToken->function()->token->linenr() == 8);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 4 &&
functionToken->next()->function()->token->linenr() == 9);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 11);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" template <typename A> class Fred { struct impl; };\n"
" template <typename A> struct Fred<A>::impl {\n"
" impl() { }\n"
" ~impl() { }\n"
" impl(const impl &) { }\n"
" void foo(const impl &, const impl &) const { }\n"
" };\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 4 &&
functionToken->function()->token->linenr() == 4);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 5 &&
functionToken->next()->function()->token->linenr() == 5);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 6);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 7);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" template <typename A> class Fred { struct impl; };\n"
" template <typename A> struct Fred<A>::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
" };\n"
" template <typename A> Fred<A>::impl::impl() { }\n"
" template <typename A> Fred<A>::impl::~impl() { }\n"
" template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
" template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 4 &&
functionToken->function()->token->linenr() == 9);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 5 &&
functionToken->next()->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
@ -3311,23 +3587,110 @@ private:
}
{
GET_SYMBOL_DB("namespace NS {\n"
" class Fred { struct impl; };\n"
" template <typename A> class Fred { struct impl; };\n"
" template <typename A> struct Fred<A>::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
" };\n"
"}\n"
"struct NS::Fred::impl {\n"
"template <typename A> NS::Fred<A>::impl::impl() { }\n"
"template <typename A> NS::Fred<A>::impl::~impl() { }\n"
"template <typename A> NS::Fred<A>::impl::impl(const NS::Fred<A>::impl &) { }\n"
"template <typename A> void NS::Fred<A>::impl::foo(const NS::Fred<A>::impl &, const NS::Fred<A>::impl &) const { }\n");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 4 &&
functionToken->function()->token->linenr() == 10);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 5 &&
functionToken->next()->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred < A > :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 6 &&
functionToken->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred < A > :: impl & , const NS :: Fred < A > :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 13);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" template <typename A> class Fred { struct impl; };\n"
"}\n"
"template <typename A> struct NS::Fred<A>::impl {\n"
" impl() { }\n"
" ~impl() { }\n"
" impl(const impl &) { }\n"
" void foo(const impl &, const impl &) const { }\n"
"};");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 5);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 6);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 7);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const impl & , const impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 8);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" template <typename A> class Fred { struct impl; };\n"
"}\n"
"template <typename A> struct NS::Fred<A>::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"using namespace NS;\n"
"Fred::impl::impl() { }\n"
"Fred::impl::~impl() { }\n"
"Fred::impl::impl(const Fred::impl &) { }");
"template <typename A> NS::Fred<A>::impl::impl() { }\n"
"template <typename A> NS::Fred<A>::impl::~impl() { }\n"
"template <typename A> NS::Fred<A>::impl::impl(const NS::Fred<A>::impl &) { }\n"
"template <typename A> void NS::Fred<A>::impl::foo(const NS::Fred<A>::impl &, const NS::Fred<A>::impl &) const { }\n");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 7);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 3);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
@ -3341,12 +3704,117 @@ private:
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred :: impl & ) { }");
TODO_ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const NS :: Fred < A > :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const NS :: Fred < A > :: impl & , const NS :: Fred < A > :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 13);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" template <typename A> class Fred { struct impl; };\n"
"}\n"
"template <typename A> struct NS::Fred<A>::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"namespace NS {\n"
" template <typename A> Fred<A>::impl::impl() { }\n"
" template <typename A> Fred<A>::impl::~impl() { }\n"
" template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
" template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }\n"
"}");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 13);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 14);
}
{
GET_SYMBOL_DB("namespace NS {\n"
" template <typename A> class Fred { struct impl; };\n"
"}\n"
"template <typename A> struct NS::Fred::impl {\n"
" impl();\n"
" ~impl();\n"
" impl(const impl &);\n"
" void foo(const impl &, const impl &) const;\n"
"};\n"
"using namespace NS;\n"
"template <typename A> Fred<A>::impl::impl() { }\n"
"template <typename A> Fred<A>::impl::~impl() { }\n"
"template <typename A> Fred<A>::impl::impl(const Fred<A>::impl &) { }\n"
"template <typename A> void Fred<A>::impl::foo(const Fred<A>::impl &, const Fred<A>::impl &) const { }\n");
ASSERT(db != nullptr);
ASSERT(db && db->scopeList.size() == 8);
ASSERT(db && db->classAndStructScopes.size() == 2);
ASSERT(db && db->typeList.size() == 2);
ASSERT(db && db->functionScopes.size() == 4);
const Token * functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 5 &&
functionToken->function()->token->linenr() == 11);
functionToken = Token::findsimplematch(tokenizer.tokens(), "~ impl ( ) { }");
ASSERT(db && functionToken && functionToken->next()->function() &&
functionToken->next()->function()->functionScope &&
functionToken->next()->function()->tokenDef->linenr() == 6 &&
functionToken->next()->function()->token->linenr() == 12);
functionToken = Token::findsimplematch(tokenizer.tokens(), "impl ( const Fred < A > :: impl & ) { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 7 &&
functionToken->function()->token->linenr() == 13);
functionToken = Token::findsimplematch(tokenizer.tokens(), "foo ( const Fred < A > :: impl & , const Fred < A > :: impl & ) const { }");
ASSERT(db && functionToken && functionToken->function() &&
functionToken->function()->functionScope &&
functionToken->function()->tokenDef->linenr() == 8 &&
functionToken->function()->token->linenr() == 14);
}
}
void symboldatabase65() {
// don't crash on missing links from instantiation of template with typedef
check("int ( * X0 ) ( long ) < int ( ) ( long ) > :: f0 ( int * ) { return 0 ; }");
ASSERT_EQUALS("[test.cpp:1]: (debug) SymbolDatabase::findFunction found '>' without link.\n", errout.str());
}
void enum1() {