diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 287634bd3..1f683b2bb 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -344,6 +344,9 @@ void CheckAutoVariables::returnReference() // have we reached a function that returns a reference? if (tok->previous() && tok->previous()->str() == "&") { for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) { + if (tok2->str() != "return") + continue; + // return.. if (Token::Match(tok2, "return %var% ;")) { // is the returned variable a local variable? @@ -374,6 +377,11 @@ void CheckAutoVariables::returnReference() 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); + } } } } diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 76aa01a37..b5afa8141 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -104,6 +104,8 @@ private: TEST_CASE(returnReference5); TEST_CASE(returnReference6); TEST_CASE(returnReference7); + TEST_CASE(returnReferenceLiteral); + TEST_CASE(returnReferenceCalculation); // global namespace TEST_CASE(testglobalnamespace); @@ -847,6 +849,45 @@ private: 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() { check("class SharedPtrHolder\n"