diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index 1e29ede5d..acfcb47f3 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -327,6 +327,34 @@ bool CheckAutoVariables::returnTemporary(const Token *tok) const //--------------------------------------------------------------------------- +static bool astHasAutoResult(const Token *tok) +{ + if (tok->astOperand1() && !astHasAutoResult(tok->astOperand1())) + return false; + if (tok->astOperand2() && !astHasAutoResult(tok->astOperand2())) + return false; + + if (tok->isOp()) + return true; + + if (tok->isLiteral()) + return true; + + if (tok->isName()) { + // TODO: check function calls, struct members, arrays, etc also + if (!tok->variable()) + return false; + if (tok->variable()->isStlType() && !Token::Match(tok->astParent(), "<<|>>")) + return true; + if (tok->variable()->isClass() || tok->variable()->isPointer() || tok->variable()->isReference()) // TODO: Properly handle pointers/references to classes in symbol database + return false; + + return true; + } + + return false; +} + void CheckAutoVariables::returnReference() { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); @@ -377,7 +405,7 @@ void CheckAutoVariables::returnReference() } // Return reference to a literal or the result of a calculation - else if (tok2->astOperand1() && (tok2->astOperand1()->isCalculation() || tok2->next()->isLiteral())) { + else if (tok2->astOperand1() && (tok2->astOperand1()->isCalculation() || tok2->next()->isLiteral()) && astHasAutoResult(tok2->astOperand1())) { errorReturnTempReference(tok2); } } diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 3ca844932..ec7e9b8a0 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -254,7 +254,7 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok) // Skip casts if (tok->str() == "(") { tok = tok->link(); - if(tok) + if (tok) tok = tok->next(); } diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index b5afa8141..02680967c 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -867,6 +867,16 @@ private: "}"); ASSERT_EQUALS("[test.cpp:2]: (error) Reference to temporary returned.\n", errout.str()); + check("std::ostream& operator<<(std::ostream& out, const std::string& path) {\n" + " return out << path;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("Unknown1& operator<<(Unknown1 out, Unknown2 path) {\n" + " return out << path;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + check("int& a(int b) {\n" " return 2*(b+1);\n" "}");