Revert "Fixed #3190 (SymbolDatabase: Parse of sub class constructor fails)"
This reverts commit 1ee980184e
.
This commit is contained in:
parent
1ee980184e
commit
b591097c87
|
@ -2220,10 +2220,6 @@ void CheckMemoryLeakInFunction::check()
|
||||||
if (!var->isPointer() && var->typeStartToken()->str() != "int")
|
if (!var->isPointer() && var->typeStartToken()->str() != "int")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// check for known class without implementation (forward declaration)
|
|
||||||
if (var->isPointer() && var->type() && var->type()->isForwardDeclaration())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken());
|
unsigned int sz = _tokenizer->sizeOfType(var->typeStartToken());
|
||||||
if (sz < 1)
|
if (sz < 1)
|
||||||
sz = 1;
|
sz = 1;
|
||||||
|
|
|
@ -52,33 +52,17 @@ 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% [{:]")) {
|
||||||
const Token *tok2;
|
scopeList.push_back(Scope(this, tok, scope));
|
||||||
std::list<std::string> names;
|
|
||||||
|
|
||||||
if (tok->strAt(1) == "::") {
|
Scope *new_scope = &scopeList.back();
|
||||||
names.push_front(tok->strAt(2));
|
|
||||||
tok2 = tok->tokAt(3);
|
|
||||||
} else {
|
|
||||||
tok2 = tok->tokAt(2);
|
|
||||||
names.push_front(tok->strAt(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
while (tok2 && tok2->str() == "::") {
|
|
||||||
names.push_front(tok2->strAt(1));
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we have valid code
|
|
||||||
if (!tok2)
|
|
||||||
break;
|
|
||||||
|
|
||||||
Scope *new_scope = getScope(names, tok, scope);
|
|
||||||
if (tok->str() == "class")
|
if (tok->str() == "class")
|
||||||
access[new_scope] = Private;
|
access[new_scope] = Private;
|
||||||
else if (tok->str() == "struct")
|
else if (tok->str() == "struct")
|
||||||
access[new_scope] = Public;
|
access[new_scope] = Public;
|
||||||
|
|
||||||
|
const Token *tok2 = tok->tokAt(2);
|
||||||
|
|
||||||
// only create base list for classes and structures
|
// only create base list for classes and structures
|
||||||
if (new_scope->isClassOrStruct()) {
|
if (new_scope->isClassOrStruct()) {
|
||||||
// goto initial '{'
|
// goto initial '{'
|
||||||
|
@ -105,7 +89,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
classAndStructTypes.insert(new_scope->className);
|
classAndStructTypes.insert(new_scope->className);
|
||||||
|
|
||||||
// make the new scope the current scope
|
// make the new scope the current scope
|
||||||
scope = applyScope(new_scope);
|
scope = &scopeList.back();
|
||||||
|
scope->nestedIn->nestedList.push_back(scope);
|
||||||
|
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
}
|
}
|
||||||
|
@ -139,30 +124,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
}
|
}
|
||||||
|
|
||||||
// forward declaration
|
// forward declaration
|
||||||
else if (Token::Match(tok, "class|struct %var% ;") &&
|
else if (Token::Match(tok, "class|struct %var% ;")) {
|
||||||
tok->strAt(-1) != "friend") {
|
|
||||||
// fill the classAndStructTypes set..
|
// fill the classAndStructTypes set..
|
||||||
classAndStructTypes.insert(tok->next()->str());
|
classAndStructTypes.insert(tok->next()->str());
|
||||||
|
|
||||||
scopeList.push_back(Scope(this, tok, scope));
|
/** @todo save forward declarations in database someday */
|
||||||
|
|
||||||
Scope *new_scope = &scopeList.back();
|
|
||||||
if (tok->str() == "class")
|
|
||||||
access[new_scope] = Private;
|
|
||||||
else if (tok->str() == "struct")
|
|
||||||
access[new_scope] = Public;
|
|
||||||
|
|
||||||
// make the new scope the current scope
|
|
||||||
scope = &scopeList.back();
|
|
||||||
scope->nestedIn->nestedList.push_back(scope);
|
|
||||||
|
|
||||||
// save the forward declaration
|
|
||||||
_forwardDecls.push_back(scope);
|
|
||||||
|
|
||||||
// leave the scope
|
|
||||||
scope = scope->nestedIn;
|
|
||||||
|
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// using namespace
|
// using namespace
|
||||||
|
@ -237,11 +205,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
else {
|
else {
|
||||||
// check for end of scope
|
// check for end of scope
|
||||||
if (tok == scope->classEnd) {
|
if (tok == scope->classEnd) {
|
||||||
if (!_back.empty() && _back.top().forward == scope) {
|
scope = scope->nestedIn;
|
||||||
scope = _back.top().back;
|
|
||||||
_back.pop();
|
|
||||||
} else
|
|
||||||
scope = scope->nestedIn;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,68 +817,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope * SymbolDatabase::getScope(const std::list<std::string> &names, const Token *tok, Scope *scope)
|
|
||||||
{
|
|
||||||
// check for forward declarations
|
|
||||||
if (_forwardDecls.empty()) {
|
|
||||||
// none so just return end of scope list
|
|
||||||
scopeList.push_back(Scope(this, tok, scope));
|
|
||||||
|
|
||||||
return &scopeList.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// got forward declarations so check for possible match
|
|
||||||
std::list<Scope *>::iterator decls;
|
|
||||||
for (decls = _forwardDecls.begin(); decls != _forwardDecls.end(); ++decls) {
|
|
||||||
Scope * decl = *decls;
|
|
||||||
Scope * next = decl;
|
|
||||||
std::list<std::string>::const_iterator it;
|
|
||||||
for (it = names.begin(); next && it != names.end(); ++it) {
|
|
||||||
if (next->className == *it)
|
|
||||||
next = next->nestedIn;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fully qualified name match
|
|
||||||
if (it == names.end()) {
|
|
||||||
_back.push(Back(decl, scope));
|
|
||||||
decl->classDef = tok;
|
|
||||||
for (std::list<Scope *>::iterator nli = decl->nestedIn->nestedList.begin();
|
|
||||||
nli != decl->nestedIn->nestedList.end(); ++nli) {
|
|
||||||
Scope *b = *nli;
|
|
||||||
if (b == decl) {
|
|
||||||
// remove forward declration
|
|
||||||
_forwardDecls.erase(decls);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return decl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no forward declaration found so just return end of scope list
|
|
||||||
scopeList.push_back(Scope(this, tok, scope));
|
|
||||||
|
|
||||||
return &scopeList.back();
|
|
||||||
}
|
|
||||||
|
|
||||||
Scope * SymbolDatabase::applyScope(Scope * scope)
|
|
||||||
{
|
|
||||||
// check if there was a forward declaration
|
|
||||||
std::list<Scope *>::iterator it;
|
|
||||||
for (it = scope->nestedIn->nestedList.begin(); it != scope->nestedIn->nestedList.end(); ++it) {
|
|
||||||
if ((*it) == scope)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add it if there was no forward declaration
|
|
||||||
if (it == scope->nestedIn->nestedList.end())
|
|
||||||
scope->nestedIn->nestedList.push_back(scope);
|
|
||||||
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart)
|
bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart)
|
||||||
{
|
{
|
||||||
// function returning function pointer? '... ( ... %var% ( ... ))( ... ) {'
|
// function returning function pointer? '... ( ... %var% ( ... ))( ... ) {'
|
||||||
|
@ -1620,7 +1522,7 @@ void SymbolDatabase::printOut(const char *title) const
|
||||||
|
|
||||||
count = scope->nestedList.size();
|
count = scope->nestedList.size();
|
||||||
for (nsi = scope->nestedList.begin(); nsi != scope->nestedList.end(); ++nsi) {
|
for (nsi = scope->nestedList.begin(); nsi != scope->nestedList.end(); ++nsi) {
|
||||||
std::cout << " " << (*nsi) << " " << (*nsi)->type << " " << (*nsi)->className;
|
std::cout << " " << &(*nsi) << " " << (*nsi)->type << " " << (*nsi)->className;
|
||||||
if (count-- > 1)
|
if (count-- > 1)
|
||||||
std::cout << ",";
|
std::cout << ",";
|
||||||
}
|
}
|
||||||
|
@ -1850,20 +1752,11 @@ Scope::Scope(SymbolDatabase *check_, const Token *classDef_, Scope *nestedIn_) :
|
||||||
type = Scope::eGlobal;
|
type = Scope::eGlobal;
|
||||||
} else if (classDef->str() == "class") {
|
} else if (classDef->str() == "class") {
|
||||||
type = Scope::eClass;
|
type = Scope::eClass;
|
||||||
const Token * tok = classDef->next();
|
className = classDef->next()->str();
|
||||||
while (tok->strAt(1) == "::")
|
|
||||||
tok = tok->tokAt(2);
|
|
||||||
className = tok->str();
|
|
||||||
} else if (classDef->str() == "struct") {
|
} else if (classDef->str() == "struct") {
|
||||||
type = Scope::eStruct;
|
type = Scope::eStruct;
|
||||||
if (classDef->next()->str() == "::") {
|
|
||||||
const Token * tok = classDef->next();
|
|
||||||
while (tok->strAt(1) == "::")
|
|
||||||
tok = tok->tokAt(2);
|
|
||||||
className = tok->str();
|
|
||||||
}
|
|
||||||
// anonymous and unnamed structs don't have a name
|
// anonymous and unnamed structs don't have a name
|
||||||
else if (classDef->next()->str() != "{")
|
if (classDef->next()->str() != "{")
|
||||||
className = classDef->next()->str();
|
className = classDef->next()->str();
|
||||||
} else if (classDef->str() == "union") {
|
} else if (classDef->str() == "union") {
|
||||||
type = Scope::eUnion;
|
type = Scope::eUnion;
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stack>
|
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
@ -491,10 +490,6 @@ public:
|
||||||
type == eTry || type == eCatch);
|
type == eTry || type == eCatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isForwardDeclaration() const {
|
|
||||||
return isClassOrStruct() && classStart == NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief find if name is in nested list
|
* @brief find if name is in nested list
|
||||||
* @param name name of nested scope
|
* @param name name of nested scope
|
||||||
|
@ -630,9 +625,6 @@ private:
|
||||||
void addNewFunction(Scope **info, const Token **tok);
|
void addNewFunction(Scope **info, const Token **tok);
|
||||||
static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart);
|
static bool isFunction(const Token *tok, const Scope* outerScope, const Token **funcStart, const Token **argStart);
|
||||||
|
|
||||||
Scope * getScope(const std::list<std::string> &names, const Token *tok, Scope *scope);
|
|
||||||
Scope * applyScope(Scope * scope);
|
|
||||||
|
|
||||||
/** class/struct types */
|
/** class/struct types */
|
||||||
std::set<std::string> classAndStructTypes;
|
std::set<std::string> classAndStructTypes;
|
||||||
|
|
||||||
|
@ -642,19 +634,6 @@ private:
|
||||||
|
|
||||||
/** variable symbol table */
|
/** variable symbol table */
|
||||||
std::vector<const Variable *> _variableList;
|
std::vector<const Variable *> _variableList;
|
||||||
|
|
||||||
/** Forward declarations list for fast searching.
|
|
||||||
Forward declarations are removed if implementation is found. */
|
|
||||||
std::list<Scope *> _forwardDecls;
|
|
||||||
|
|
||||||
/** Scope to jump back to when forward declaration implementation found.
|
|
||||||
Implementation information updates forward declaration. */
|
|
||||||
struct Back {
|
|
||||||
Scope * forward; // forward declaration
|
|
||||||
Scope * back; // scope to jump back to
|
|
||||||
Back(Scope * f, Scope * b) : forward(f), back(b) { }
|
|
||||||
};
|
|
||||||
std::stack<Back> _back;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -107,7 +107,6 @@ private:
|
||||||
TEST_CASE(uninitVar20); // ticket #2867
|
TEST_CASE(uninitVar20); // ticket #2867
|
||||||
TEST_CASE(uninitVar21); // ticket #2947
|
TEST_CASE(uninitVar21); // ticket #2947
|
||||||
TEST_CASE(uninitVar22); // ticket #3043
|
TEST_CASE(uninitVar22); // ticket #3043
|
||||||
TEST_CASE(uninitVar23); // ticket #3190
|
|
||||||
TEST_CASE(uninitVarEnum);
|
TEST_CASE(uninitVarEnum);
|
||||||
TEST_CASE(uninitVarStream);
|
TEST_CASE(uninitVarStream);
|
||||||
TEST_CASE(uninitVarTypedef);
|
TEST_CASE(uninitVarTypedef);
|
||||||
|
@ -1562,24 +1561,6 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:7]: (warning) Member variable 'Fred::x' is not assigned a value in 'Fred::operator='.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:7]: (warning) Member variable 'Fred::x' is not assigned a value in 'Fred::operator='.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uninitVar23() { // ticket #3190
|
|
||||||
check("class Foo { class Sub; };\n"
|
|
||||||
"class Bar { class Sub; };\n"
|
|
||||||
"class Bar::Sub {\n"
|
|
||||||
"public:\n"
|
|
||||||
" Sub() { }\n"
|
|
||||||
" int n;\n"
|
|
||||||
"};\n"
|
|
||||||
"class ::Foo::Sub {\n"
|
|
||||||
"public:\n"
|
|
||||||
" Sub() { }\n"
|
|
||||||
" int n;\n"
|
|
||||||
"};");
|
|
||||||
|
|
||||||
ASSERT_EQUALS("[test.cpp:10]: (warning) Member variable 'Sub::n' is not initialized in the constructor.\n"
|
|
||||||
"[test.cpp:5]: (warning) Member variable 'Sub::n' is not initialized in the constructor.\n", errout.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void uninitVarArray1() {
|
void uninitVarArray1() {
|
||||||
check("class John\n"
|
check("class John\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
|
|
@ -637,9 +637,9 @@ private:
|
||||||
" printf(\"%f\", f);\n"
|
" printf(\"%f\", f);\n"
|
||||||
" printf(\"%p\", f);\n"
|
" printf(\"%p\", f);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 1) requires an unsigned integer given in the argument list.\n"
|
TODO_ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 1) requires an integer given in the argument list.\n"
|
||||||
"[test.cpp:4]: (warning) %f in format string (no. 1) requires a floating point number given in the argument list.\n"
|
"[test.cpp:4]: (warning) %f in format string (no. 1) requires an integer given in the argument list.\n"
|
||||||
"[test.cpp:5]: (warning) %p in format string (no. 1) requires an address given in the argument list.\n", errout.str());
|
"[test.cpp:5]: (warning) %p in format string (no. 1) requires an integer given in the argument list.\n", "", errout.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -672,7 +672,7 @@ private:
|
||||||
seen_something = true;
|
seen_something = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT_EQUALS(true, seen_something);
|
TODO_ASSERT_EQUALS("works", "doesn't work", seen_something ? "works" : "doesn't work");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue