Fixed #4388 (false positive 'noConstructor' in 1.57)

This commit is contained in:
Robert Reif 2013-02-15 06:44:07 +01:00 committed by Daniel Marjamäki
parent 452dc23742
commit c5ee083c82
5 changed files with 46 additions and 93 deletions

View File

@ -410,10 +410,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
if (end->next()->str() == "const") if (end->next()->str() == "const")
function.isConst = true; function.isConst = true;
// pure virtual function
if (Token::Match(end, ") const| = %any%"))
function.isPure = true;
// count the number of constructors // count the number of constructors
if (function.type == Function::eConstructor || if (function.type == Function::eConstructor ||
function.type == Function::eCopyConstructor) function.type == Function::eCopyConstructor)
@ -424,10 +420,35 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
function.arg = function.argDef; function.arg = function.argDef;
// out of line function // out of line function
if (Token::Match(end, ") const| ;") || if (Token::Match(end, ") const| ;")) {
Token::Match(end, ") const| = %any%")) {
// find the function implementation later // find the function implementation later
tok = end->next(); tok = end->next();
if (tok->str() != ";")
tok = tok->next();
scope->functionList.push_back(function);
}
// default or delete
else if (Token::Match(end, ") = default|delete ;")) {
if (end->strAt(2) == "default")
function.isDefault = true;
else
function.isDelete = true;
tok = end->tokAt(3);
scope->functionList.push_back(function);
}
// pure virtual function
else if (Token::Match(end, ") const| = %any% ;")) {
function.isPure = true;
if (end->next()->str() == "const")
tok = end->tokAt(4);
else
tok = end->tokAt(3);
scope->functionList.push_back(function); scope->functionList.push_back(function);
} }
@ -981,7 +1002,8 @@ bool SymbolDatabase::isFunction(const Token *tok, const Scope* outerScope, const
tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok tok->strAt(-1) == "::" || tok->strAt(-1) == "~" || // or a scope qualifier in front of tok
outerScope->isClassOrStruct()) && // or a ctor/dtor outerScope->isClassOrStruct()) && // or a ctor/dtor
(Token::Match(tok->next()->link(), ") const| ;|{|=") || (Token::Match(tok->next()->link(), ") const| ;|{|=") ||
Token::Match(tok->next()->link(), ") : ::| %var% (|::|<|{"))) { Token::Match(tok->next()->link(), ") : ::| %var% (|::|<|{") ||
Token::Match(tok->next()->link(), ") = delete|default ;"))) {
*funcStart = tok; *funcStart = tok;
*argStart = tok->next(); *argStart = tok->next();
return true; return true;
@ -1642,6 +1664,8 @@ void SymbolDatabase::printOut(const char *title) const
std::cout << " isStatic: " << (func->isStatic ? "true" : "false") << std::endl; std::cout << " isStatic: " << (func->isStatic ? "true" : "false") << std::endl;
std::cout << " isFriend: " << (func->isFriend ? "true" : "false") << std::endl; std::cout << " isFriend: " << (func->isFriend ? "true" : "false") << std::endl;
std::cout << " isExplicit: " << (func->isExplicit ? "true" : "false") << std::endl; std::cout << " isExplicit: " << (func->isExplicit ? "true" : "false") << std::endl;
std::cout << " isDefault: " << (func->isDefault ? "true" : "false") << std::endl;
std::cout << " isDelete: " << (func->isDelete ? "true" : "false") << std::endl;
std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl; std::cout << " isOperator: " << (func->isOperator ? "true" : "false") << std::endl;
std::cout << " retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl; std::cout << " retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl;
std::cout << " tokenDef: " << _tokenizer->list.fileLine(func->tokenDef) << std::endl; std::cout << " tokenDef: " << _tokenizer->list.fileLine(func->tokenDef) << std::endl;

View File

@ -390,6 +390,8 @@ public:
isStatic(false), isStatic(false),
isFriend(false), isFriend(false),
isExplicit(false), isExplicit(false),
isDefault(false),
isDelete(false),
isOperator(false), isOperator(false),
retFuncPtr(false) { retFuncPtr(false) {
} }
@ -427,6 +429,8 @@ public:
bool isStatic; // is static bool isStatic; // is static
bool isFriend; // is friend bool isFriend; // is friend
bool isExplicit; // is explicit bool isExplicit; // is explicit
bool isDefault; // is default
bool isDelete; // is delete
bool isOperator; // is operator bool isOperator; // is operator
bool retFuncPtr; // returns function pointer bool retFuncPtr; // returns function pointer

View File

@ -1745,8 +1745,6 @@ bool Tokenizer::tokenize(std::istream &code,
return false; return false;
} }
simplifyDefaultAndDeleteInsideClass();
// Remove __declspec() // Remove __declspec()
simplifyDeclspec(); simplifyDeclspec();
@ -2196,47 +2194,6 @@ bool Tokenizer::hasComplicatedSyntaxErrorsInTemplates()
return false; return false;
} }
void Tokenizer::simplifyDefaultAndDeleteInsideClass()
{
if (isC())
return;
// Remove "= default|delete" inside class|struct definitions
// Todo: Remove it if it is used "externally" too.
for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "struct|class %var% :|{")) {
for (Token *tok2 = tok->tokAt(3); tok2; tok2 = tok2->next()) {
if (tok2->str() == "{")
tok2 = tok2->link();
else if (tok2->str() == "}")
break;
else if (Token::Match(tok2, ") = delete|default ;")) {
Token * const end = tok2->tokAt(4);
tok2 = tok2->link()->previous();
// operator ==|>|<|..
if (Token::Match(tok2->previous(), "operator %any%"))
tok2 = tok2->previous();
else if (Token::simpleMatch(tok2->tokAt(-2), "operator [ ]"))
tok2 = tok2->tokAt(-2);
else if (Token::simpleMatch(tok2->tokAt(-2), "operator ( )"))
tok2 = tok2->tokAt(-2);
else if (Token::simpleMatch(tok2->tokAt(-3), "operator delete [ ]"))
tok2 = tok2->tokAt(-3);
while ((tok2->isName() && tok2->str().find(":") == std::string::npos) ||
Token::Match(tok2, "[&*~]"))
tok2 = tok2->previous();
if (Token::Match(tok2, "[;{}]") || tok2->isName())
Token::eraseTokens(tok2, end);
else
tok2 = end->previous();
}
}
}
}
}
bool Tokenizer::hasEnumsWithTypedef() bool Tokenizer::hasEnumsWithTypedef()
{ {
for (const Token *tok = list.front(); tok; tok = tok->next()) { for (const Token *tok = list.front(); tok; tok = tok->next()) {

View File

@ -62,6 +62,7 @@ private:
TEST_CASE(simple7); // ticket #4531 TEST_CASE(simple7); // ticket #4531
TEST_CASE(simple8); TEST_CASE(simple8);
TEST_CASE(simple9); // ticket #4574 TEST_CASE(simple9); // ticket #4574
TEST_CASE(simple10); // ticket #4388
TEST_CASE(initvar_with_this); // BUG 2190300 TEST_CASE(initvar_with_this); // BUG 2190300
TEST_CASE(initvar_if); // BUG 2190290 TEST_CASE(initvar_if); // BUG 2190290
@ -331,6 +332,16 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void simple10() { // ticket #4388
check("class Fred {\n"
"public:\n"
" Fred() = default;\n"
"private:\n"
" int x;\n"
"};");
ASSERT_EQUALS("", errout.str());
}
void initvar_with_this() { void initvar_with_this() {
check("struct Fred\n" check("struct Fred\n"
"{\n" "{\n"

View File

@ -398,7 +398,6 @@ private:
TEST_CASE(cpp0xtemplate1); TEST_CASE(cpp0xtemplate1);
TEST_CASE(cpp0xtemplate2); TEST_CASE(cpp0xtemplate2);
TEST_CASE(cpp0xtemplate3); TEST_CASE(cpp0xtemplate3);
TEST_CASE(cpp0xdefault);
TEST_CASE(arraySize); TEST_CASE(arraySize);
@ -6314,48 +6313,6 @@ private:
tokenizeAndStringify(code)); tokenizeAndStringify(code));
} }
void cpp0xdefault() {
{
const char *code = "struct foo {"
" foo() = default;"
"}";
ASSERT_EQUALS("struct foo { }", tokenizeAndStringify(code));
}
{
const char *code = "struct A {"
" void operator delete (void *) = delete;"
" void operator delete[] (void *) = delete;"
"}";
ASSERT_EQUALS("struct A { }", tokenizeAndStringify(code));
}
{
const char *code = "struct A {"
" void operator = (void *) = delete;"
"}";
ASSERT_EQUALS("struct A { }", tokenizeAndStringify(code));
}
{
const char *code = "struct foo {"
" foo();"
"}"
"foo::foo() = delete;";
TODO_ASSERT_EQUALS("struct foo { }",
"struct foo { foo ( ) ; } foo :: foo ( ) = delete ;", tokenizeAndStringify(code));
}
//ticket #3448 (segmentation fault)
{
const char *code = "struct A {"
" void bar () = delete;"
"};"
"void baz () = delete;";
ASSERT_EQUALS("struct A { } ; void baz ( ) = delete ;", tokenizeAndStringify(code));
}
}
std::string arraySize_(const std::string &code) { std::string arraySize_(const std::string &code) {
errout.str(""); errout.str("");
Settings settings; Settings settings;