Fixed #4388 (false positive 'noConstructor' in 1.57)
This commit is contained in:
parent
452dc23742
commit
c5ee083c82
|
@ -410,10 +410,6 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
if (end->next()->str() == "const")
|
||||
function.isConst = true;
|
||||
|
||||
// pure virtual function
|
||||
if (Token::Match(end, ") const| = %any%"))
|
||||
function.isPure = true;
|
||||
|
||||
// count the number of constructors
|
||||
if (function.type == Function::eConstructor ||
|
||||
function.type == Function::eCopyConstructor)
|
||||
|
@ -424,10 +420,35 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
function.arg = function.argDef;
|
||||
|
||||
// out of line function
|
||||
if (Token::Match(end, ") const| ;") ||
|
||||
Token::Match(end, ") const| = %any%")) {
|
||||
if (Token::Match(end, ") const| ;")) {
|
||||
// find the function implementation later
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
outerScope->isClassOrStruct()) && // or a ctor/dtor
|
||||
(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;
|
||||
*argStart = tok->next();
|
||||
return true;
|
||||
|
@ -1642,6 +1664,8 @@ void SymbolDatabase::printOut(const char *title) const
|
|||
std::cout << " isStatic: " << (func->isStatic ? "true" : "false") << std::endl;
|
||||
std::cout << " isFriend: " << (func->isFriend ? "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 << " retFuncPtr: " << (func->retFuncPtr ? "true" : "false") << std::endl;
|
||||
std::cout << " tokenDef: " << _tokenizer->list.fileLine(func->tokenDef) << std::endl;
|
||||
|
|
|
@ -390,6 +390,8 @@ public:
|
|||
isStatic(false),
|
||||
isFriend(false),
|
||||
isExplicit(false),
|
||||
isDefault(false),
|
||||
isDelete(false),
|
||||
isOperator(false),
|
||||
retFuncPtr(false) {
|
||||
}
|
||||
|
@ -427,6 +429,8 @@ public:
|
|||
bool isStatic; // is static
|
||||
bool isFriend; // is friend
|
||||
bool isExplicit; // is explicit
|
||||
bool isDefault; // is default
|
||||
bool isDelete; // is delete
|
||||
bool isOperator; // is operator
|
||||
bool retFuncPtr; // returns function pointer
|
||||
|
||||
|
|
|
@ -1745,8 +1745,6 @@ bool Tokenizer::tokenize(std::istream &code,
|
|||
return false;
|
||||
}
|
||||
|
||||
simplifyDefaultAndDeleteInsideClass();
|
||||
|
||||
// Remove __declspec()
|
||||
simplifyDeclspec();
|
||||
|
||||
|
@ -2196,47 +2194,6 @@ bool Tokenizer::hasComplicatedSyntaxErrorsInTemplates()
|
|||
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()
|
||||
{
|
||||
for (const Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
|
|
|
@ -62,6 +62,7 @@ private:
|
|||
TEST_CASE(simple7); // ticket #4531
|
||||
TEST_CASE(simple8);
|
||||
TEST_CASE(simple9); // ticket #4574
|
||||
TEST_CASE(simple10); // ticket #4388
|
||||
|
||||
TEST_CASE(initvar_with_this); // BUG 2190300
|
||||
TEST_CASE(initvar_if); // BUG 2190290
|
||||
|
@ -331,6 +332,16 @@ private:
|
|||
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() {
|
||||
check("struct Fred\n"
|
||||
"{\n"
|
||||
|
|
|
@ -398,7 +398,6 @@ private:
|
|||
TEST_CASE(cpp0xtemplate1);
|
||||
TEST_CASE(cpp0xtemplate2);
|
||||
TEST_CASE(cpp0xtemplate3);
|
||||
TEST_CASE(cpp0xdefault);
|
||||
|
||||
TEST_CASE(arraySize);
|
||||
|
||||
|
@ -6314,48 +6313,6 @@ private:
|
|||
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) {
|
||||
errout.str("");
|
||||
Settings settings;
|
||||
|
|
Loading…
Reference in New Issue