diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 7300b8e29..6f4b4ea43 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1788,28 +1788,29 @@ void CheckClass::checkConst() // don't warn for friend/static/virtual functions if (func.isFriend() || func.isStatic() || func.hasVirtualSpecifier()) continue; - // get last token of return type - const Token *previous = func.tokenDef->previous(); - // does the function return a pointer or reference? - if (Token::Match(previous, "*|&")) { - if (func.retDef->str() != "const") - continue; - } else if (Token::Match(previous->previous(), "*|& >")) { - const Token *temp = previous->previous(); - - bool foundConst = false; - while (!Token::Match(temp->previous(), ";|}|{|public:|protected:|private:")) { - temp = temp->previous(); - if (temp->str() == "const") { - foundConst = true; + // is non-const pointer/reference returned? + { + bool isConst = false; + bool isPointerOrReference = false; + for (const Token *typeToken = func.retDef; typeToken; typeToken = typeToken->next()) { + if (Token::Match(typeToken, "(|{|;")) + break; + if (!isPointerOrReference && typeToken->str() == "const") { + isConst = true; + break; + } + if (Token::Match(typeToken, "*|&")) { + isPointerOrReference = true; break; } } - - if (!foundConst) + if (isPointerOrReference) continue; - } else if (func.isOperator() && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator + } + + + if (func.isOperator()) { // Operator without return type: conversion operator const std::string& opName = func.tokenDef->str(); if (opName.compare(8, 5, "const") != 0 && (endsWith(opName,'&') || endsWith(opName,'*'))) continue; @@ -1819,7 +1820,7 @@ void CheckClass::checkConst() } else { // don't warn for unknown types.. // LPVOID, HDC, etc - if (previous->str().size() > 2 && !previous->type() && previous->isUpperCaseName()) + if (func.retDef->str().size() > 2 && !func.retDef->type() && func.retDef->isUpperCaseName()) continue; } diff --git a/test/testclass.cpp b/test/testclass.cpp index a5db98b02..803d74c8c 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -198,6 +198,7 @@ private: TEST_CASE(constRangeBasedFor); // #5514 TEST_CASE(const_shared_ptr); TEST_CASE(constPtrToConstPtr); + TEST_CASE(constTrailingReturnType); TEST_CASE(initializerListOrder); TEST_CASE(initializerListUsage); @@ -6314,6 +6315,14 @@ private: ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::getData' can be const.\n", errout.str()); } + void constTrailingReturnType() { // #9814 + checkConst("struct A {\n" + " int x = 1;\n" + " auto get() -> int & { return x; }\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } + void checkInitializerListOrder(const char code[]) { // Clear the error log errout.str("");