Fixed false negatives in checkautovariables.cpp:
- Detect returning temporary instances (#4076) - Added support for returning user defined types
This commit is contained in:
parent
00f6c635b8
commit
e05a597066
|
@ -238,22 +238,45 @@ bool CheckAutoVariables::returnTemporary(const Token *tok) const
|
|||
|
||||
std::list<Scope>::const_iterator scope;
|
||||
|
||||
bool func = false; // Might it be a function call?
|
||||
bool retref = false; // is there such a function that returns a reference?
|
||||
bool retvalue = false; // is there such a function that returns a value?
|
||||
|
||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
if (scope->type == Scope::eFunction) {
|
||||
if (scope->classDef->str() == funcname) {
|
||||
const Token *tok2 = scope->classDef;
|
||||
while (tok2 && Token::Match(tok2->tokAt(-2), "%type% ::"))
|
||||
tok2 = tok2->tokAt(-2);
|
||||
if (tok2 && Token::simpleMatch(tok2->tokAt(-3), "std :: string"))
|
||||
retvalue = true;
|
||||
else if (tok2 && Token::simpleMatch(tok2->tokAt(-4), "std :: string &"))
|
||||
retref = true;
|
||||
for (scope = symbolDatabase->scopeList.begin(); !retref && scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
if (scope->type == Scope::eFunction && scope->function->type != Function::eConstructor && scope->function->type != Function::eCopyConstructor) {
|
||||
if (scope->className == funcname) {
|
||||
retref = scope->classDef->strAt(-1) == "&";
|
||||
if (!retref) {
|
||||
const Token* start = scope->classDef;
|
||||
while (start->previous() && !Token::Match(start->previous(), ";|}|{|public:|private:|protected:")) {
|
||||
if ((start->str() == ")" || start->str() == ">") && start->link())
|
||||
start = start->link();
|
||||
start = start->previous();
|
||||
}
|
||||
if (start->str() == "const")
|
||||
start = start->next();
|
||||
if (start->str() == "::")
|
||||
start = start->next();
|
||||
|
||||
if (Token::simpleMatch(start, "std ::")) {
|
||||
if (start->strAt(3) != "<" || !Token::simpleMatch(start->linkAt(3), "> ::"))
|
||||
retvalue = true;
|
||||
else
|
||||
retref = true; // Assume that a reference is returned
|
||||
} else {
|
||||
if (symbolDatabase->isClassOrStruct(start->str()))
|
||||
retvalue = true;
|
||||
else
|
||||
retref = true;
|
||||
}
|
||||
|
||||
}
|
||||
func = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!func && symbolDatabase->isClassOrStruct(funcname))
|
||||
return true;
|
||||
|
||||
return bool(!retref && retvalue);
|
||||
}
|
||||
|
|
|
@ -445,6 +445,34 @@ private:
|
|||
" return hello();\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:8]: (error) Reference to temporary returned.\n", errout.str());
|
||||
|
||||
check("std::string hello() {\n"
|
||||
" return std::string();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"std::string &f() {\n"
|
||||
" return hello();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str());
|
||||
|
||||
check("class Foo;\n"
|
||||
"Foo hello() {\n"
|
||||
" return Foo();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"Foo& f() {\n"
|
||||
" return hello();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:7]: (error) Reference to temporary returned.\n", errout.str());
|
||||
|
||||
check("Foo hello() {\n"
|
||||
" return Foo();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"Foo& f() {\n" // Unknown type - might be a reference
|
||||
" return hello();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void returnReference2() {
|
||||
|
@ -504,6 +532,31 @@ private:
|
|||
" return hello();\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:11]: (error) Reference to temporary returned.\n", errout.str());
|
||||
|
||||
check("class Bar;\n"
|
||||
"Bar foo() {\n"
|
||||
" return something;\n"
|
||||
"}\n"
|
||||
"Bar& bar() {\n"
|
||||
" return foo();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:6]: (error) Reference to temporary returned.\n", errout.str());
|
||||
|
||||
check("std::map<int, string> foo() {\n"
|
||||
" return something;\n"
|
||||
"}\n"
|
||||
"std::map<int, string>& bar() {\n"
|
||||
" return foo();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (error) Reference to temporary returned.\n", errout.str());
|
||||
|
||||
check("Bar foo() {\n"
|
||||
" return something;\n"
|
||||
"}\n"
|
||||
"Bar& bar() {\n" // Unknown type - might be a typedef to a reference type
|
||||
" return foo();\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void returnReference3() {
|
||||
|
|
Loading…
Reference in New Issue