diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 5dd6075d1..5ce277233 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2120,16 +2120,24 @@ void CheckOther::checkMisusedScopedObject() misusedScopeObjectError(ctorTok, typeStr); tok = tok->next(); } + if (tok->isAssignmentOp() && Token::simpleMatch(tok->astOperand1(), "(") && tok->astOperand1()->astOperand1()) { + if (const Function* ftok = tok->astOperand1()->astOperand1()->function()) { + if (ftok->retType && Token::Match(ftok->retType->classDef, "class|struct|union") && !Function::returnsReference(ftok)) + misusedScopeObjectError(tok->next(), ftok->retType->name(), /*isAssignment*/ true); + } + } } } } -void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& varname) +void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& varname, bool isAssignment) { + std::string msg = "Instance of '$symbol' object is destroyed immediately"; + msg += isAssignment ? ", assignment has no effect." : "."; reportError(tok, Severity::style, "unusedScopedObject", - "$symbol:" + varname + "\n" - "Instance of '$symbol' object is destroyed immediately.", CWE563, Certainty::normal); + "$symbol:" + varname + "\n" + + msg, CWE563, Certainty::normal); } static const Token * getSingleExpressionInBlock(const Token * tok) diff --git a/lib/checkother.h b/lib/checkother.h index b95f36c8b..84073ae72 100644 --- a/lib/checkother.h +++ b/lib/checkother.h @@ -251,7 +251,7 @@ private: void redundantBitwiseOperationInSwitchError(const Token *tok, const std::string &varname); void suspiciousCaseInSwitchError(const Token* tok, const std::string& operatorString); void selfAssignmentError(const Token *tok, const std::string &varname); - void misusedScopeObjectError(const Token *tok, const std::string &varname); + void misusedScopeObjectError(const Token *tok, const std::string &varname, bool isAssignment = false); void duplicateBranchError(const Token *tok1, const Token *tok2, ErrorPath errors); void duplicateAssignExpressionError(const Token *tok1, const Token *tok2, bool inconclusive); void oppositeExpressionError(const Token *opTok, ErrorPath errors); diff --git a/test/testother.cpp b/test/testother.cpp index 8f62e3076..2808df4c1 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -140,6 +140,7 @@ private: TEST_CASE(testMisusedScopeObjectInConstructor); TEST_CASE(testMisusedScopeObjectStandardType); TEST_CASE(testMisusedScopeObjectNamespace); + TEST_CASE(testMisusedScopeObjectAssignment); // #11371 TEST_CASE(trac2071); TEST_CASE(trac2084); TEST_CASE(trac3693); @@ -5136,6 +5137,19 @@ private: errout.str()); } + void testMisusedScopeObjectAssignment() { // #11371 + check("struct S;\n" + "S f();\n" + "S& g();\n" + "S&& h();\n" + "S* i();\n" + "void t0() { f() = {}; }\n" + "void t1() { g() = {}; }\n" + "void t2() { h() = {}; }\n" + "void t3() { *i() = {}; }\n", "test.cpp"); + ASSERT_EQUALS("[test.cpp:6]: (style) Instance of 'S' object is destroyed immediately, assignment has no effect.\n", errout.str()); + } + void trac2084() { check("void f()\n" "{\n"