From 88e4794d6e3c5fa43a34147be03e3d58f0b4dd32 Mon Sep 17 00:00:00 2001 From: PKEuS Date: Wed, 1 Aug 2012 10:24:38 -0700 Subject: [PATCH] Refactorized CheckClass::checkConst: - Added checking for functions that can be even declared static (#1971. Removed fix for #1563) - Consistent usage of Function::TokenDef to avoid problems with scope identifiers - Rewrote parsing of function body making it more generic - Removed three redundant tests --- lib/checkclass.cpp | 238 ++++++++++++++++++++++----------------------- lib/checkclass.h | 9 +- test/testclass.cpp | 152 +++++++++++++---------------- 3 files changed, 185 insertions(+), 214 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index a6f0de833..3ae765d11 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1197,15 +1197,13 @@ void CheckClass::checkConst() for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { // does the function have a body? - if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isConst && !func->isVirtual) { + if (func->type == Function::eFunction && func->hasBody && !func->isFriend && !func->isStatic && !func->isVirtual) { // get last token of return type - const Token *previous = func->tokenDef->isName() ? func->token->previous() : func->token->tokAt(-2); - while (previous && previous->str() == "::") - previous = previous->tokAt(-2); + const Token *previous = func->tokenDef->previous(); // does the function return a pointer or reference? if (Token::Match(previous, "*|&")) { - const Token *temp = func->token->previous(); + const Token *temp = previous; while (!Token::Match(temp->previous(), ";|}|{|public:|protected:|private:")) temp = temp->previous(); @@ -1213,7 +1211,7 @@ void CheckClass::checkConst() if (temp->str() != "const") continue; } else if (Token::Match(previous->previous(), "*|& >")) { - const Token *temp = func->token->previous(); + const Token *temp = previous; while (!Token::Match(temp->previous(), ";|}|{|public:|protected:|private:")) { temp = temp->previous(); @@ -1223,27 +1221,15 @@ void CheckClass::checkConst() if (temp->str() != "const") continue; - } else if (func->isOperator && Token::Match(func->tokenDef->previous(), ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator - const std::string& opName = func->token->str(); + } else if (func->isOperator && Token::Match(previous, ";|{|}|public:|private:|protected:")) { // Operator without return type: conversion operator + const std::string& opName = func->tokenDef->str(); if (opName.compare(8, 5, "const") != 0 && opName[opName.size()-1] == '&') continue; } else { // don't warn for unknown types.. // LPVOID, HDC, etc - if (previous->isName()) { - bool allupper = true; - const std::string& s(previous->str()); - for (std::string::size_type pos = 0; pos < s.size(); ++pos) { - const char ch = s[pos]; - if (ch != '_' && !std::isupper(ch)) { - allupper = false; - break; - } - } - - if (allupper && s.size() > 2) - continue; - } + if (previous->isUpperCaseName() && previous->str().size() > 2 && !symbolDatabase->isClassOrStruct(previous->str())) + continue; } // check if base class function is virtual @@ -1252,8 +1238,9 @@ void CheckClass::checkConst() continue; } + bool memberAccessed = false; // if nothing non-const was found. write error.. - if (checkConstFunc(&(*scope), &*func)) { + if (checkConstFunc(&(*scope), &*func, memberAccessed)) { std::string classname = scope->className; const Scope *nest = scope->nestedIn; while (nest && nest->type != Scope::eGlobal) { @@ -1269,10 +1256,12 @@ void CheckClass::checkConst() else if (func->tokenDef->str() == "[") functionName += "]"; - if (func->isInline) - checkConstError(func->token, classname, functionName); - else // not inline - checkConstError2(func->token, func->tokenDef, classname, functionName); + if (!func->isConst || (!memberAccessed && !func->isOperator)) { + if (func->isInline) + checkConstError(func->token, classname, functionName, !memberAccessed && !func->isOperator); + else // not inline + checkConstError2(func->token, func->tokenDef, classname, functionName, !memberAccessed && !func->isOperator); + } } } } @@ -1309,7 +1298,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok) if (tok->varId() == 0) symbolDatabase->debugMessage(tok, "CheckClass::isMemberVar found used member variable \'" + tok->str() + "\' with varid 0"); - return !var->isMutable(); + return !var->isStatic(); } } @@ -1375,7 +1364,7 @@ bool CheckClass::isMemberFunc(const Scope *scope, const Token *tok) /** @todo we need to look at the argument types when there are overloaded functions * with the same number of arguments */ if (func->tokenDef->str() == tok->str() && (func->argCount() == args || (func->argCount() > args && countMinArgs(func->argDef) <= args))) { - return true; + return !func->isStatic; } } @@ -1437,138 +1426,139 @@ bool CheckClass::isConstMemberFunc(const Scope *scope, const Token *tok) return false; } -bool CheckClass::checkConstFunc(const Scope *scope, const Function *func) +bool CheckClass::checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed) { // if the function doesn't have any assignment nor function call, // it can be a const function.. for (const Token *tok1 = func->functionScope->classStart; tok1 && tok1 != func->functionScope->classEnd; tok1 = tok1->next()) { - // assignment.. = += |= .. - if (tok1->isAssignmentOp()) { - if (tok1->next()->str() == "this") { - return(false); - } else if (isMemberVar(scope, tok1->previous())) { + if (tok1->isName() && isMemberVar(scope, tok1)) { + memberAccessed = true; + const Variable* v = symbolDatabase->getVariableFromVarId(tok1->varId()); + if (v && v->isMutable()) + continue; + + if (tok1->str() == "this" && tok1->previous()->isAssignmentOp()) return(false); + + unsigned int lastVarId = tok1->varId(); + const Token* end = tok1; + for (;;) { + if (Token::Match(end->next(), ". %var%")) { + end = end->tokAt(2); + if (end->varId()) + lastVarId = end->varId(); + } else if (end->strAt(1) == "[") { + if (end->varId()) { + const Variable *var = symbolDatabase->getVariableFromVarId(end->varId()); + + if (var && Token::simpleMatch(var->typeStartToken(), "std :: map")) // operator[] changes a map + return(false); + } + end = end->linkAt(1); + } else if (end->strAt(1) == ")") + end = end->next(); + else + break; } + + if (end->strAt(1) == "(") { + const Variable *var = symbolDatabase->getVariableFromVarId(lastVarId); + if (!var) + return(false); + if (Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const + && (Token::Match(end, "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(end, "rfind|copy"))) + ; + else if (!var->type() || !isConstMemberFunc(var->type(), end)) + return(false); + } + + // Assignment + else if (end->next()->type() == Token::eAssignmentOp) + return(false); + + // Streaming + else if (end->strAt(1) == "<<" && tok1->strAt(-1) != "<<") + return(false); + else if (tok1->strAt(-1) == ">>") + return(false); + + // ++/-- + else if (end->next()->type() == Token::eIncDecOp || tok1->previous()->type() == Token::eIncDecOp) + return(false); + + + const Token* start = tok1; + while (tok1->strAt(-1) == ")") + tok1 = tok1->linkAt(-1); + + if (start->strAt(-1) == "delete") + return(false); + + tok1 = end; } // streaming: << - else if (tok1->str() == "<<" && isMemberVar(scope, tok1->previous()) && tok1->strAt(-2) != "<<") { - return(false); - } else if (Token::simpleMatch(tok1->previous(), ") <<") && - isMemberVar(scope, tok1->tokAt(-2))) { - return(false); - } - - // streaming: >> - else if (tok1->str() == ">>" && isMemberVar(scope, tok1->next())) { - return(false); - } - - // increment/decrement (member variable?).. - else if (tok1->type() == Token::eIncDecOp) { - // var++ and var-- - if (Token::Match(tok1->previous(), "%var%") && - tok1->previous()->str() != "return") { - if (isMemberVar(scope, tok1->previous())) { - return(false); - } - } - - // var[...]++ and var[...]-- - else if (tok1->previous()->str() == "]") { - if (isMemberVar(scope, tok1->previous()->link()->previous())) { - return(false); - } - } - - // ++var and --var - else if (Token::Match(tok1->next(), "%var%")) { - if (isMemberVar(scope, tok1->next())) { - return(false); - } - } - } - - // std::map variable member - else if (Token::Match(tok1, "%var% [") && isMemberVar(scope, tok1)) { - const Variable *var = symbolDatabase->getVariableFromVarId(tok1->varId()); - - if (var && (var->typeStartToken()->str() == "map" || - Token::simpleMatch(var->typeStartToken(), "std :: map"))) { + else if (Token::simpleMatch(tok1->previous(), ") <<") && + isMemberVar(scope, tok1->tokAt(-2))) { + const Variable* var = symbolDatabase->getVariableFromVarId(tok1->tokAt(-2)->varId()); + if (!var || !var->isMutable()) return(false); - } } + // function call.. else if (Token::Match(tok1, "%var% (") && !tok1->isStandardType() && !Token::Match(tok1, "return|if|string|switch|while|catch|for")) { - if (isMemberFunc(scope, tok1) && !isConstMemberFunc(scope, tok1) && tok1->strAt(-1) != ".") { - return(false); + if (isMemberFunc(scope, tok1) && tok1->strAt(-1) != ".") { + if (!isConstMemberFunc(scope, tok1)) + return(false); + memberAccessed = true; } // Member variable given as parameter for (const Token* tok2 = tok1->tokAt(2); tok2 && tok2 != tok1->next()->link(); tok2 = tok2->next()) { if (tok2->str() == "(") tok2 = tok2->link(); - else if (tok2->isName() && isMemberVar(scope, tok2)) - return(false); // TODO: Only bailout if function takes argument as non-const reference + else if (tok2->isName() && isMemberVar(scope, tok2)) { + const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId()); + if (!var || !var->isMutable()) + return(false); // TODO: Only bailout if function takes argument as non-const reference + } } } else if (Token::simpleMatch(tok1, "> (") && (!tok1->link() || !Token::Match(tok1->link()->previous(), "static_cast|const_cast|dynamic_cast|reinterpret_cast"))) { return(false); - } else if (Token::Match(tok1, "%var% . %var% (")) { - if (!isMemberVar(scope, tok1)) - tok1 = tok1->next(); - else if (tok1->varId()) { - const Variable *var = symbolDatabase->getVariableFromVarId(tok1->varId()); - - if (var && Token::simpleMatch(var->typeStartToken(), "std ::") // assume all std::*::size() and std::*::empty() are const - && (Token::Match(tok1->tokAt(2), "size|empty|cend|crend|cbegin|crbegin|max_size|length|count|capacity|get_allocator|c_str|str ( )") || Token::Match(tok1->tokAt(2), "rfind|copy"))) - tok1 = tok1->next(); - else if (var) { // Check if the function is const - const Scope* type = var->type(); - if (!type || !isConstMemberFunc(type, tok1->tokAt(2))) - return(false); - else - tok1 = tok1->next(); - } else - return(false); - } else - return(false); - } - - // delete.. - else if (tok1->str() == "delete") { - const Token* end = Token::findsimplematch(tok1->next(), ";")->previous(); - while (end->str() == ")") - end = end->previous(); - if (end->str() == "this") - return(false); - if (end->isName() && isMemberVar(scope, end)) - return(false); - } } return(true); } -void CheckClass::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname) +void CheckClass::checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic) { - checkConstError2(tok, 0, classname, funcname); + checkConstError2(tok, 0, classname, funcname, suggestStatic); } -void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname) +void CheckClass::checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic) { std::list toks; toks.push_back(tok1); if (tok2) toks.push_back(tok2); - reportError(toks, Severity::style, "functionConst", - "Technically the member function '" + classname + "::" + funcname + "' can be const.\n" - "The member function '" + classname + "::" + funcname + "' can be made a const " - "function. Making this function 'const' should not cause compiler errors. " - "Even though the function can be made const function technically it may not make " - "sense conceptually. Think about your design and the task of the function first - is " - "it a function that must not change object internal state?", true); + if (!suggestStatic) + reportError(toks, Severity::style, "functionConst", + "Technically the member function '" + classname + "::" + funcname + "' can be const.\n" + "The member function '" + classname + "::" + funcname + "' can be made a const " + "function. Making this function 'const' should not cause compiler errors. " + "Even though the function can be made const function technically it may not make " + "sense conceptually. Think about your design and the task of the function first - is " + "it a function that must not change object internal state?", true); + else + reportError(toks, Severity::performance, "functionStatic", + "Technically the member function '" + classname + "::" + funcname + "' can be static.\n" + "The member function '" + classname + "::" + funcname + "' can be made a static " + "function. Making a function static can bring a performance benefit since no 'this' instance is " + "passed to the function. This change should not cause compiler errors but it does not " + "necessarily make sense conceptually. Think about your design and the task of the function first - " + "is it a function that must not access members of class instances?", true); } //--------------------------------------------------------------------------- diff --git a/lib/checkclass.h b/lib/checkclass.h index 306a76f9a..8d323be47 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -123,8 +123,8 @@ private: void thisSubtractionError(const Token *tok); void operatorEqRetRefThisError(const Token *tok); void operatorEqToSelfError(const Token *tok); - void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname); - void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname); + void checkConstError(const Token *tok, const std::string &classname, const std::string &funcname, bool suggestStatic); + void checkConstError2(const Token *tok1, const Token *tok2, const std::string &classname, const std::string &funcname, bool suggestStatic); void initializerListError(const Token *tok1,const Token *tok2, const std::string & classname, const std::string &varname); void suggestInitializationList(const Token *tok, const std::string& varname); @@ -140,7 +140,8 @@ private: c.thisSubtractionError(0); c.operatorEqRetRefThisError(0); c.operatorEqToSelfError(0); - c.checkConstError(0, "class", "function"); + c.checkConstError(0, "class", "function", false); + c.checkConstError(0, "class", "function", true); c.initializerListError(0, 0, "class", "variable"); c.suggestInitializationList(0, "variable"); } @@ -176,7 +177,7 @@ private: bool isMemberVar(const Scope *scope, const Token *tok); bool isMemberFunc(const Scope *scope, const Token *tok); bool isConstMemberFunc(const Scope *scope, const Token *tok); - bool checkConstFunc(const Scope *scope, const Function *func); + bool checkConstFunc(const Scope *scope, const Function *func, bool& memberAccessed); // constructors helper function /** @brief Information about a member variable. Used when checking for uninitialized variables */ diff --git a/test/testclass.cpp b/test/testclass.cpp index 1ff5376f1..23e8d72e1 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -93,7 +93,7 @@ private: TEST_CASE(const15); TEST_CASE(const16); // ticket #1551 TEST_CASE(const17); // ticket #1552 - TEST_CASE(const18); // ticket #1563 + TEST_CASE(const18); TEST_CASE(const19); // ticket #1612 TEST_CASE(const20); // ticket #1602 TEST_CASE(const21); // ticket #1683 @@ -2075,13 +2075,13 @@ private: checkConst("class Fred {\n" " const std::string foo() { return ""; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str()); checkConst("class Fred {\n" " std::string s;\n" " const std::string & foo() { return ""; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str()); // constructors can't be const.. checkConst("class Fred {\n" @@ -2120,7 +2120,7 @@ private: " int x;\n" " void b() { a(); }\n" "};"); - ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::b' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::b' can be static.\n", errout.str()); // static functions can't be const.. checkConst("class foo\n" @@ -2134,7 +2134,7 @@ private: checkConst("class Fred {\n" " const std::string foo() const throw() { return ""; }\n" "};\n"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str()); } void const2() { @@ -2241,35 +2241,12 @@ private: "int Fred::getA() { return a; }"); ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::getA' can be const.\n", errout.str()); - checkConst("class Fred {\n" - " const std::string foo();\n" - "};\n" - "const std::string Fred::foo() { return ""; }"); - ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str()); - checkConst("class Fred {\n" " std::string s;\n" " const std::string & foo();\n" "};\n" "const std::string & Fred::foo() { return ""; }"); - ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str()); - - // constructors can't be const.. - checkConst("class Fred {\n" - " int a;\n" - "public:\n" - " Fred()\n" - "};\n" - "Fred::Fred() { }"); - ASSERT_EQUALS("", errout.str()); - - // assignment through |=.. - checkConst("class Fred {\n" - " int a;\n" - " int setA();\n" - "};\n" - "int Fred::setA() { a |= true; }"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str()); // functions with a function call to a non-const member can't be const.. (#1305) checkConst("class Fred\n" @@ -2405,7 +2382,7 @@ private: "void Fred::foo() { }" "void Fred::foo(std::string & a) { a = s; }" "void Fred::foo(const std::string & a) { s = a; }"); - ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n" + ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n" "[test.cpp:7] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str()); // check functions with different or missing parameter names @@ -2422,11 +2399,11 @@ private: "void Fred::foo3(int a, int b) { }\n" "void Fred::foo4(int a, int b) { }\n" "void Fred::foo5(int, int) { }"); - ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::foo1' can be const.\n" - "[test.cpp:10] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo2' can be const.\n" - "[test.cpp:11] -> [test.cpp:5]: (style, inconclusive) Technically the member function 'Fred::foo3' can be const.\n" - "[test.cpp:12] -> [test.cpp:6]: (style, inconclusive) Technically the member function 'Fred::foo4' can be const.\n" - "[test.cpp:13] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::foo5' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::foo1' can be static.\n" + "[test.cpp:10] -> [test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::foo2' can be static.\n" + "[test.cpp:11] -> [test.cpp:5]: (performance, inconclusive) Technically the member function 'Fred::foo3' can be static.\n" + "[test.cpp:12] -> [test.cpp:6]: (performance, inconclusive) Technically the member function 'Fred::foo4' can be static.\n" + "[test.cpp:13] -> [test.cpp:7]: (performance, inconclusive) Technically the member function 'Fred::foo5' can be static.\n", errout.str()); // check nested classes checkConst("class Fred {\n" @@ -2622,7 +2599,7 @@ private: } void const6() { - // ticket # 1491 + // ticket #1491 checkConst("class foo {\n" "public:\n" "};\n" @@ -2634,7 +2611,7 @@ private: "public:\n" " void foo() { }\n" "};"); - ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'Fred::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::foo' can be static.\n", errout.str()); checkConst("struct fast_string\n" "{\n" @@ -3197,13 +3174,12 @@ private: } void const18() { - // ticket #1563 checkConst("class Fred {\n" "static int x;\n" "public:\n" " void set(int i) { x = i; }\n" "};\n"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Fred::set' can be static.\n", errout.str()); } void const19() { @@ -3451,7 +3427,7 @@ private: " UnknownScope::x = x_;\n" " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4]: (style, inconclusive) Technically the member function 'AA::vSetXPos' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'AA::vSetXPos' can be static.\n", errout.str()); } @@ -3880,7 +3856,7 @@ private: "{\n" "}\n"); - ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (style, inconclusive) Technically the member function 'Fred::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:5]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n", errout.str()); checkConst("class Fred\n" "{\n" @@ -3894,7 +3870,7 @@ private: "{\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (style, inconclusive) Technically the member function 'Fred::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:7]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n", errout.str()); checkConst("namespace NS {\n" " class Fred\n" @@ -3910,7 +3886,7 @@ private: " }\n" "}\n"); - ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:8]: (style, inconclusive) Technically the member function 'NS::Fred::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static.\n", errout.str()); checkConst("namespace NS {\n" " class Fred\n" @@ -3926,7 +3902,7 @@ private: "{\n" "}\n"); - ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (style, inconclusive) Technically the member function 'NS::Fred::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'NS::Fred::f' can be static.\n", errout.str()); checkConst("class Foo {\n" " class Fred\n" @@ -3942,7 +3918,7 @@ private: "{\n" "}\n"); - ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (style, inconclusive) Technically the member function 'Foo::Fred::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:11] -> [test.cpp:8]: (performance, inconclusive) Technically the member function 'Foo::Fred::f' can be static.\n", errout.str()); } void const43() { // ticket 2377 @@ -4031,7 +4007,7 @@ private: " };\n" "}\n"); - ASSERT_EQUALS("[test.cpp:8]: (style, inconclusive) Technically the member function 'tools::WorkspaceControl::toGrid' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:8]: (performance, inconclusive) Technically the member function 'tools::WorkspaceControl::toGrid' can be static.\n", errout.str()); } void const46() { // ticket 2663 @@ -4046,8 +4022,8 @@ private: " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Altren::fun1' can be const.\n" - "[test.cpp:7]: (style, inconclusive) Technically the member function 'Altren::fun2' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Altren::fun1' can be static.\n" + "[test.cpp:7]: (performance, inconclusive) Technically the member function 'Altren::fun2' can be static.\n", errout.str()); } void const47() { // ticket 2670 @@ -4058,7 +4034,7 @@ private: " void bar() { foo(); }\n" "};\n"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static.\n", errout.str()); checkConst("class Altren {\n" "public:\n" @@ -4067,7 +4043,8 @@ private: " void bar() { foo(1); }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:5]: (style, inconclusive) Technically the member function 'Altren::bar' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (performance, inconclusive) Technically the member function 'Altren::foo' can be static.\n" + "[test.cpp:5]: (style, inconclusive) Technically the member function 'Altren::bar' can be const.\n", errout.str()); } void const48() { // ticket 2672 @@ -4157,7 +4134,7 @@ private: "private:\n" " int bar;\n" "};"); - ASSERT_EQUALS("", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'foo::DoSomething' can be static.\n", errout.str()); } void const53() { // ticket 3049 @@ -4201,7 +4178,7 @@ private: " switch (x) { }\n" " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str()); checkConst("class A\n" "{\n" @@ -4244,7 +4221,7 @@ private: "\n" " return RET_NOK;\n" "}\n"); - ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (style, inconclusive) Technically the member function 'A::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:9] -> [test.cpp:4]: (performance, inconclusive) Technically the member function 'A::f' can be static.\n", errout.str()); checkConst("class MyObject {\n" "public:\n" @@ -4252,7 +4229,7 @@ private: " for (int i = 0; i < 5; i++) { }\n" " }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str()); } void const57() { // tickets #2669 and #2477 @@ -4277,7 +4254,8 @@ private: "private:\n" " MyGUI::IntCoord mCoordValue;\n" "};\n"); - ASSERT_EQUALS("[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:7]: (performance, inconclusive) Technically the member function 'MyGUI::types::TCoord::size' can be static.\n" + "[test.cpp:15]: (style, inconclusive) Technically the member function 'SelectorControl::getSize' can be const.\n", errout.str()); checkConst("struct Foo {\n" " Bar b;\n" @@ -4308,7 +4286,8 @@ private: " b.run();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:6]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Bar::run' can be static.\n" + "[test.cpp:6]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str()); } void const58() { @@ -4317,14 +4296,14 @@ private: " f.clear();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str()); checkConst("struct MyObject {\n" " int foo(Foo f) {\n" " return f.length();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'MyObject::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MyObject::foo' can be static.\n", errout.str()); checkConst("struct MyObject {\n" " Foo f;\n" @@ -4373,8 +4352,8 @@ private: " return foo3();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:11]: (style, inconclusive) Technically the member function 'Foo::bar3' can be const.\n" - "[test.cpp:14]: (style, inconclusive) Technically the member function 'Foo::bar4' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:11]: (performance, inconclusive) Technically the member function 'Foo::bar3' can be static.\n" + "[test.cpp:14]: (performance, inconclusive) Technically the member function 'Foo::bar4' can be static.\n", errout.str()); } void const_passThisToMemberOfOtherClass() { @@ -4392,7 +4371,7 @@ private: " f.foo();\n" " }\n" "};"); - ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Technically the member function 'Foo::foo' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Foo::foo' can be static.\n", errout.str()); } void assigningPointerToPointerIsNotAConstOperation() { @@ -4451,25 +4430,25 @@ private: "class Fred {\n" " void nextA() { return ++a; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return --a; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a++; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a--; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); } void constassign1() { @@ -4507,31 +4486,31 @@ private: "class Fred {\n" " void nextA() { return a=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a-=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a+=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a*=-1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a;\n" "class Fred {\n" " void nextA() { return a/=-2; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); } void constassign2() { @@ -4563,31 +4542,31 @@ private: "class Fred {\n" " void nextA() { return s.a=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a-=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a+=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a*=-1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("struct A { int a; } s;\n" "class Fred {\n" " void nextA() { return s.a/=-2; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("struct A { int a; };\n" "class Fred {\n" @@ -4655,25 +4634,25 @@ private: "class Fred {\n" " void nextA() { return ++a[0]; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return --a[0]; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]++; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]--; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); } void constassignarray() { @@ -4711,31 +4690,31 @@ private: "class Fred {\n" " void nextA() { return a[0]=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]-=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]+=1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]*=-1; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); checkConst("int a[2];\n" "class Fred {\n" " void nextA() { return a[0]/=-2; }\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::nextA' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'Fred::nextA' can be static.\n", errout.str()); } // return pointer/reference => not const @@ -4777,7 +4756,8 @@ private: " void f() const { };\n" " void a() { f(); };\n" "};\n"); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::a' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'Fred::f' can be static.\n" + "[test.cpp:3]: (style, inconclusive) Technically the member function 'Fred::a' can be const.\n", errout.str()); // ticket #1593 checkConst("class A\n" @@ -5040,7 +5020,7 @@ private: settings.addEnabled("style"); checkConst(code, &settings, true); - ASSERT_EQUALS("[test.cpp:3]: (style, inconclusive) Technically the member function 'foo::f' can be const.\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Technically the member function 'foo::f' can be static.\n", errout.str()); checkConst(code, &settings, false); // TODO: Set inconclusive to true (preprocess it) ASSERT_EQUALS("", errout.str());