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")
|
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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue