diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 42c0a2e6f..f3e4e7fd0 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1988,18 +1988,32 @@ void CheckClass::checkConst() // don't warn when returning non-const pointer/reference { - bool isPointerOrReference = false; - for (const Token *typeToken = func.retDef; typeToken; typeToken = typeToken->next()) { - if (Token::Match(typeToken, "(|{|;")) - break; - if (!isPointerOrReference && typeToken->str() == "const") - break; - if (Token::Match(typeToken, "*|&")) { - isPointerOrReference = true; - break; + auto isPointerOrReference = [this](const Token* start, const Token* end) -> bool { + bool inTemplArgList = false, isConstTemplArg = false; + for (const Token* tok = start; tok != end; tok = tok->next()) { + if (tok->str() == "{") // end of trailing return type + return false; + if (tok->str() == "<") { + if (!tok->link()) + mSymbolDatabase->debugMessage(tok, "debug", "CheckClass::checkConst found unlinked template argument list '" + tok->expressionString() + "'."); + inTemplArgList = true; + } + else if (tok->str() == ">") { + inTemplArgList = false; + isConstTemplArg = false; + } + else if (tok->str() == "const") { + if (!inTemplArgList) + return false; + isConstTemplArg = true; + } + else if (!isConstTemplArg && Token::Match(tok, "*|&")) + return true; } - } - if (isPointerOrReference) + return false; + }; + + if (isPointerOrReference(func.retDef, func.tokenDef)) continue; } diff --git a/test/testclass.cpp b/test/testclass.cpp index 11da78dc9..018dfaee1 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -193,7 +193,7 @@ private: TEST_CASE(const74); // ticket #10671 TEST_CASE(const75); // ticket #10065 TEST_CASE(const76); // ticket #10825 - TEST_CASE(const77); // ticket #10307 + TEST_CASE(const77); // ticket #10307, #10311 TEST_CASE(const78); // ticket #10315 TEST_CASE(const_handleDefaultParameters); TEST_CASE(const_passThisToMemberOfOtherClass); @@ -6033,13 +6033,19 @@ private: errout.str()); } - void const77() { // #10307 - checkConst("template \n" + void const77() { + checkConst("template \n" // #10307 "struct S {\n" " std::vector const* f() const { return p; }\n" " std::vector const* p;\n" "};\n"); ASSERT_EQUALS("", errout.str()); + + checkConst("struct S {\n" // #10311 + " std::vector v;\n" + " std::vector& f() { return v; }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void const78() { // #10315