diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index eda8afce8..6b4eb7da9 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1559,6 +1559,10 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co for (; tok && tok != last; tok = tok->next()) { // check for return of reference to this + + if (const Token* lScope = isLambdaCaptureList(tok)) // skip lambda + tok = lScope->link(); + if (tok->str() != "return") continue; diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 5ce277233..9a8b8dd7e 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -2446,7 +2446,7 @@ void CheckOther::checkDuplicateExpression() } } ErrorPath errorPath; - if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=")) { + if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|*|<<|>>|+=|*=|<<=|>>=") && !isLambdaCaptureList(tok->astParent())) { if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1(), true)) continue; const bool pointerDereference = (tok->astOperand1() && tok->astOperand1()->isUnaryOp("*")) || diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index a0fbb7395..f2182c0c1 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -1385,25 +1385,25 @@ static void compileExpression(Token *&tok, AST_state& state) compileComma(tok, state); } -static bool isLambdaCaptureList(const Token * tok) +const Token* isLambdaCaptureList(const Token * tok) { // a lambda expression '[x](y){}' is compiled as: // [ // `-( <<-- optional // `-{ // see compilePrecedence2 - if (tok->str() != "[") - return false; + if (!Token::simpleMatch(tok, "[")) + return nullptr; if (!Token::Match(tok->link(), "] (|{")) - return false; + return nullptr; if (Token::simpleMatch(tok->astOperand1(), "{") && tok->astOperand1() == tok->link()->next()) - return true; + return tok->astOperand1(); if (!tok->astOperand1() || tok->astOperand1()->str() != "(") - return false; + return nullptr; const Token * params = tok->astOperand1(); - if (!params->astOperand1() || params->astOperand1()->str() != "{") - return false; - return true; + if (!Token::simpleMatch(params->astOperand1(), "{")) + return nullptr; + return params->astOperand1(); } // Compile inner expressions inside inner ({..}) and lambda bodies diff --git a/lib/tokenlist.h b/lib/tokenlist.h index 3ea24c66a..cc3fc10cf 100644 --- a/lib/tokenlist.h +++ b/lib/tokenlist.h @@ -221,5 +221,7 @@ private: /// @} +const Token* isLambdaCaptureList(const Token* tok); + //--------------------------------------------------------------------------- #endif // tokenlistH diff --git a/test/testclass.cpp b/test/testclass.cpp index 6967e685a..cbdd47bb3 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -1321,6 +1321,16 @@ private: "};\n" "A::B & A::B::operator=(const A::B & b) { return b; }"); ASSERT_EQUALS("[test.cpp:8]: (style) 'operator=' should return reference to 'this' instance.\n", errout.str()); + + checkOpertorEqRetRefThis( // #11380 + "struct S {\n" + " S& operator=(const S& other) {\n" + " i = []() { return 42; }();\n" + " return *this;\n" + " }\n" + " int i;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void operatorEqRetRefThis2() { diff --git a/test/testother.cpp b/test/testother.cpp index 2808df4c1..071b9a08f 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -4850,6 +4850,14 @@ private: " }\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + check("struct S {\n" // #11383 + " void f() {\n" + " auto l2 = [i = i]() { return i; };\n" + " }\n" + " int i;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void trac1132() {