Improved check: Complain about returning reference to literals or reference to calculation result (#4317)
This commit is contained in:
parent
35f644542e
commit
6635abbe55
|
@ -344,6 +344,9 @@ void CheckAutoVariables::returnReference()
|
||||||
// have we reached a function that returns a reference?
|
// have we reached a function that returns a reference?
|
||||||
if (tok->previous() && tok->previous()->str() == "&") {
|
if (tok->previous() && tok->previous()->str() == "&") {
|
||||||
for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
|
for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
|
||||||
|
if (tok2->str() != "return")
|
||||||
|
continue;
|
||||||
|
|
||||||
// return..
|
// return..
|
||||||
if (Token::Match(tok2, "return %var% ;")) {
|
if (Token::Match(tok2, "return %var% ;")) {
|
||||||
// is the returned variable a local variable?
|
// is the returned variable a local variable?
|
||||||
|
@ -374,6 +377,11 @@ void CheckAutoVariables::returnReference()
|
||||||
errorReturnTempReference(tok2);
|
errorReturnTempReference(tok2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return reference to a literal or the result of a calculation
|
||||||
|
else if (tok2->astOperand1() && (tok2->astOperand1()->isCalculation() || tok2->next()->isLiteral())) {
|
||||||
|
errorReturnTempReference(tok2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,8 @@ private:
|
||||||
TEST_CASE(returnReference5);
|
TEST_CASE(returnReference5);
|
||||||
TEST_CASE(returnReference6);
|
TEST_CASE(returnReference6);
|
||||||
TEST_CASE(returnReference7);
|
TEST_CASE(returnReference7);
|
||||||
|
TEST_CASE(returnReferenceLiteral);
|
||||||
|
TEST_CASE(returnReferenceCalculation);
|
||||||
|
|
||||||
// global namespace
|
// global namespace
|
||||||
TEST_CASE(testglobalnamespace);
|
TEST_CASE(testglobalnamespace);
|
||||||
|
@ -847,6 +849,45 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void returnReferenceLiteral() {
|
||||||
|
check("const std::string &a() {\n"
|
||||||
|
" return \"foo\";\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str());
|
||||||
|
|
||||||
|
check("const std::string a() {\n"
|
||||||
|
" return \"foo\";\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void returnReferenceCalculation() {
|
||||||
|
check("const std::string &a(const std::string& str) {\n"
|
||||||
|
" return \"foo\" + str;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str());
|
||||||
|
|
||||||
|
check("int& a(int b) {\n"
|
||||||
|
" return 2*(b+1);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str());
|
||||||
|
|
||||||
|
check("const std::string &a(const std::string& str) {\n"
|
||||||
|
" return str;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("const std::string &a(int bar) {\n"
|
||||||
|
" return foo(bar + 1);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("const std::string a(const std::string& str) {\n"
|
||||||
|
" return \"foo\" + str;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void testglobalnamespace() {
|
void testglobalnamespace() {
|
||||||
check("class SharedPtrHolder\n"
|
check("class SharedPtrHolder\n"
|
||||||
|
|
Loading…
Reference in New Issue